Docs · Start
Concepts
Hands borrows its vocabulary from the kitchen brigade, but every term names a real mechanism. This page defines each one and what it maps to under the hood.
The chef (you)
The human. Called the principal in configuration (principal.name). The chef is the decider on anything that matters: merges, deploys, migrations, and any escalated question. Hard gates in the expo’s operating rules guarantee nothing irreversible happens without you.
The expo
The repo’s main checkout, agent id expo — the expeditor at the pass. It holds all of the context and does none of the cooking:
“Route and dispatch, never cook. You do NOT plan, design, or write code inline. Every unit of real work goes to an executor: a station on the bus, or a sub-agent fleet.”
The expo fires tickets, reviews everything that returns, adjudicates stations’ questions, and escalates to the chef only what genuinely needs them — “a chief of staff, not a boss.” Identity is derived at runtime: the main git worktree resolves to expo automatically (worktrees shared via git rev-parse --git-common-dir).
Stations & the line
A station is an autonomous Claude Code instance, id station-<n>, running in its own managed git worktree (~/.hands/worktrees/<slug>/station-<n>) on its own branch (hands/station-<n>). A station is a generalist: its context is the ticket at hand and its own worktree, and it fans out sub-agents for slices of the work as it sees fit. Between tickets it parks — a persistent Monitor tails its notify file, so an idle station costs nothing. The line is the set of stations collectively.
The sous & the cdc
Two judgment seats beside the expo, each in its own pane and each opt-in (sous.enabled, cdc.enabled). The sous is the one you talk to: the expo’s first escalation hop, and the role that composes recipes into tickets — onto the rail’s queue, unassigned, for the expo to place (see The sous). The cdc (chef de cuisine) is the quality gate: it rules whether a fresh ticket needs a plan, reviews submitted plans and returned PRs, and nothing ships until it has reviewed or explicitly abstained — judge everywhere, producer nowhere. The division in one line: the expo is efficiency, the sous is vision, the cdc is quality.
Tickets, the rail, and dishes
A ticket is a unit of delegated work on the bus, created with hands_delegate. The rail is everything in flight. A dish is the external deliverable — the PR or issue that several rail tickets usually assemble. Ticket states, with their kitchen-facing labels:
| State | On the dashboard | Meaning |
|---|---|---|
open | queued | composed by the sous, not yet assigned — the queue the expo drains onto stations each pass |
assigned | fired | dispatched to a station |
in_progress | cooking | a station claimed it and is working |
returned | at the pass | finished work awaiting the expo's review |
done | served | reviewed and closed |
cancelled | 86'd | killed — off the rail |
Composition and assignment are two different roles’ halves of the rail. The sous composes: it calls hands_delegate without to, and the ticket lands on the queue unassigned. The expo assigns: for it, hands_delegate requires to, and draining the queue onto stations is its first duty each pass. A station never pulls from the queue itself — its own pass only ever asks for tickets assigned to it, and the expo’s obligations sweep chases any open ticket that sits too long.
Recipes, the menu, and the board
A recipe is a principal-authored markdown file — a title, prose, and acceptance criteria written as GFM checkboxes, gherkin-flavoured but not rigidly structured. The menu is the day’s ranked subset of recipes with state: menu — what the kitchen is actually focused on right now, read via hands_menu and considered stale after 24 hours unless reconfirmed. Tickets ladder up to a recipe on the menu: hands_delegate requires it, and rejects a ticket whose recipe isn’t currently promoted. The board is two related things: your external tracker (Linear, GitHub), which Hands references but never owns — and the passive standup digest that the UserPromptSubmit hook injects into each prompt when something actually changed.
Wakes
A wake is the unit of cost: one line appended to an agent’s .notify file, firing its Monitor, costing one full model turn over that agent’s entire accumulated context. Wakes are logged (wakesLastHour / wakes24h on the dashboard) and the whole system is built to minimize them — see Token usage.
Readiness & attestation
Before a station takes work it attests: clean tree, no stashes, on its branch, synced with trunk, worktree lock held, inbox monitor armed. The checks are machine-derived, never self-reported, and the attestation expires on events, not the clock — the trunk advancing, the worktree moving, the lock changing hands. No current attestation, no tickets to that station.
The books
The durable journal: an append-only event log in a local SQLite database, ~/.claude/hands/books.db — machine-wide, not per-repo, so every kitchen on the machine writes into one record under its own <project>/<handle> namespace and can read across all of them. Beside it sit derived daily pages, ~/.claude/hands/books/<project>/<handle>/<date>.md plus a README index per handle: plain markdown you can open or grep, regenerable from the events and safe to delete. The books are load-bearing, never optional — no account, no network, nothing to configure. Every state-changing action is recorded; digests never include message bodies. If it’s not on the books, it didn’t happen.
The split is deliberate: the bus database holds current state, the books hold how it got there. That is also why the record is rows rather than files — a question escalated on Tuesday and answered on Thursday leaves no trace in questions.state, and history in a git-backed NDJSON tree could only be searched by cloning it and parsing every day-file in memory. hands recall --type question.escalate --since 7d answers it as a query. See The books.
Strict pass discipline
The default topology (topology: "strict-hub"): stations may talk only to the expo and the chef. Station-to-station messages and station broadcasts are rejected by the server before anything is written — a blocked send never wakes anyone. topology: "open" opts out of those two.
Who may put a ticket on the rail is a separate, absolute rule that holds in every topology, including open: the sous composes (queued, unassigned) and the expo assigns (named station) — nobody else calls hands_delegate at all. A station can neither fire a ticket at a peer nor assign one to itself; it hands work upward with hands_ask or hands_send({to:'expo'}) and the expo delegates it.
“Hands” — the call
The name does double duty: the fleet is Hands, and calling “hands” on a finished dish is how you summon them to ship it — review, merge, deploy. Even then, the hard gates hold: the fleet does the prep; the chef sends the dish.