Write, review, and fix Bash (.sh) scripts using project conventions and best practices. Always use this skill when writing any .sh file, creating a new shell script, fixing a bash error or runtime error, reviewing shell code, adding a new script to scripts/, or when the user asks about bash style, naming, formatting, or patterns. This skill combines official style rules with project-specific patterns to produce correct, portable scripts on the first try. Trigger on: write bash, create .sh, ba...
Pro scans all 2 files and shows the line behind each finding
Scanned 10/6/2026
npx -y skills add e128/dotnet-reference --skill bash-patterns --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Bash Patterns?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/e128-bash-patterns)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: bash-patterns
description: >
Write, review, and fix Bash (.sh) scripts using project conventions and best practices.
Always use this skill when writing any .sh file, creating a new shell script, fixing a
bash error or runtime error, reviewing shell code, adding a new script to scripts/, or
when the user asks about bash style, naming, formatting, or patterns. This skill combines
official style rules with project-specific patterns to produce correct, portable scripts
on the first try. Trigger on: write bash, create .sh, bash script, shell script, bash error,
fix .sh, bash style, bash patterns, script error in bash.
---
# Bash Scripting Patterns
Bash 5+. Scripts live in `scripts/` (`.sh`), must pass `shellcheck` before commit.
Generic bash idioms (control flow, string/array ops, functions, built-ins): see `references/bash-reference.md`. This file covers only project conventions and gotchas.
## Naming Conventions
| Element | Convention | Example |
|---------|-----------|---------|
| Script files | kebab-case | `build-project.sh` |
| Functions | snake_case | `function fetch_user()` |
| Local variables | snake_case | `local user_id` |
| Constants | SCREAMING_SNAKE_CASE | `readonly OUTPUT_DIR` |
| Environment variables | SCREAMING_SNAKE_CASE | `$APP_VERSION` |
## Script Header Template
```bash
#!/usr/bin/env bash
set -euo pipefail
# One-line summary of what this script does.
#
# Usage:
# scripts/my-script.sh [--flag] <arg>
```
**Always start with `set -euo pipefail`.**
## Formatting Rules
- No trailing whitespace.
- Indent with 2 spaces (not tabs).
- Lines <= 100 chars preferred; wrap long lines with `\`.
- Quote all variable expansions: `"$var"` not `$var`.
- Use `[[ ]]` for conditionals (not `[ ]`).
- Use `$(command)` for subshells (not backticks).
## Argument Parsing Template
```bash
SOLUTION=""
FLAG=false
JSON=false
while [[ $# -gt 0 ]]; do
case "$1" in
--flag) FLAG=true; shift ;;
--json) JSON=true; shift ;;
-*) echo "Unknown flag: $1" >&2; exit 1 ;;
*) SOLUTION="$1"; shift ;;
esac
done
[[ -z "$SOLUTION" ]] && { echo "Usage: script.sh <arg> [--flag]" >&2; exit 1; }
```
## Core Patterns
### JSON Output Mode
Use `jq` for JSON construction and parsing:
```bash
if $JSON; then
jq -nc \
--arg status "$status" \
--argjson count "$count" \
'{status: $status, count: $count}'
fi
```
### Error Handling
```bash
# Trap for cleanup
cleanup() { rm -f "$TMP_FILE"; }
trap cleanup EXIT
# Check command exists
command -v dotnet &>/dev/null || { echo "dotnet not found" >&2; exit 1; }
# Capture exit code without exiting
output=$(some_command 2>&1) || true
exit_code=$?
```
### Temporary Files
```bash
TMP_FILE="$(mktemp)"
trap 'rm -f "$TMP_FILE"' EXIT
```
### Prerequisites Check
```bash
check_prerequisites() {
local -a missing=()
for tool in git dotnet jq; do
command -v "$tool" &>/dev/null || missing+=("$tool")
done
if [[ ${#missing[@]} -gt 0 ]]; then
echo "Missing required tools: ${missing[*]}" >&2
exit 1
fi
}
```
### Shared Library Pattern
```bash
# In scripts/lib.sh
#!/usr/bin/env bash
# Shared utility functions sourced by other scripts.
get_repo_root() {
git rev-parse --show-toplevel
}
log_info() {
echo "[INFO] $*" >&2
}
log_error() {
echo "[ERROR] $*" >&2
}
# In consumer script
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/lib.sh"
```
## Command Design Rules
- Max 2 positional parameters; use `--flags` for anything beyond that.
- Document every exported function with a comment line above it.
- Provide both long and short flag forms for commonly-used flags (`-j` / `--json`).
- Validate external tool availability at script start (see Prerequisites pattern).
- Always use `local` for function-scoped variables.
- Use `readonly` for constants that should not change.
## Pitfalls Quick Reference
| Symptom | Root cause | Fix |
|---------|-----------|-----|
| `unbound variable` | `set -u` + unset var | Use `${var:-}` for optional vars |
| Script exits silently | `set -e` + failed command | Add `|| true` for expected failures |
| `command not found` | Missing PATH or wrong name | Check `command -v` first |
| Glob expansion in variable | Unquoted `$var` with `*` | Always quote: `"$var"` |
| Pipe swallows exit code | Default pipe behavior | `set -o pipefail` (in header) |
| Array empty check fails | Wrong syntax | Use `${#arr[@]}` not `$arr` |
| Heredoc indentation breaks | Spaces in heredoc | Use `<<-` with tabs, or `<<'EOF'` |
| Word splitting in loop | Unquoted expansion | Quote arrays: `"${arr[@]}"` |
| Subshell variable lost | `( )` creates subshell | Use `{ }` or process substitution |
## Test Before Commit
`shellcheck` is the authoritative linter — fix all warnings before committing.
```bash
shellcheck scripts/my-script.sh
bash -n scripts/my-script.sh # syntax-only check
```
## Self-Improvement
After writing or fixing any Bash script:
1. **Add new pitfalls to the quick reference** — If a new error was hit that isn't in the Pitfalls Quick Reference table, add a row immediately (Symptom | Root cause | Fix).
2. **Update version-specific guidance** — If a Bash feature requires a specific version (e.g., associative arrays require Bash 4+), note the version requirement.
3. **Record project-specific patterns** — If a pattern emerged specific to this project's scripts, add it here.
4. **Fix stale instructions immediately** — If any instruction in this skill contradicted what actually worked, correct it before the session ends.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!