From swe-workbench
Bash idioms — strict mode, quoting, parameter expansion, arrays, pipefail, trap cleanup, idempotency, heredocs, and POSIX portability. Auto-load when working with .sh, .bash files, or when the user mentions bash, shell, sh, shellcheck, set -e, or pipefail.
How this skill is triggered — by the user, by Claude, or both
Slash command
/swe-workbench:language-bashThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```bash
set -euo pipefail
IFS=$'\n\t'
-e is suppressed in conditional contexts (||, &&, if, !); explicit subshells (...) do inherit it — use || true to absorb expected failures.-u treats unset variables as errors; unset arrays trigger it: declare before use (arr=()) or guard with ${arr[@]+"${arr[@]}"} for optional arrays.IFS=$'\n\t' prevents accidental word-splitting on spaces in for loops and command substitution."$var" — bare $var triggers word splitting and glob expansion.'literal' for fixed strings with no expansion needed.[[ ]] over [ ]: supports =~ regex, no word splitting, lexical string comparison.$() over backticks: nestable, readable, no escaping required.if [[ "$filename" =~ \.(sh|bash)$ ]]; then
shellcheck "$filename"
fi
${var:-default} — substitute default if unset or empty.${var:?error msg} — abort with message if unset; pairs well with set -u.${var%suffix} — strip shortest suffix match (e.g. strip extension).${var//pattern/repl} — replace all occurrences in-place.files=(src/a.sh "src/b script.sh" src/c.sh)
for f in "${files[@]}"; do # each element quoted separately
process "$f"
done
"${arr[@]}" — each element as a separate quoted word; always use for iteration."${arr[*]}" — all elements joined by IFS[0]; use only for joining to a string.for x in $(cmd) — use mapfile -t arr < <(cmd) or while IFS= read -r line.pipefail makes a pipeline fail when any stage fails, not just the last.$(...) runs in a subshell; variable assignments inside don't leak out.cmd || true absorbs an expected non-zero exit under -e; cmd 2>/dev/null suppresses stderr noise separately.proc &; always wait "$pid" before consuming results.cmd >/dev/null 2>&1 silences all; cmd 2>&1 >/dev/null silences stdout only (stderr still shows — order determines what 2>&1 copies).tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT
trap 'echo "interrupted" >&2; exit 130' INT TERM
trap early — after state the handler depends on exists, before risky operations.trap '...' ERR fires only on non-zero exit codes; use for diagnostic logging (cannot prevent -e from exiting).EXIT (always), ERR (errors), INT (Ctrl-C), TERM (kill).COMMITTED=0
[[ -f .committed ]] && COMMITTED=1
if (( COMMITTED == 0 )); then
git commit -m "$msg"
touch .committed
fi
[[ -f sentinel ]] || create_it.git ls-remote, gh pr view --json state.tmp=$(mktemp) && generate > "$tmp" && mv "$tmp" target.STEP_DONE=0/1) let downstream branches re-enter safely after interruption.# Literal — no variable expansion:
sql=$(cat <<'EOF'
SELECT * FROM $table WHERE id = $id
EOF
)
# Interpolating — $USER expands:
cat <<EOF
Deploying as $USER to $ENV
EOF
# Strip leading tabs (not spaces) with <<-:
if true; then
cat <<-EOF
indented content
EOF
fi
#!/usr/bin/env bash when using [[ ]], arrays, ${var,,}, mapfile, or process substitution.#!/bin/sh only when strict POSIX portability is required — drop all bash-isms.shellcheck --shell=bash (or --shell=sh) to enforce the declared contract.bats-core for non-trivial scripts: one assertion per test, temp dirs for isolation.assert_eq() { [[ "$1" == "$2" ]] || { echo "FAIL: expected '$2', got '$1'" >&2; exit 1; }; }
PATH.eval "$(script 2>&1)" patterns, capture the script output FIRST from a valid cwd, THEN cd to the eval directory, THEN eval. $(...) launches a subshell that inherits the cwd at expansion time — cd eval_cwd && eval "$(script)" means the script runs FROM eval_cwd, not the original directory, and may exit early.# Wrong — script inherits eval_cwd as cwd, may exit early if it's not a git repo:
cd "$eval_cwd" && eval "$(bash script.sh arg 2>&1)"
# Correct — capture first, then move, then eval:
output="$(bash script.sh arg 2>&1)"; cd "$eval_cwd"; eval "$output"
Under set -e, use output=$(…) || handle_error — $? is unreachable because the parent script aborts at the failed assignment before the next line executes. The || forms a conditional context that suppresses set -e and runs the handler on non-zero exit.
`cmd` — use $(cmd).$var and $@ — always quote.for f in $(ls) or for f in $(find ...) — use globs or mapfile.ls output for filenames — use find or shell globs.eval on user-controlled or external input — command injection risk.cd dir && cmd without a subshell — if cmd fails, subsequent code runs from the wrong directory; use (cd dir && cmd) to scope the change.cat file | grep (UUOC) — use grep pattern file.set -x in production — use PS4 with a debug flag and enable only in targeted blocks.npx claudepluginhub lugassawan/swe-workbench --plugin swe-workbenchGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.