Bash scripting
Guidelines for writing production-quality bash scripts. Use whenever asked to write a bash script.From its SKILL.md
npx -y skills add thomd/coding-agent-skills --skill bash-scriptingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
5.4 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
<cli_design_principles>
Human-Friendly Design
- Provide
--helpand-hflags; show usage on invalid input - Use full words for long flags (
--outputnot--outp) - Confirm destructive actions unless
--forceis passed - Show progress for long operations; support
--quietand--verbose
Composability
- Write output to stdout by default but support
--output <file> - Write errors and diagnostics to stderr only
- Accept stdin when
-is given as filename - Produce one record per line for pipeline friendly text output
- Offer
--jsonfor machine-parseable output when appropriate
Exit Codes
0= success1= general error2= invalid usage
Error Messages
- Format:
scriptname: error: what went wrong - Include what happened and how to fix it
- Suggest
--helpon invalid usage
Debugging
- Add support for debuggin output if appropriate when a environment variable
DEBUG=1is set.
Robustness
- Validate arguments before doing any work
- Fail fast—don't partially complete then error
- Clean up temp files on exit (use trap)
Usage Help
Put CLI help as comments at the top of the script following this template:
#!/usr/bin/env bash
#
# What is the script doing?
#
# USAGE
#
# COMMAND SUB_SOMMAND --OPTION # help text for this command
#
# COMMANDS
#
# SUB_COMMAND_1 # COMMAND_1 does this
# SUB_COMMAND_2 # COMMAND_2 does that
#
# OPTIONS
#
# -a OPRION_A # OPTION_A does this
# -b OPRION_B # OPTION_B does that
#
# EXAMPLES
#
# COMMAND -a OPTION # This does this
#
set -euo pipefail
show_help() {
# shellcheck disable=SC2086
awk '/^[^ #]/{c=1}c==0{print $0}' $0 | sed -n '/^#/p' | sed 1d | sed 's/^#/ /g' |
perl -pe "s/ #(.*)$/$(tput setaf 0)\1$(tput sgr 0)/" |
perl -pe "s/(USAGE|EXAMPLES|COMMANDS|OPTIONS)/$(tput setaf 0)\1$(tput sgr 0)/" |
perl -pe "s/\`(.+)\`/$(tput sgr 0 1)\1$(tput sgr 0)/"
exit 1
}
show_help
</cli_design_principles>
Be idempotent where possible (safe to run twice).
On commands which are changing data or critical, ask for confirmation from the command user using this script
yesno() {
echo ""
read -r -p " $1 [Y/n] " response
[[ $response == "n" || $response == "N" ]] && exit 1
}
yesno "are you sure to do this?"
<bash_coding_standards>
Script Header
Always start with:
#!/usr/bin/env bash
set -euo pipefail
Variables
- Lowercase for local:
local filename - UPPERCASE for exported/constants:
readonly VERSION="1.0.0" - Always quote:
"$var"not$var - Defaults:
${var:-default}, required:${var:?error message}
Conditionals
- Use
[[ ]]not[ ] - Use
(( ))for arithmetic - Check command existence:
command -v git &>/dev/null
Functions
- Use
localfor all variables - Keep functions short and single-purpose
- Return status with
return, output withecho
Color Codes
Use ANSI color codes; auto-disabled when stdout isn't a TTY (e.g. piped to a logfile, run in CI)
BOLD=$'\e[1m'; BLUE=$'\e[34m'; GREEN=$'\e[32m'; RED=$'\e[31m'; DIM=$'\e[2m'; RESET=$'\e[0m'
[[ -t 1 ]] || { BOLD=; BLUE=; GREEN=; RED=; DIM=; RESET=; }
Error Handling & Cleanup
info() { printf '%s●%s %s%s%s\n' "$BLUE" "$RESET" "$BOLD" "$*" "$RESET"; }
ok() { printf '%s✓%s %s\n' "$GREEN" "$RESET" "$*"; }
err() { printf '%s✗%s %s\n' "$RED" "$RESET" "$*" >&2; }
# `trap - ERR` disarms the ERR trap below so the explicit `exit 1` doesn't double-report.
die() { err "$*"; trap - ERR; exit 1; }
trap 'err "script failed at line $LINENO"' ERR
Argument Parsing Pattern
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) usage; exit 0 ;;
-o|--output) output="$2"; shift 2 ;;
--) shift; break ;;
-*) die "unknown option: $1" ;;
*) break ;;
esac
done
Safe Iteration
# Over lines (handles whitespace)
while IFS= read -r line; do ...; done < "$file"
# Over globs (handles missing matches)
for f in *.txt; do [[ -e "$f" ]] || continue; ...; done
</bash_coding_standards>
<validation>Always run shellcheck cli for static code analysis and lint tool
Usage
shellcheck -s bash script.sh
Accept disabled shellcheck rules
Add at top of file to disable rules in a file:
#!/usr/bin/env bash
# shellcheck disable=SC2003,SC2219
add at a specific line to disable line:
hexToAscii() {
# shellcheck disable=SC2059
printf "\x$1"
}
</validation>
Bash Completion Scripts
Bash completion scripts resides in a subfolder bash_completion.d within the project. A Makefile installs the bash completion scripts alongside the script
itself into $(HOME)/etc/bash_completion.d.
Simple example:
#!/usr/bin/env bash
_name-of-script_completions() {
local cur prev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
COMPREPLY=($(compgen -W "-h -a -b -c" -- ${cur}))
}
complete -F _name-of-script_completions name-of-script
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.