Fetched https://x.ai/cli/install.sh and read it, rather than inferring
the layout from docs. Three facts, every one of which the template had
wrong:
· the CLI installs as 'grok' (with an 'agent' alias) — NOT 'grok-build'.
So the drill was checking a command that never existed.
· BIN_DIR defaults to $HOME/.grok/bin, and what lands there is a
SYMLINK into the versioned download dir — which is exactly why the
template's 'find -type f' found nothing.
· GROK_BIN_DIR can override the directory.
The install was almost certainly succeeding the whole time; the template
was hunting for the wrong name, as the wrong file type, in the wrong
place. Now it links the known path onto the system PATH, asserts
'grok --version' answers, and dumps what the installer actually left if
the upstream layout ever moves.
Also corrected: the drill's version check (grok, not grok-build), the
agent briefing ('grok login'), the template description, and the README
row. The lesson is the repo's oldest one — read the thing, don't reason
about it.
The first drill run where every failure was the RELEASE CODE, not the
environment. 71 passed, 5 failed; all five traced to four bugs:
1. migrate-host --retire-legacy could NEVER succeed. Re-homing ADDS
user.box=1 but never removed user.claudebox=1, and legacy_boxes()
counted the old tag — so retire saw its own freshly-migrated box as
un-migrated and refused forever ('legacy boxes still exist:
legacybox'), leaving claudenet + claude-dev behind. Now: a verified
re-home drops the legacy tag LAST (after the move is proven, so a
failure anywhere above still leaves the box valid under one tag or
the other), and legacy_boxes() ignores boxes already carrying
user.box=1.
2. box expose died with a bare 'could not add the proxy device' — it
swallowed incus's reason, exactly the sin this repo keeps punishing.
Now it prints incus's error. And the mechanism is corrected: a VM's
proxy needs NAT mode, which requires a static NIC address, so expose
pins the box's current lease first (which also fixes the restart
caveat — the exposure no longer points at a lease the box may lose).
3. wait_box's 2-minute window was too short: the legacy box was declared
dead and then every migration check against it passed. 4 minutes.
4. The grok template hunted for a regular file named exactly
'grok-build' under /home/grok and found nothing — an installer's drop
may be a SYMLINK, and its binary name is upstream's to choose. Now it
tries the plausible names and paths, falls back to any executable
grok*, links both names, and SAYS what it found — or dumps what the
installer actually left when it finds nothing. The drill likewise
dumps the on-disk evidence and the cloud-init log on a --version
failure instead of discarding the box.
Two things:
1. The host scripts are first-class verbs now — 'box setup-host',
'box teardown-host [--purge-incus]', 'box migrate-host --box <n>'.
Nobody should have to run ~/.local/share/box/host/<script>.sh; that
read like an external script and exposed an install path. Each verb
execs the installed script with its flags passed through (same
pattern as 'box doctor'). README, doctor hints, and the uninstall
section point at the verbs now.
2. The repo-runbook convention is '.box/', not '.claudebox/'. Renamed
across docs and the templates' agent briefing; the briefing tells
the agent to read either, and box-recipe.md notes the rename, so
repos still shipping '.claudebox/' keep working through the
transition. (Consuming repos rename their own folder — tracked
separately.)
Also widened the help command column for the longer verb names, and
fixed one sed-casualty where a broad '.claudebox'→'.box' pass had
turned the README's legacy user.claudebox tag into user.box.
Two coding-CLI templates mirroring claude's shape: a box.env + verbatim
cloud-init, inheriting the box-net placement contract structurally, no
new design.
- codex: OpenAI Codex CLI via 'npm i -g @openai/codex' (the SCOPED
package; needs Node 22), symlinked onto the non-interactive exec PATH
via 'npm prefix -g' — the same PATH fix the claude template needed.
- grok: xAI Grok Build via the official 'curl x.ai/cli/install.sh',
run AS the grok user (the installer drops into $HOME); the binary is
found and symlinked to /usr/local/bin.
Install commands verified upstream at implementation time, per the
issue's rule (npmjs.com/package/@openai/codex, x.ai/cli). Each gets an
AGENTS.md-style context file telling the agent it lives in a
disposable, isolated, creds-free box.
Drill: templates listing now expects four; a compact per-template smoke
(mint, '<cli> --version' via box exec, remove) validates each payload
installs and lands on the exec PATH — the generic mechanic is already
proven by blank+claude and not repeated.
Closes#54