Docs › AI coding agents
AI coding agents
Coding agents (Claude Code and others) run tests, typechecks and linters all day, often several agents at once. Sparehand can take those runs off your computer automatically: the agent types npm test as usual, and the run happens on a free worker, with the same output and exit code.
Pick your tools
sparehand agent status # the coding tools on this Mac, and how each is connected
sparehand agent install all # connect every tool found here
sparehand agent install gemini # or one: claude, codex, gemini, cursor, copilot, windsurf,
# opencode, kiro, cline
sparehand agent test gemini # what its hook does with a heavy command and a light one
sparehand agent uninstall cursor
The Mac app does the same in Settings → AI Tools, with a switch per tool.
There are two kinds of connection:
- A hook decides for the agent. The tool asks Sparehand before each shell command, with the rules below. In most tools the hook changes the command, so
npm testruns assparehand run --or-local …and the model does nothing different. Codex and Kiro only let a hook refuse a command: there the hook refuses the heavy command once and gives the model the Sparehand command to run instead. - A note asks the agent to run heavy checks as
sparehand run --or-local <command>itself. It depends on the model following it: most do, most of the time, but it is a request and not a rule. Where a tool has both, the note covers what the hook doesn't reach.
| Tool | Connected by | Where |
|---|---|---|
| Claude Code | hook | ~/.claude/settings.json |
| Gemini CLI | hook, plus a note | ~/.gemini/settings.json, ~/.gemini/GEMINI.md |
| Cursor | hook | ~/.cursor/hooks.json |
| Codex CLI | hook that refuses and names the command, plus a note | ~/.codex/hooks.json, ~/.codex/AGENTS.md |
| GitHub Copilot CLI | hook, plus a note | ~/.copilot/hooks/sparehand.json, ~/.copilot/copilot-instructions.md |
| Windsurf | hook (Devin Local and Devin CLI), plus a note in Cascade's global rules | ~/.config/devin/config.json, ~/.codeium/windsurf/memories/global_rules.md |
| OpenCode | hook (a plugin), plus a note | ~/.config/opencode/plugins/sparehand.js, ~/.config/opencode/AGENTS.md |
| Kiro | hook that refuses and names the command (CLI only), plus a steering file | ~/.kiro/hooks/sparehand.json, ~/.kiro/steering/sparehand.md |
| Cline | a note only: it depends on the model following it | ~/Documents/Cline/Rules/sparehand.md |
Three things to know:
- Codex runs a new hook only after you trust it: open Codex and type
/hooks. Its sandbox has no network unless you allow it ([sandbox_workspace_write] network_access = truein~/.codex/config.toml); without it the runs stay on your computer. - Kiro's hook works in its CLI. In the Kiro IDE only the steering file applies.
- GitHub Copilot's coding agent (the one that works on GitHub) isn't connected: it reads hooks only from the repository and runs on GitHub's machines.
sparehand agent status shows, per tool, whether it is on this Mac, whether it is connected by hook or by note, and the version of the tool its hook was checked against. The formats, their sources and the date of the last check are in Coding tools' hooks.
Trying a connection
sparehand agent test cursor # or: all
This hands the installed hook two commands the way the tool would, npm test and git status, and prints what the hook answers: the first goes to a spare machine (or is refused with the command to run), the second is left alone. Nothing is run, on a worker or here. For a tool that isn't connected it shows what the hook would do; for Cline it says there is no hook to try.
Disconnecting
sparehand agent uninstall TOOL (or all) puts each file back exactly as it was, byte for byte, and removes the files and folders that were made for the connection. Sparehand keeps a copy of each file from before its first change in ~/.config/sparehand/agent-tools/ until then. If you changed a file after connecting, your changes stay and only Sparehand's part goes: its hook entry, or the lines between <!-- sparehand:start --> and <!-- sparehand:end -->.
Claude Code
sparehand agent install # for all your projects (~/.claude/settings.json)
sparehand agent install --project # only this project (.claude/settings.json)
sparehand agent status
sparehand agent uninstall
This adds a PreToolUse hook for the Bash tool. New sessions pick it up. The rest of this page describes that hook; the other tools' hooks follow the same rules.
What it hands over
Checks whose only result is their output and exit code, so running them elsewhere loses nothing:
npm/pnpm/yarn/buntest,test:*,typecheck,lint,lint:*,check,verifyjest,vitest,tsc --noEmit(atscthat writes files is a build and stays),eslint,mocha,playwright test,biome check,prettier --check(directly or throughnpx,pnpm exec,bunx)pytest,mypy,ruff check,pyright,tox;go test/go vet;cargo test/check/clippy;mvn test,gradle test,dotnet test,rspec,phpunit,make test/check/lint
A command like cd apps/api && npx jest src/orders 2>&1 | tail -20 is handed over as a whole.
What it leaves alone
- Builds (
npm run build,cargo build,make…): their output files are needed on your computer. SetSPAREHAND_AGENT_GET=dist,coverage(the paths the results land in, relative to where the command runs) and builds are handed over too, with those paths copied back when the job ends (sparehand run --get).SPAREHAND_AGENT_BUILDS=1hands builds over without bringing anything back (when a build is only a check). - Anything that changes your computer or the outside world, or needs it: installs,
git,ssh,docker,sudo, deploys and migrations, dev servers and watchers, snapshot updates (-u),--fix/--write, output written to a file (>), commands already usingsparehand.
How it behaves
- The command becomes
sparehand run --or-local sh -c '<command>': it runs on the least busy worker, or right on your computer when none is free (no "exit 255" for the agent to deal with). - When your computer is full too (
SPAREHAND_HUB_JOBS), the command waits for whichever machine frees up first instead of piling on. In Claude Code and OpenCode, whose commands carry their own timeout, the hook adds up to 5 minutes to it for that (10 minutes in all), so the wait doesn't cut the run short. The other tools give a hook no timeout to change; there the run waits 30 seconds at most and then runs on your computer. - The hook never approves anything: the rewritten command still goes through your own permission rules.
- If anything goes wrong in the hook (no Node, odd input), the command runs unchanged.
Settings
In ~/.config/sparehand/sparehand.conf or the environment:
| Setting | Meaning |
|---|---|
SPAREHAND_AGENT=off | Switch the hook off without uninstalling it |
SPAREHAND_AGENT_GET=dist,coverage | Bring these paths back after every handed-over command; builds are handed over too |
SPAREHAND_AGENT_BUILDS=1 | Also hand over builds (without bringing their output back) |
SPAREHAND_AGENT_MATCH=regex | Replace the list of commands that count as checks |
SPAREHAND_AGENT_SKIP=regex | Extra commands to leave alone |
SPAREHAND_AGENT_CODEX=rewrite | In Codex, change the command in place instead of refusing it with the command to run. Codex takes a changed command only together with an "allow", and its documentation doesn't say whether that skips your approval |
Other agents and scripts
Any tool can use sparehand run --or-local <command>: it runs on a worker when one is free and on your computer otherwise, and always returns the command's own output and exit code.