Part of the AgentBox docs. Start at CLAUDE.md.
pnpm build && pnpm lint && pnpm typecheck && pnpm testEach long-running CLI command tees its output to ~/.agentbox/logs/<command>.log
and prints the path on startup. When iterating, don't block on agentbox create
with a long timeout — start it in the background and tail the log instead
(tail -f ~/.agentbox/logs/latest.log). Same for agentbox claude / codex /
opencode. See CLAUDE.md for the full testing/verifying
workflow and the pnpm drive harness for interactive TUIs.
A representative loop:
node apps/cli/dist/index.js create -y -n smoke # tail logs/latest.log
node apps/cli/dist/index.js checkpoint create smoke --set-default
node apps/cli/dist/index.js claude --host-snapshot -y -n cc -- --model sonnet
# (in tmux) Ctrl+a d to detach; reattach with `agentbox claude attach cc`
node apps/cli/dist/index.js status smoke --inspect
node apps/cli/dist/index.js destroy smoke -y
node apps/cli/dist/index.js destroy cc -yFor the full lifecycle command list see docs/features.md.
The box image is pinned to agentbox/box:dev and reused across creates. On
first use the CLI pulls a prebuilt copy from GHCR
(ghcr.io/madarco/agentbox/box) instead of building locally — a multi-minute
build collapses to a docker pull. The pull target is tagged by the
build-context fingerprint (sha-<first 16 hex>, see registryRefForSha() in
image.ts), so the tag is the content identity: a fingerprint that matches a
published build pulls cleanly; one that doesn't (a locally edited baked file)
404s and the CLI builds locally. ensureImage() / DockerProvider.prepare()
go through pullOrBuild().
Force a local build (skip the pull):
agentbox prepare --provider docker --build # or: agentbox create --build
agentbox config set --global box.imageRegistry "" # disable pulling everywhereAfter any change that bakes into the image, wipe the cached copy so the next create rebuilds:
docker rmi agentbox/box:devagentbox self-update does this for you. Anything COPY'd in
packages/sandbox-docker/Dockerfile.box, or listed as a context file in
apps/cli/scripts/stage-runtime.mjs, needs a rebuild — the Dockerfile and the
stage script are the authoritative list.
Wipe everything if state drifts: agentbox prune --all -y.
.github/workflows/box-image.yml builds a multi-arch (amd64 + arm64) manifest
and pushes it to GHCR, tagged sha-<fingerprint>, <cliVersion>, and latest.
It runs on workflow_dispatch, on v* tags, and on main pushes that touch the
build context (Dockerfile.box, the docker scripts, packages/ctl/**,
apps/cli/share/**). The fingerprint is computed by
apps/cli/scripts/print-box-context-sha.mjs (same inputs as the runtime
fingerprint — verified equal locally).
One-time setup: after the first successful publish, make the GHCR package
public (repo → Packages → box → Package settings → Change visibility →
Public), otherwise anonymous docker pull from end users fails and they fall
back to building locally.
macOS (arm64 tested), Docker via OrbStack or Docker Desktop. Container needs
--cap-add=SYS_ADMIN --device=/dev/fuse --security-opt=apparmor:unconfined —
runBox in packages/sandbox-docker/src/docker.ts is the single source of
truth for those flags.
Only @madarco/agentbox (apps/cli) is published. Releases are driven from the
commit history — there is no Changesets step.
-
Generate the notes. Run the
/release-notes [patch|minor|major]slash command in Claude Code from the repo root. It reads the commits since the lastvX.Y.Ztag, curates them into a short user-facing entry (grouped Breaking / Added / Changed / Fixed), and prepends it toapps/cli/CHANGELOG.md. Review and edit the entry — it is a draft, not the final word. -
Cut the release. From
apps/cli, run the matching publish script:pnpm --filter @madarco/agentbox run publish:minor # or publish:patchnpm versionbumpspackage.json; theversionlifecycle script stagesCHANGELOG.mdso both land in one commit; npm tags itvX.Y.Zand the script pushes the commit + tag. That tag is the anchor for the next/release-notes. -
Publish to npm.
cd apps/cli && npm publish(prepublishOnlyrebuilds the workspace first).CHANGELOG.mdships in the tarball (it is in the packagefileslist) — npm surfaces it on the package page.
The first tracked release is tagged v0.9.0; earlier history lives in the git
log.