Claude Code Plugins

Community-maintained marketplace

Feedback

>-

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name bash
description Guide for writing production-quality bash scripts following modern idiomatic practices. Enforces set -euo pipefail, [[ ]] conditionals, ${var} syntax, ShellCheck compliance. Triggers on "bash script", "shell script", ".sh file", "write a script", "automation script", "bash function", "shellcheck", "bash template", "pre-commit hook", "deploy script", "build script", "install script", "setup script", "bash error handling", "bash arrays", "bash loop", "bash conditional", "parse arguments", "getopts", "bash logging", "#!/bin/bash", "source script", "dot script", "shell function", "edit script", "update script", "modify script", "change script", "edit .sh", "update .sh", "modify .sh", "statusline.sh", "hook script". PROACTIVE: MUST invoke BEFORE editing/writing ANY .sh file or pre-commit hook.
allowed-tools Read, Write, Edit, Bash, Glob, Grep

ABOUTME: Bash scripting skill for production-quality scripts with Bash 4.x+

ABOUTME: Emphasizes safety, readability, maintainability, and mandatory ShellCheck compliance

Bash Scripting Skill

Target: Bash 4.0+ with mandatory ShellCheck compliance.

Detailed patterns: See references/script-template.md and references/advanced-patterns.md


🚨 PROACTIVE INVOCATION REQUIRED

┌─────────────────────────────────────────────────────────────┐
│  BEFORE using Edit/Write on ANY .sh file:                   │
│                                                             │
│  1. CHECK the file extension - is it .sh?                   │
│  2. If YES → This skill MUST be active                      │
│  3. If skill not loaded → STOP and invoke /bash first       │
│                                                             │
│  This applies even if the user didn't mention "bash" or     │
│  "script" - file extension is the trigger!                  │
│                                                             │
│  Examples that require /bash skill:                         │
│  - "update the statusline" (edits statusline.sh)            │
│  - "add a feature to the hook" (edits pre-commit)           │
│  - "fix the deploy script" (edits deploy.sh)                │
└─────────────────────────────────────────────────────────────┘

Quick Reference

Pattern Use Avoid
Conditionals [[ "${var}" == "x" ]] [ $var == "x" ]
Variables "${var}" (quoted) $var (unquoted)
Command sub $(command) `command`
Arithmetic (( count++ )) let count++
Error handling set -euo pipefail No safety flags

When to Use Bash

USE for (< 200 lines):

  • Quick automation tasks
  • Build/deployment scripts
  • System administration
  • Glue code between tools

DON'T USE for:

  • Complex business logic
  • Robust error handling with recovery
  • Long-running services
  • Code requiring unit testing

If script exceeds ~200 lines, consider Python or Go.


🔄 RESUMED SESSION CHECKPOINT

┌─────────────────────────────────────────────────────────────┐
│  SESSION RESUMED - BASH SKILL VERIFICATION                  │
│                                                             │
│  Before continuing:                                         │
│  1. Does script have set -euo pipefail?                     │
│  2. Are all variables quoted: "${var}"?                     │
│  3. Using [[ ]] conditionals (not [ ])?                     │
│  4. Run: shellcheck <script>.sh                             │
└─────────────────────────────────────────────────────────────┘

Mandatory Header

Every script MUST start with:

#!/bin/bash
set -euo pipefail

# -e: Exit on error
# -u: Error on unset variables
# -o pipefail: Pipeline fails on first error

Core Syntax Rules

Conditionals (Always [[ ]])

if [[ "${var}" =~ ^[0-9]+$ ]]; then
    echo "Numeric"
fi

if [[ -f "${file}" && -r "${file}" ]]; then
    echo "File exists and readable"
fi

Variable Expansion (Always quoted)

echo "Value: ${config_path}"
echo "Array: ${my_array[@]}"

Command Substitution

current_date=$(date +"%Y-%m-%d")
file_count=$(find . -type f | wc -l)

Arithmetic

(( count++ ))
(( total = value1 + value2 ))
if (( count > 10 )); then
    echo "Exceeded"
fi

Error Handling Patterns

Pattern 1: Need output AND status

output=$(complex_command 2>&1)
rc=$?
if [[ ${rc} -ne 0 ]]; then
    log_error "Failed: ${output}"
    return 1
fi

Pattern 2: Status check only

if ! simple_command --flag; then
    die "Command failed"
fi

# Or short form
simple_command || die "Failed"

Essential Functions

# Logging
log_info()  { echo "[INFO] $(date +%H:%M:%S) ${*}" >&2; }
log_error() { echo "[ERROR] $(date +%H:%M:%S) ${*}" >&2; }
die()       { log_error "${*}"; exit 1; }

# Validation
validate_file() {
    local -r f="${1}"
    [[ -f "${f}" ]] || die "Not found: ${f}"
    [[ -r "${f}" ]] || die "Not readable: ${f}"
}

# Cleanup
cleanup() {
    [[ -d "${TEMP_DIR:-}" ]] && rm -rf "${TEMP_DIR}"
}
trap cleanup EXIT

Argument Parsing

parse_arguments() {
    while [[ $# -gt 0 ]]; do
        case "${1}" in
            -h|--help)    help; exit 0 ;;
            -v|--verbose) VERBOSE=true; shift ;;
            -f|--file)
                [[ -z "${2:-}" ]] && die "-f requires argument"
                FILE="${2}"; shift 2
                ;;
            -*)           die "Unknown: ${1}" ;;
            *)            break ;;
        esac
    done
    ARGS=("${@}")
}

ShellCheck Compliance

All scripts MUST pass ShellCheck with zero warnings.

Common Fixes

Warning Fix
SC2086: Quote to prevent globbing rm "${file}" not rm $file
SC2155: Declare separately local x; x=$(cmd) not local x=$(cmd)
SC1090: Can't follow source # shellcheck source=/dev/null
SC2046: Quote command sub Use while read instead of for x in $(cmd)

Run ShellCheck

shellcheck script.sh
shellcheck -s bash script.sh
find . -name "*.sh" -exec shellcheck {} +

Arrays Quick Reference

Indexed Arrays

declare -a files=()
files+=("item")
for f in "${files[@]}"; do echo "${f}"; done
echo "Count: ${#files[@]}"

Associative Arrays (Bash 4+)

declare -A config=()
config["key"]="value"
for k in "${!config[@]}"; do echo "${k}=${config[${k}]}"; done

Security Rules

  1. Never use eval
  2. Sanitize all inputs
  3. Use absolute paths for system commands
  4. Use readonly for constants
  5. Don't store secrets in scripts

Checklist

Before script is complete:

  • set -euo pipefail at top
  • All variables use "${var}" syntax
  • Uses [[ ]] for conditionals
  • Uses $(command) for substitution
  • ShellCheck passes (zero warnings)
  • Has help() function
  • Has cleanup trap
  • Variables properly scoped (local/readonly)
  • If > 100 lines: Has bats tests

Full Template

See references/script-template.md for complete production script template.

Advanced Patterns

See references/advanced-patterns.md for:

  • Arrays and associative arrays
  • String manipulation
  • Parallel processing
  • Progress indicators
  • Input validation
  • bats-core testing