skills/bash-script-generator/SKILL.md
Generate Bash 3.2-compatible scripts with a standardized check_requirements guardrail, friendly validation errors, and optional shfmt formatting. Use when writing or updating bash scripts that need consistent argument validation, dependency checks, and portability.
npx skillsauth add asteroid-belt-llc/skills bash-script-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
check_requirements function that validates inputs and dependencies kindlyset -euo pipefail), quotes expansions, and keeps logic portable to macOS/Linux Bash 3.2shfmt when available and return a polished result ready for immediate useUse this skill whenever the user asks for a new bash script or a major refactor of an existing script and they expect:
Do not use this skill for:
sh-only scripts (no Bash-specific features allowed)coproccurl, jq). Note install hints when useful.Deliverable: A short table (in notes or your head) of arguments, env vars, and commands you will feed into
check_requirementsandusagemessaging.
Lay out the sections before writing code:
Header & Safety
#!/usr/bin/env bashset -euo pipefailIFS=$'\n\t' only if tighter word splitting is needed.Metadata Comments (optional)
Usage Helper
usage() function that prints how to run the script, expected args, environment variables, and examples.Requirement Configuration
REQUIRED_ARGS, REQUIRED_ENV_VARS, and REQUIRED_PROGRAMS as indexed arrays (compatible with Bash 3.2). When nothing is required, keep the arrays empty but present.case statements; do not use declare -A (requires Bash ≥4).check_requirements Function (see Phase 3 for exact pattern)
Argument Parsing
getopts for short flags. For long options, parse manually with a while loop; avoid getopt if portability is uncertain.${VAR:-} to coexist with set -u).Main Logic
main() and finish with main "$@".Follow this recipe while writing the actual script content.
check_requirementscheck_requirements() {
local -r provided_arg_count=$1
local missing=0
if [ ${#REQUIRED_ARGS[@]} -gt 0 ] && [ "$provided_arg_count" -lt ${#REQUIRED_ARGS[@]} ]; then
printf 'Error: Expected %s arguments (%s) but received %s.\n' \
${#REQUIRED_ARGS[@]} "${REQUIRED_ARGS[*]}" "$provided_arg_count" >&2
missing=1
fi
local env_var
for env_var in "${REQUIRED_ENV_VARS[@]}"; do
if [ -z "${!env_var:-}" ]; then
printf 'Error: Missing required environment variable %s. Please set it before rerunning.\n' "$env_var" >&2
missing=1
fi
done
local program
for program in "${REQUIRED_PROGRAMS[@]}"; do
if ! command -v "$program" >/dev/null 2>&1; then
printf 'Error: Required program %s is not installed or not on PATH. Please install it first.\n' "$program" >&2
missing=1
fi
done
if [ "$missing" -ne 0 ]; then
printf '\n' >&2
usage >&2
return 1
fi
}
Implementation notes:
check_requirements right after argument parsing, e.g. check_requirements "$#".REQUIRED_ARGS limited to the mandatory ones and validate optional parameters separately after check_requirements "$#" succeeds.>&2) and exit gracefully with return 1 so the caller can exit 1 or handle it.usage from error paths (like failed requirement checks) so successful runs stay quiet unless the user explicitly asks for help.local -n).[[ string =~ regex ]] with capture groups that rely on Bash ≥3.2. Basic regex is fine, but keep patterns simple.mapfile, readarray, coproc, printf -v, or process substitution that requires /dev/fd (often missing on macOS).$( command ) subshells over backticks and quote every expansion.printf instead of echo -e for reliable escape handling.usage() {
cat <<'EOF'
Usage: my_script.sh <source> <destination> [--dry-run]
Required arguments:
source Path to the input file (must exist)
destination Output directory (will be created if missing)
Environment variables:
API_TOKEN Token used to authenticate API requests
External tools:
curl, jq
Examples:
my_script.sh ./input.csv ./out --dry-run
EOF
}
Tailor the body to the specific script; keep instructions kind and explicit.
usage() and check_requirements() exactly once.getopts or manual loop) and convert into named variables.check_requirements immediately after parsing. If it fails, exit with exit 1.main() with clear, modular helpers; rely on functions instead of sprawling inline code.main "$@" and ensure the script returns appropriate exit codes.Self-check
usage?set -euo pipefail (guard nullable variables with ${VAR:-})?Formatting via shfmt
if command -v shfmt >/dev/null 2>&1; then ... fishfmt -i 2 -bn -ci -sr -w <path-to-script> after writing the file.Final Response Checklist
bash).shfmt), note it explicitly.Use this skeleton as a starting point and adapt each section based on the user's requirements:
#!/usr/bin/env bash
set -euo pipefail
# Script: <name>
# Purpose: <one-line description>
# Requirements: <short summary of args/env/programs>
REQUIRED_ARGS=("arg1" "arg2")
REQUIRED_ENV_VARS=("ENV_VAR")
REQUIRED_PROGRAMS=("curl" "jq")
usage() {
cat <<'EOF'
Usage: <script-name> <arg1> <arg2>
Required arguments:
arg1 <describe>
arg2 <describe>
Environment variables:
ENV_VAR <describe>
External tools:
curl, jq
EOF
}
check_requirements() {
local -r provided_arg_count=$1
local missing=0
if [ ${#REQUIRED_ARGS[@]} -gt 0 ] && [ "$provided_arg_count" -lt ${#REQUIRED_ARGS[@]} ]; then
printf 'Error: Expected %s arguments (%s) but received %s.\n' \
${#REQUIRED_ARGS[@]} "${REQUIRED_ARGS[*]}" "$provided_arg_count" >&2
missing=1
fi
local env_var
for env_var in "${REQUIRED_ENV_VARS[@]}"; do
if [ -z "${!env_var:-}" ]; then
printf 'Error: Missing required environment variable %s. Please set it before rerunning.\n' "$env_var" >&2
missing=1
fi
done
local program
for program in "${REQUIRED_PROGRAMS[@]}"; do
if ! command -v "$program" >/dev/null 2>&1; then
printf 'Error: Required program %s is not installed or not on PATH. Please install it first.\n' "$program" >&2
missing=1
fi
done
if [ "$missing" -ne 0 ]; then
printf '\n' >&2
usage >&2
return 1
fi
}
parse_args() {
# TODO: replace with real parsing
SOURCE=${1:-}
DEST=${2:-}
}
main() {
parse_args "$@"
check_requirements "$#" || exit 1
# TODO: script logic goes here
printf 'Running with source=%s dest=%s\n' "$SOURCE" "$DEST"
}
main "$@"
Update placeholders, replace TODO sections, and adjust arrays when a requirement does not apply (leave the array empty—do not delete it).
check_requirements functionusage() accurately reflects arguments, env vars, and dependenciesshfmt (or explicitly noted why it was skipped)development
Transforms technical documents into rigorous learning journeys with collegiate-level mastery requirements. Uses Bloom's taxonomy progression, 80%+ mastery thresholds, and multi-level verification before advancing. Treats learning as a high school to college graduation progression. Use when user wants deep understanding, not surface familiarity.
development
Use when starting significant features, epics, or complex tasks. Creates multi-phase implementation plans with parallelizable phases, poker estimates, TDD-first acceptance criteria, and quality gates. Detects tech stack from CLAUDE.md/AGENTS.md (bypassing internet research if complete) or via codebase scan.
development
Generates a docs/ directory of markdown files giving AI and humans deep context on WHAT a codebase is, HOW it works, and WHY decisions were made. Scans any codebase, produces structured documentation. Re-runnable — detects existing docs, monorepos, and git-based staleness. Runs automatically without user interaction.
development
Weekly codebase hygiene skill that identifies and fixes AI-generated code problems ("slop") using Martin Fowler's refactoring techniques. Scans for 15 common issues, prioritizes by severity, and generates superplan-compatible plans for systematic improvement.