Status:
accepted · ADR-28 · Filed 2026-04-28Decision
Bash scripts in this repo own the TTY surface. MCP verbs own the state-and-network surface. The dividing line is whether the work touches the user’s terminal FD — OSC sequences, ANSI colors, interactive prompts, background watcher subshells, exec-into-foreground-editor, job control. Concretely:- Stays a script: launchers (coder.sh), bootstrap (bootstrap.sh, start-backend.sh), in-container entrypoints (docker-entrypoint.sh), interactive restore flows (prism-restore.sh), and CI/lint tools that don’t run in agent hot-paths (spec049_grep_guard.sh, proto-codegen.sh).
- Becomes a verb: deploys, backups, clone-from-remote, perf probes — any work that returns structured data and isn’t tied to the user’s terminal.
- Hybrid: scripts that must run on a remote host (root on server1) stay scripts on the host but get a thin local verb wrapper that SSHs in, runs the script with
--json, and returns parsed output (prism-server-install.sh, prism-server-clean.sh).
prism_resolve) rather than reimplement.
Rationale
Two forces:-
Token cost. Bash tool calls dump stdout+stderr verbatim into the agent’s conversation transcript. A 50-line docker-compose run becomes 50 lines of context that has to be re-cached on every cache miss (Anthropic’s 5-min prompt-cache TTL). Equivalent verb returns structured JSON — typically 10× smaller. Empirically the largest single token leak in agent transcripts is
bin/prism-deploy-server1.sh(150–300 lines per call × 5–15 calls per active dev session). - Performance. Recurring shell calls pay cold-start tax per invocation: ssh handshake (~200–800ms), shell spawn (~30ms), docker CLI startup (~100ms). Verbs can hold persistent backend resources (ssh ControlMaster, docker socket, Postgres/Redis pools) and amortize the cost across calls.
Alternatives Considered
- Keep all bash. Token-bloat in agent transcripts compounds with session length; ssh/docker cold-start tax stacks per recurring call. Rejected.
- Port everything to verbs. Impossible — TTY constraints don’t bend. Interactive
read -pprompts and OSC title sequences can’t live in a remote backend process. Rejected. - Extract a shared bash helper library. Dedupes script-internal duplication but does nothing for agent token cost — agents still invoke bash, still see the output. Rejected as the primary approach (still recommended for surviving scripts that share env/project resolve logic — but they should call the verb instead, see SPEC-051 Phase 3).
- Move bash → TypeScript CLI. TS CLI cold-start (~100–200ms node startup) is better than bash but no connection-pooling, and agents still read stdout via the Bash tool. Equivalent to bash for token cost. Rejected.

