box/docs/box-recipe.md
dan-claude-bot 86dbb0449e refactor(templates): the tenant seeds carry rig's -box family suffix
rig is growing a second family of roles, and once a 'staging' role can mean
either a fleet machine or a box tenant, the bare name stops naming anything.
rig's answer is a suffix on the role (heavy-duty/rig#76): '-server' for fleet
machines, '-box' for box tenants. box's answer is that a template keeps being
named for the role it converges, so the tenant templates move with it:

  claude  -> claude-box    codex   -> codex-box
  grok    -> grok-box      staging -> staging-box

Templates are the only surface that spells a rig role out loud
(BOX_BOOTSTRAP_ROLE, auto-run at mint since #81), so a directory that says one
thing and a role key that says another is a trap with a 15-minute fuse: it
mints clean and dies at convergence. Renamed with 'git mv' so the history of
each seed follows it.

'blank' keeps its name. It seeds no tenant role and sets no
BOX_BOOTSTRAP_ROLE, so it has nothing to agree with — renaming it would only
churn the default template's name for symmetry's sake.

Two namespaces move apart here and only one of them moved: the template name
and the role are now claude-box, while the seed USER stays 'claude' — that is
the user rig's role converges and the one 'box shell' lands in. test/cli.sh
pins the pair per tenant rather than each half alone, because a later rename
that moves one and forgets the other mints a box whose role dies looking for a
user nobody created. drill.sh keeps its bare box NAMES ('codex', 'grok' — what
the pre-flight banner announces and what teardown deletes) and only moves the
--template it passes.

The mint-time hints in cmd_new match both spellings of user.box.template, and
that is not an alias for the role: 'rig bootstrap claude' is gone and nothing
here softens the cut. The stamp is a fact about an INSTANCE, written at its own
mint time and carried forward by every clone; refusing the old spelling would
cut nothing over and only drop the login hint on boxes that predate today —
the same reason user.claudebox is honored everywhere else. migrate-host.sh
stamps re-homed legacy boxes claude-box, the name the template has today, so a
re-homed box looks like a fresh mint rather than a fossil.

Ordered AFTER rig's rename, and that is not a preference. The seeds install rig
from RIG_REPO/RIG_REF, defaulting to heavy-duty/rig@main and unpinned until
rig#32's releases, so these templates ask whatever main happens to be for
'rig bootstrap claude-box'. Against a pre-rename rig that role does not exist
and cmd_new refuses to call the box ready. Merged in the other order the window
closes instead of opening: rig's cut is hard, with no aliases, so the day it
lands every unmerged box seed naming a bare role is the broken one.

Closes #123

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 00:01:29 +00:00

3.5 KiB

The .box/ convention

box mints trust-less, creds-free, isolated VMs with a coding agent already installed (box new/shell/snapshot/restore/exec/down/start/rm/status) — the claude-box, codex-box, and grok-box templates each ship a CLI agent. The tool knows nothing about your project. There is no install step and no host-run setup script.

A project makes itself easy to stand up inside a box by shipping an optional .box/ folder. This folder is agent-facing documentation — read and acted on by the box's coding agent (the reasoning agent) running inside the box, whichever template you minted. It is not shell that the host executes.

The folder was named .claudebox/ before the 0.5.0 rename. Repos that still ship .claudebox/ keep working — the agent is told to read either — but new projects should use .box/.

What it is / what it is not

  • Optional. No .box/ is a perfectly valid state.
  • Agent-facing. You are writing instructions to a reasoning agent, not a machine. Prose is fine; the agent adapts.
  • Not a host contract. The host never parses, sources, or runs anything in here. There is no enforced schema and no required filenames.
  • Old model: a host-executed .devbox/setup.sh. New model: a runbook the agent reads and decides how to act on.

How it's consumed

Every coding-agent box ships a global agent-context file — ~/.claude/CLAUDE.md for claude, ~/.codex/AGENTS.md for codex, ~/.grok/AGENTS.md for grok — telling the agent it is inside a box and to treat a repo's .box/ folder as its bootstrap runbook. So the whole flow is (shown with claude; the other agents follow the same shape):

box new           # get a box
box shell         # get in
git clone <repo> && cd <repo>
claude                  # the agent reads .box/ and brings the project up

The operator can also just say: "set this project up per .box".

Suggested contents (all optional)

Author everything here for a reasoning agent.

  • .box/SETUP.md — the prose runbook. Prerequisites, how to install deps, how to start services, how to template the env, how to seed data, and how to smoke-test. Written as instructions to the agent.
  • Helper scripts (e.g. .box/dev-up.sh) that the runbook tells the agent to run. The agent decides to run them; the host never does.
  • .box/env.template — example env the runbook explains how to fill. Staging values the operator pastes in. Never commit real secrets.
  • .box/compose.yml — optional services the runbook starts.

Worked example

A minimal .box/SETUP.md for a Node + Postgres app:

# Setup

This is a Node service backed by Postgres.

1. Install deps: `npm ci`
2. Start Postgres: `docker compose -f .box/compose.yml up -d`
3. Create the env file: copy `.box/env.template` to `.env` and ask the
   operator to fill in `DATABASE_URL` and `API_KEY` (staging values).
4. Run migrations: `npm run migrate`
5. Start the app: `npm run dev`
6. Smoke-test: `curl -sf localhost:3000/health` should return `{"ok":true}`.

That's it — the agent reads it top to bottom and adapts if reality differs.

Guidance

  • Keep it declarative and resilient. State intent and steps; let the agent adapt when the repo has drifted. Don't hard-code brittle assumptions.
  • Never put real credentials in .box/. Templates and staging placeholders only. The operator pastes real values at runtime.
  • No .box/ is fine. The operator can stand the project up by hand, or let the agent infer the steps from the repo's README / CLAUDE.md.