Bash Expert

Caution

Ad-hoc bash is the leading cause of deploy incidents. Missing set -euo pipefail, unquoted variables, hardcoded /usr/local paths — each one is a time bomb. The agent writes scripts that are correct by construction, not by luck.

Tip

Trigger by describing the script you need. “create a setup script for my plugin”, “bash script to check homebrew services”, “install script for macOS and Linux” — the agent picks the right template, adds error handling, and validates syntax before handing back the file.

Quick reference

FieldValue
Modelinherit — runs on the session’s model
ToolsRead, Write, Edit, Glob, Grep, Bash, WebFetch
Triggers”create script”, “bash script”, “shell script”
Output.sh file + bash -n + ShellCheck report

Scope guard

Bash Expert sizes the task before writing. One bounded unit = one deliverable, roughly 5 files, roughly 10 steps.

SituationWhat the agent does
Brief fits one bounded unitStarts immediately
Brief exceeds ~5 files / ~10 steps, or bundles several independent deliverablesStops before starting, returns a split proposal: 2-N bounded subtasks, each with scope and a suggested owner
Scope grows mid-flightStops at the next clean boundary, reports done / remaining / how to split
Brief is missing GOAL, SCOPE, CONTEXT, CONSUMER or acceptanceStates the assumption explicitly in the report, or asks once — never invents scope

“Write the whole CI toolchain” gets a split proposal. “Write the install script for brewtools” gets a script.

Tip

Got a split proposal instead of a script? That is the guard working. Pick one script from the proposal and re-send it, or spawn the subtasks as parallel agents in a single message.

When to use

  • Plugin lifecycle scripts — setup, install, teardown, version-bump for brewcode/brewtools/brewui/brewdoc
  • CI helper scripts — health checks, service validation, environment bootstrap
  • Cross-platform portability — script must run on both macOS (ARM + Intel) and Linux without modification
  • Structured output — script prints markdown tables or phase headers consumed by Claude Code skills
  • Idempotent installers — safe to re-run; checks state before mutating

Examples

# Natural language triggers
"create a setup script for the brewtools plugin"
"bash script to check if all homebrew services are running"
"write an install script that works on macOS and Linux"
# Multi-mode dispatch
"write a multi-mode script with status/install/help commands"
# Plugin-aware paths resolve via ${CLAUDE_PLUGIN_ROOT}
"create a version-bump script for the plugin"

Flow

  1. Analyze the request

    Reads existing scripts in the repo (Glob + Grep) to match conventions. Identifies target platform, required commands, and expected output format before writing a single line.

  2. Choose a template

    Minimal (single-purpose, ≤20 lines) or full multi-mode dispatch (`CMD="${1:-help}"` + case block). Plugin scripts always get SCRIPT_DIR self-location and correct plugin-root resolution.

  3. Implement

    Writes the script with set -euo pipefail, quoted variables, trap cleanup EXIT where needed, and status symbols (✅ ❌ ⚠️) in output. macOS/Linux divergences handled via platform detection, not hardcoded paths.

  4. Validate

    Runs bash -n script.sh (syntax check) and shellcheck script.sh (static analysis). Fixes all ShellCheck warnings before reporting.

  5. Report

    Prints a structured summary: file path, purpose, platform, and a checklist of verified properties. You get a ready-to-run script, not a draft.

Internals — patterns, templates, and platform handling

Conventions

PatternExampleUse
Strict modeset -euo pipefailEvery script, by default
Cleanup traptrap cleanup EXITTemp files, locks, other resources
Required var${VAR:?error msg}Mandatory input
Soft failurecmd || echo "⚠️ warning"Optional steps

Mode detection

ARGS_LOWER=$(echo "${1:-}" | tr '[:upper:]' '[:lower:]')
[[ "$ARGS_LOWER" =~ (install|setup|init) ]] && MODE="install"
[[ "$ARGS_LOWER" =~ (update|upgrade) ]] && MODE="update"
[[ -z "$ARGS_LOWER" ]] && MODE="default"

Minimal template

#!/bin/bash
set -euo pipefail
ARG="${1:-}"
[[ -z "$ARG" ]] && { echo "Usage: script.sh <arg>"; exit 1; }
echo "Processing: $ARG"
echo "✅ Done"

macOS vs Linux divergences

FeaturemacOSLinux
Brew prefix/opt/homebrew (ARM), /usr/local (Intel)/home/linuxbrew/.linuxbrew
timeoutgtimeout (coreutils)timeout
sed in-placesed -i ''sed -i
readlinkgreadlink -freadlink -f

Always derive prefix via $(brew --prefix) — never hardcode.

Structured output

ElementPattern
Status symbols success · error · ⚠️ warning · ⏭️ skipped · 🔄 updated
Markdown tableecho "| Component | Status |" then the separator row, then data rows
Phase headerecho "=== Phase 1: Scanning ===" && echo ""

JSON parsing fallback chain

  1. jq -r '.key' file.json
  2. python3 -c "import json,sys;print(json.load(sys.stdin)['key'])"
  3. grep -oP '"key":\s*"\K[^"]+' file.json

Plugin path variables

VariableAvailable in
$CLAUDE_PLUGIN_ROOTHooks only
${CLAUDE_SKILL_DIR}Skills (string substitution)
${CLAUDE_PLUGIN_ROOT}Agents (native substitution in agent .md at Task spawn)

Anti-patterns

AvoidPrefer
[ $VAR ][[ -n "$VAR" ]]
cat file | grepgrep X file
ls | while readfind -exec or glob
cd dir; cmd; cd -(cd dir && cmd)
echo $VARecho "$VAR"
if [ $? -eq 0 ]if cmd; then
/usr/local hardcoded$(brew --prefix)

Delivery checklist

#Check
1#!/bin/bash shebang
2set -euo pipefail
3Usage header comment
4shellcheck clean
5chmod +x applied
6bash -n passes
7help subcommand works
8Error paths tested
9Idempotent — safe re-run

Return Contract

Verdict first, <=30 lines, path:line. No script bodies, no ShellCheck transcripts, no smoke-run output, no preamble — one block per script, nothing else (the format is in Flow step 5 above). Failures return the check that failed plus the offending path:line, never the full output; long logs and full ShellCheck runs go to .claude/reports/<YYYYMMDD-HHMMSS>_bash-expert/, path only.

/brewtools:agent-return-setup enforces this at ~1000 / ~2500 est-tokens when installed; the contract itself ships unconditionally.

🔗

hook-creator agent

Builds Claude Code hooks — pairs with bash-expert when a hook shells out.

🔗

GitHub source

Agent definition, system prompt, and tool configuration.

📄

Brewcode overview

All brewcode skills and agents in one place.

Updating plugins

Use /brewtools:plugin-update to check and update the brewcode plugin suite in one command. See the FAQ for details.