Repository navigation
Description
Every Bash script and bats suite in this repository needs an evaluation. Each one gets ported to a Go command, ported to a Python script, or optimized and kept as Bash, and no Bash script stays longer than about 200 SLOC. Bash and bats are now the main drag on the test suites here and in the consumers. They're also the main source of the portability breakage found while landing v0.11 and v0.12.
Why
- Size. On main there are 73 unique source scripts totalling about 6,990 SLOC (comments and blank lines excluded), plus about 5,270 lines of bats across 36 suites. The generator and APM deployment multiply every skill script into up to four copies (both harness packages,
.claude/skills/,.agents/skills/), so the tree carries about 44,800 lines of.sh. - Portability. Most of the failures behind ci: run bats regression suites on Linux and macOS #190 were Bash and bats portability defects that merged unnoticed: GNU-only
sed -iand regex alternation that break on BSD userland,[[ -v ]]and empty-array expansion that break on macOS's Bash 3.2 (fix(tasks): handle empty pre-approval scopes on bash 3.2 #197), tests that reached forrg, and tests that didn't pin resolution underMISE_LOCKED=1. Each one was a real defect that a typed language with a standard library would have prevented or caught at build time. - Test runtime. bats suites dominate test time here and in the consumers. One consumer's
mise run testincludes a bats file that takes about 15 minutes on an idle machine (agent-pr and agent-commit: reuse a dry run's gate passes on an unchanged tree #161). bats tests start real processes and scratch repositories for every case, so they're slow by construction and flaky under load.
Scripts over the limit
| SLOC | Script |
|---|---|
| 402 | .devtools/scripts/check-leaks.sh |
| 375 | packages/agents/source/skills/pr/shared/scripts/validate-description.sh |
| 332 | packages/agents/source/lib/lib.sh |
| 284 | packages/agents/source/skills/pr/shared/scripts/preflight.sh |
| 269 | packages/agents/source/skills/pr/shared/scripts/create-pr.sh |
| 257 | packages/agents/source/skills/fix-prose/shared/scripts/check-suppressions.sh |
| 242 | packages/agents/source/skills/rebase/shared/scripts/preflight.sh |
| 213 | packages/agents/source/skills/commit/shared/scripts/preflight.sh |
The full ranked inventory goes in the evaluation itself. The next group, 100 to 200 SLOC, is about 25 scripts, among them rebase/verify-rebase.sh, tools/skill-tokens.sh, merge-pr/squash-merge.sh, merge-pr/preflight.sh, tools/test-guards.sh and commit/commit.sh.
Scope
- Every
.shunderpackages/agents/source/,.devtools/scripts/,tools/andscripts/(the generated and deployed copies follow their source). - Every bats suite, including
tests/test_helper.bash. - Inline bash in mise task bodies (
mise.toml,.devtools/tasks/*.toml) longer than a few lines. - The same review for the consumer repositories' own scripts and suites (o11y, tailnet-policy, space-geese-project, devhub, vale-ai-tells), done after devtools so they can adopt whatever devtools ships instead of keeping their own copies.
Decision criteria
For each script, record its SLOC, what calls it (skill, hook, task, CI, consumer), its test coverage and suite runtime, and one decision:
- Go command. For logic with real control flow, parsing, git or GitHub API work, or anything that has to behave the same on macOS, Linux and Windows. These belong in
cmd/(or the agent binary program in Move reusable agent tooling into released Go binaries #174), with table-driven tests, and ship as released binaries so consumers don't vendor source. - Python script. For text and report processing where Python's standard library fits better and there's no hot path, following the existing
tools/*.pypattern (uv script headers, pytest, 100% branch coverage). - Keep as Bash, optimized. Only for thin glue: under about 200 SLOC, mostly sequencing other commands, with no parsing beyond trivial. Its bats tests shrink to the cases that need a real shell; everything else moves into unit tests of whatever the glue calls.
Acceptance
- An inventory of every script and suite with SLOC, callers, runtime and the decision, committed under
docs/or the plan directory. - A lint gate in the shared payload that fails on any Bash script over 200 SLOC (comments and blanks excluded). No allowlist or baseline: pre-existing findings are never grandfathered in these projects, so the gate lands only once every script is under the limit, through porting, splitting, or optimizing.
- A migration order that puts the portability-fragile and slow ones first (
check-leaks.sh,validate-description.sh, the preflights,lib.sh), coordinated with Move reusable agent tooling into released Go binaries #174 so Go ports land in the binary program, not as one-off commands. - Measured test-time results before and after for this repository's
mise run test, and the bats share of it. - Consumer follow-ups filed once devtools ships the replacements.
Related
#174 (moving reusable agent tooling into released Go binaries) is the natural home for the Go ports. #161 (reusing gate passes) addresses repeated test runs, not slow ones. #144 (ShellCheck SC2312) still applies to whatever stays Bash, so whatever stays Bash still has to clear #144's sweep.
Activity
feat(tools): establish the shell migration baseline (#243)
fix(docs): split the script inventory into smaller sections (#248)
14 remaining items