bash-defensive-patternslisted
Install: claude install-skill uwuclxdy/agenticat
# Bash Defensive Patterns
Defensive idioms for Bash that changes real systems. Pick each guard by intent and keep its reason next to the code.
## `set` Flags by Intent
Comment the intent beside the flags so nobody cargo-cults the wrong one.
```bash
set -euo pipefail # orchestration/deploy: any failed step aborts the run
set -uo pipefail # drop -e: steps may fail without aborting (optional installs, fail-open heartbeats)
set -u # long-running/interactive loop: -e would kill on a benign non-zero
```
A thin wrapper sets no flags and ends with `exec` so the wrapped tool's exit code reaches the supervisor verbatim:
```bash
exec tool "$@" # no set flags; propagate the real exit code to systemd
```
## Quoting and Expansion
End-of-options guard against argument injection:
```bash
cp -- "$src" "$dst"
```
## Input Guards
Validate at the boundary; parse into a checked value so no call site re-tests a raw string.
```bash
HOST="${1:?host ip required}" # required positional arg
: "${DB_URL:?set DB_URL in $CONF}" # required env/config var
case "$MIN" in *[!0-9]*|'') echo "MIN must be integer" >&2; exit 2;; esac
safe="${HOST//[^0-9A-Za-z]/_}" # sanitize untrusted string used as a filename
```
## Cleanup with Trap
Every `mktemp` gets an EXIT trap. Manual per-path `rm` leaks the moment someone adds a new early exit.
```bash
TMP="$(mktemp)"; trap 'rm -f "$TMP"' EXIT
```
## Idempotency
Check-then-act so a re-run is a no-op.
```bash
have()