Claude-skill-registry coding-shell-scripts
Guidelines and patterns for writing bash/shell scripts. Use when creating new shell scripts, bin scripts, or bash utilities. Includes script templates, header comments, error handling, and common patterns.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/coding-shell-scripts" ~/.claude/skills/majiayu000-claude-skill-registry-coding-shell-scripts && rm -rf "$T"
skills/data/coding-shell-scripts/SKILL.mdCoding Shell Scripts
Overview
This skill provides templates and patterns for writing bash scripts. Choose the appropriate template based on your needs:
- Simple Script Structure: For straightforward utilities and single-purpose tools
- Full Script Template: For complex scripts needing logging, cleanup handlers, and robust error handling
Simple Script Structure
For straightforward scripts (utilities, single-purpose tools):
#!/usr/bin/env bash main() { # Script logic here local arg="$1" if [ -z "$arg" ]; then echo "Usage: $(basename "$0") <argument>" >&2 exit 1 fi # Do the work echo "Processing: $arg" } main "$@"
Important: Standalone scripts MUST use
exit (not return) for error codes, since they run in their own process.
Full Script Template
For more complex scripts with logging, cleanup, and robust error handling:
#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' # Normalize TMPDIR (strip trailing slash for consistent path construction) TMPDIR="${TMPDIR:-/tmp}" TMPDIR="${TMPDIR%/}" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" #/ Usage: #/ Description: #/ Examples: #/ Options: #/ --help: Display this help message usage() { grep '^#/' "$0" | cut -c4- ; exit 0 ; } expr "$*" : ".*--help" > /dev/null && usage readonly LOG_FILE="${TMPDIR}/$(basename "$0").log" _print() { case "$1" in black) color="30" ;; red) color="31" ;; green) color="32" ;; yellow) color="33" ;; blue) color="34" ;; magenta) color="35" ;; cyan) color="36" ;; white) color="37" ;; *) echo "Unknown color: $1" >&2; return 1 ;; esac shift while [ "$#" -gt 1 ]; do case "$1" in bold) color="${color};1" ;; dim) color="${color};2" ;; *) echo "Unknown option: $1" >&2; return 1 ;; esac shift done supported_colors=$(tput colors 2>/dev/null || echo 0) if [ -n "$supported_colors" ] && [ "$supported_colors" -gt 8 ]; then printf "\\033[${color}m%b\\033[0m\\n" "$1" else printf "%b\n" "$1" fi } info() { _print cyan "info $@" | tee -a "$LOG_FILE" >&2 ; } warning() { _print yellow "warning $@" | tee -a "$LOG_FILE" >&2 ; } error() { _print red "error $@" | tee -a "$LOG_FILE" >&2 ; } fatal() { _print red bold "fatal $@" | tee -a "$LOG_FILE" >&2 ; exit 1 ; } cleanup() { # Remove temporary files # Restart services # ... } if [[ "${BASH_SOURCE[0]}" = "$0" ]]; then trap cleanup EXIT # Script goes here # ... fi
Script Validation
CRITICAL: Always validate shell scripts after creating or editing them.
Required Validation Steps
After creating or editing any shell script, you MUST run both validation tools:
-
Syntax Check with bash -n
bash -n script.shCatches basic syntax errors:
- Missing closing quotes
- Unmatched brackets or braces
- Invalid command syntax
-
Static Analysis with shellcheck
shellcheck script.shCatches deeper issues:
- Quoting problems (word splitting, glob expansion)
- Deprecated or unsafe syntax
- Common bugs and anti-patterns
- Unused or misspelled variables
- Portability issues
Validation Pattern
Run both checks together:
bash -n script.sh && shellcheck script.sh
Only consider the script complete after both tools pass without errors.
Handling Shellcheck Warnings
When shellcheck warnings are intentional, disable them with directives:
# Disable specific warning for one line # shellcheck disable=SC2086 echo $unquoted_on_purpose # Disable multiple codes for entire file (at top) # shellcheck disable=SC2086,SC2181 # Document why you're disabling # We want word splitting here for argument passing # shellcheck disable=SC2086 command $args
Common codes you might need to disable:
: Word splitting/globbing (when intentional for argument passing)SC2086
: TestingSC2181
explicitly (when needed for clarity)$?
: Dynamic source paths (shellcheck can't follow them)SC1090
: Unused variables (e.g., when reading into multiple vars)SC2034
Important: Only disable shellcheck warnings when you understand why they're triggered and have a valid reason to ignore them. Document your reasoning in comments.
Bash Constructs
for
for i in ( ls some-directory ); do echo $i done SomeArray=("foo" "bar" "baz") for item in ${SomeArray[*]}; do echo $item done
case
case "$variable" in abc) echo "\$variable = abc" ;; xyz) echo "\$variable = xyz" ;; esac
ln
ln -s <real_file> <future_link>
select
select result in Yes No Cancel do echo $result done
tput
tput cuu1 # Move cursor up by one line tput el # Clear the line
Common Patterns
Ternary expressions
<expression> && <on-true expression> || <on-false expression> # See below example for file/stdin to variable.
File or stdin assignment
Assign either a file or stdin (piped input) to a variable, with fallbacks:
# Use a filepath from args when available, or use stdin [ $# -ge 1 -a -f "$1" ] && input="$1" || input="-" content=$(cat $input) # Use stdin if pipe is occupied, otherwise use a file (test -s /dev/stdin) && input="-" || input="./config.json" content=(cat $input)
Arithmetic Operations
Use
(()) for arithmetic:
echo $(( 5 - 1 ))
CLI Arguments
More involved: https://medium.com/@Drew_Stokes/bash-argument-parsing-54f3b81a6a8f
# Simple double dash arg arg_no_bump="false" expr "$*" : ".*--no-bump" > /dev/null && arg_no_bump="true"
Reference Links
http://tldp.org/LDP/abs/html/index.html
https://stackoverflow.com/documentation/bash/topics
https://dev.to/thiht/shell-scripts-matter