@madarco/agentbox 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/{chunk-3NCUES35.js → chunk-6VTAPD4H.js} +123 -112
  2. package/dist/chunk-6VTAPD4H.js.map +1 -0
  3. package/dist/{chunk-J35IH7W5.js → chunk-7J5AJLWG.js} +61 -23
  4. package/dist/chunk-7J5AJLWG.js.map +1 -0
  5. package/dist/{chunk-3JKQNOXP.js → chunk-FJNIFTWK.js} +66 -65
  6. package/dist/chunk-FJNIFTWK.js.map +1 -0
  7. package/dist/{chunk-IDR4HVIC.js → chunk-HPZMD5DE.js} +2 -2
  8. package/dist/chunk-HPZMD5DE.js.map +1 -0
  9. package/dist/{chunk-MOC54XL6.js → chunk-PXUBE5KS.js} +376 -245
  10. package/dist/chunk-PXUBE5KS.js.map +1 -0
  11. package/dist/{chunk-SOMIKEN2.js → chunk-RFC5F5HR.js} +272 -214
  12. package/dist/chunk-RFC5F5HR.js.map +1 -0
  13. package/dist/create-AHZ3GVEZ-TGEDL7UX.js +15 -0
  14. package/dist/index.js +2760 -1857
  15. package/dist/index.js.map +1 -1
  16. package/dist/{lifecycle-YTMZYKOE-TD5S5FTS.js → lifecycle-LFOL6YFM-TCHDX3J5.js} +5 -5
  17. package/dist/{state-ZSP3ORXW-WI6KOIG3.js → state-KD7M46ZP-KHFTHFUS.js} +2 -2
  18. package/dist/stats-Z4BVJODD-HEC4TMUZ.js +19 -0
  19. package/package.json +3 -2
  20. package/runtime/docker/Dockerfile.box +53 -20
  21. package/runtime/docker/apps/cli/share/agentbox-setup/SKILL.md +39 -50
  22. package/runtime/docker/packages/ctl/dist/bin.cjs +219 -148
  23. package/runtime/docker/packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup +42 -0
  24. package/runtime/docker/packages/sandbox-docker/scripts/custom-system-CLAUDE.md +26 -15
  25. package/runtime/relay/bin.cjs +288 -12
  26. package/share/agentbox-setup/SKILL.md +39 -50
  27. package/dist/chunk-3JKQNOXP.js.map +0 -1
  28. package/dist/chunk-3NCUES35.js.map +0 -1
  29. package/dist/chunk-IDR4HVIC.js.map +0 -1
  30. package/dist/chunk-J35IH7W5.js.map +0 -1
  31. package/dist/chunk-MOC54XL6.js.map +0 -1
  32. package/dist/chunk-SOMIKEN2.js.map +0 -1
  33. package/dist/create-SE6H4B5U-IWAZHJHV.js +0 -15
  34. package/dist/stats-GZFLPYTU-DBJ2DVBJ.js +0 -19
  35. /package/dist/{create-SE6H4B5U-IWAZHJHV.js.map → create-AHZ3GVEZ-TGEDL7UX.js.map} +0 -0
  36. /package/dist/{lifecycle-YTMZYKOE-TD5S5FTS.js.map → lifecycle-LFOL6YFM-TCHDX3J5.js.map} +0 -0
  37. /package/dist/{state-ZSP3ORXW-WI6KOIG3.js.map → state-KD7M46ZP-KHFTHFUS.js.map} +0 -0
  38. /package/dist/{stats-GZFLPYTU-DBJ2DVBJ.js.map → stats-Z4BVJODD-HEC4TMUZ.js.map} +0 -0
@@ -13,12 +13,12 @@ import {
13
13
  startBox,
14
14
  stopBox,
15
15
  unpauseBox
16
- } from "./chunk-3JKQNOXP.js";
16
+ } from "./chunk-FJNIFTWK.js";
17
17
  import {
18
18
  SNAPSHOTS_ROOT
19
- } from "./chunk-MOC54XL6.js";
20
- import "./chunk-IDR4HVIC.js";
21
- import "./chunk-SOMIKEN2.js";
19
+ } from "./chunk-PXUBE5KS.js";
20
+ import "./chunk-HPZMD5DE.js";
21
+ import "./chunk-RFC5F5HR.js";
22
22
  export {
23
23
  AmbiguousBoxError,
24
24
  BoxNotFoundError,
@@ -35,4 +35,4 @@ export {
35
35
  stopBox,
36
36
  unpauseBox
37
37
  };
38
- //# sourceMappingURL=lifecycle-YTMZYKOE-TD5S5FTS.js.map
38
+ //# sourceMappingURL=lifecycle-LFOL6YFM-TCHDX3J5.js.map
@@ -10,7 +10,7 @@ import {
10
10
  removeBoxRecord,
11
11
  resolveBoxRef,
12
12
  writeState
13
- } from "./chunk-IDR4HVIC.js";
13
+ } from "./chunk-HPZMD5DE.js";
14
14
  export {
15
15
  STATE_DIR,
16
16
  STATE_FILE,
@@ -23,4 +23,4 @@ export {
23
23
  resolveBoxRef,
24
24
  writeState
25
25
  };
26
- //# sourceMappingURL=state-ZSP3ORXW-WI6KOIG3.js.map
26
+ //# sourceMappingURL=state-KD7M46ZP-KHFTHFUS.js.map
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ agentboxHomeBytes,
4
+ allCheckpointImagesBytes,
5
+ boxResourceStats,
6
+ parseDockerSize,
7
+ projectCheckpointImageBytes,
8
+ volumeSizeBytes
9
+ } from "./chunk-7J5AJLWG.js";
10
+ import "./chunk-RFC5F5HR.js";
11
+ export {
12
+ agentboxHomeBytes,
13
+ allCheckpointImagesBytes,
14
+ boxResourceStats,
15
+ parseDockerSize,
16
+ projectCheckpointImageBytes,
17
+ volumeSizeBytes
18
+ };
19
+ //# sourceMappingURL=stats-Z4BVJODD-HEC4TMUZ.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madarco/agentbox",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Launch Claude Code, Codex, and other coding agents in isolated sandboxes",
5
5
  "license": "MIT",
6
6
  "author": "Marco D'Alia",
@@ -55,9 +55,10 @@
55
55
  "tsup": "^8.3.5",
56
56
  "typescript": "^5.7.2",
57
57
  "vitest": "^2.1.8",
58
- "@agentbox/config": "0.0.0",
59
58
  "@agentbox/core": "0.0.0",
59
+ "@agentbox/relay": "0.0.0",
60
60
  "@agentbox/ctl": "0.0.0",
61
+ "@agentbox/config": "0.0.0",
61
62
  "@agentbox/sandbox-docker": "0.0.0"
62
63
  },
63
64
  "scripts": {
@@ -2,14 +2,24 @@
2
2
  #
3
3
  # Layered on Microsoft's devcontainers base:ubuntu (arm64-native — the
4
4
  # `universal:2-linux` image is amd64-only, which is a non-starter on Apple
5
- # Silicon hosts). We add the bits the box needs to mount a FUSE overlay over
6
- # /host-src + /upper, plus a "universal-ish" set of language runtimes
7
- # (Node.js 22 from NodeSource, Python 3 from apt). Anything heavier (Go, Java,
8
- # Ruby, .NET, browser tooling, vscode-server) goes in a later iteration.
5
+ # Silicon hosts). /workspace is a plain dir in the image's writable layer:
6
+ # `agentbox create` populates it via in-container `git worktree add` (or a
7
+ # tar pipe for the no-git case). The old FUSE overlay over /host-src+/upper
8
+ # is gone but fuse3 + fuse-overlayfs stay because the in-box dockerd uses
9
+ # fuse-overlayfs as its storage driver. Plus the "universal-ish" set of
10
+ # language runtimes (Node.js 22 from NodeSource, Python 3 from apt). Heavier
11
+ # tooling (Go, Java, Ruby, .NET, more browser tooling, vscode-server) goes in
12
+ # a later iteration.
9
13
  #
10
- # Required runtime flags:
14
+ # Required runtime flags (SYS_ADMIN + /dev/fuse + apparmor:unconfined are now
15
+ # load-bearing only for the *inner* dockerd — keep them):
11
16
  # --cap-add=SYS_ADMIN --device=/dev/fuse --security-opt=apparmor:unconfined
12
- FROM mcr.microsoft.com/devcontainers/base:ubuntu
17
+ #
18
+ # Pinned to ubuntu-24.04 (Noble), NOT the rolling `:ubuntu` tag: that tag now
19
+ # tracks Ubuntu 26.04, which has no Playwright Chromium build for arm64
20
+ # ("Playwright does not support chromium on ubuntu26.04-arm64") and would also
21
+ # break the t64-suffixed Chrome runtime libs below. Bump deliberately.
22
+ FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
13
23
 
14
24
  USER root
15
25
 
@@ -62,9 +72,9 @@ RUN apt-get update \
62
72
  vim \
63
73
  libcap2-bin \
64
74
  && rm -rf /var/lib/apt/lists/* \
65
- && mkdir -p /workspace /host-src /upper /snapshot /run/agentbox /var/log/agentbox \
66
- && chmod 755 /workspace /host-src /upper /snapshot \
67
- && chown vscode:vscode /run/agentbox /var/log/agentbox
75
+ && mkdir -p /workspace /run/agentbox /var/log/agentbox \
76
+ && chmod 755 /workspace \
77
+ && chown vscode:vscode /workspace /run/agentbox /var/log/agentbox
68
78
 
69
79
  # The in-box supervisor (runs as non-root `vscode`) owns a TCP forwarder that
70
80
  # binds container :80 -> the `expose:`-flagged service (see WebProxy /
@@ -74,6 +84,19 @@ RUN apt-get update \
74
84
  # sandbox — strictly narrower than the existing NET_ADMIN/seccomp=unconfined.
75
85
  RUN setcap cap_net_bind_service=+ep "$(readlink -f "$(command -v node)")"
76
86
 
87
+ # Enable corepack (pnpm/yarn shims) at build time as root. Doing this here
88
+ # rather than in the wizard's install task avoids two failures the runtime
89
+ # `corepack enable` (run as non-root `vscode`) hits: it can't write shims into
90
+ # the root-owned NodeSource bin dir (/usr/bin), and node 22's bundled corepack
91
+ # resolves its dist path relative to the symlink dirname, so a
92
+ # ~/.local/bin/pnpm symlink looks for ~/.local/dist/pnpm.js and breaks.
93
+ # `corepack@latest` fixes the symlink resolution; baking the shims into
94
+ # /usr/bin makes them root-owned-but-world-executable so `vscode` just uses
95
+ # them (each project's `packageManager` version is lazily fetched into the
96
+ # writable ~/.cache/node/corepack on first use, inside the install task).
97
+ RUN npm install -g corepack@latest \
98
+ && corepack enable pnpm yarn
99
+
77
100
  # Host repos are bind-mounted in at their identical absolute path (worktree
78
101
  # pointer files contain absolute paths to <main>/.git/worktrees/<name>, so both
79
102
  # sides have to resolve the same path), and the host owns those `.git/` dirs.
@@ -86,8 +109,9 @@ RUN git config --system --add safe.directory '*'
86
109
  # in /etc/docker/daemon.json) lets the agent run `docker build`/`docker run`
87
110
  # in its own namespace without exposing the host daemon. fuse-overlayfs is
88
111
  # required because the kernel `overlay` driver isn't usable from an
89
- # unprivileged container — but fuse3 + fuse-overlayfs are already installed
90
- # above for the /workspace overlay, so docker reuses them. iptables is needed
112
+ # unprivileged container — fuse3 + fuse-overlayfs are installed above
113
+ # specifically for this (the outer /workspace overlay is gone, but the inner
114
+ # dockerd still needs them). iptables is needed
91
115
  # for inner-container bridge networking. Adding `vscode` to the `docker` group
92
116
  # lets the agent invoke `docker` without sudo once dockerd creates the socket
93
117
  # at /var/run/docker.sock at runtime. The matching launch script is COPY'd in
@@ -109,12 +133,13 @@ RUN apt-get update \
109
133
  COPY packages/ctl/dist/bin.cjs /usr/local/bin/agentbox-ctl
110
134
  RUN chmod +x /usr/local/bin/agentbox-ctl
111
135
 
112
- # Setup guide for the first-run wizard. The CLI also installs the same file as
113
- # a host-side claude skill (~/.claude/skills/agentbox-setup/SKILL.md) the
114
- # first time the wizard fires; the existing ~/.claude rsync flow propagates
115
- # it into every box automatically. Keeping a copy baked into the image at a
116
- # stable path guarantees the wizard's initial prompt can reference the guide
117
- # even on hosts where the user wiped their ~/.claude/skills.
136
+ # Setup guide for the first-run wizard. This baked copy is the single source
137
+ # of the /agentbox-setup skill: seedSetupSkillIntoVolume()
138
+ # (packages/sandbox-docker/src/claude.ts) copies it into the box's
139
+ # claude-config volume at skills/agentbox-setup/SKILL.md on create /
140
+ # `claude start`. It is intentionally box-only the CLI never writes the
141
+ # skill to the host's ~/.claude. The stable path also lets the wizard's
142
+ # initial prompt reference the guide directly.
118
143
  COPY apps/cli/share/agentbox-setup/SKILL.md /usr/local/share/agentbox/setup-guide.md
119
144
  RUN chmod 0644 /usr/local/share/agentbox/setup-guide.md
120
145
 
@@ -251,6 +276,14 @@ RUN chmod +x /usr/local/bin/agentbox-vnc-start
251
276
  COPY packages/sandbox-docker/scripts/agentbox-dockerd-start /usr/local/bin/agentbox-dockerd-start
252
277
  RUN chmod +x /usr/local/bin/agentbox-dockerd-start
253
278
 
279
+ # Pre-`docker commit` cleanup for checkpoints. Baked into the image so the host
280
+ # can always reach it via `docker exec --user root <ctr>
281
+ # /usr/local/bin/agentbox-checkpoint-cleanup` regardless of the in-box state
282
+ # (e.g. an agent that swapped its login shell). Best-effort: every step is
283
+ # allowed to fail.
284
+ COPY packages/sandbox-docker/scripts/agentbox-checkpoint-cleanup /usr/local/bin/agentbox-checkpoint-cleanup
285
+ RUN chmod +x /usr/local/bin/agentbox-checkpoint-cleanup
286
+
254
287
  # tmux config so Claude's true-color output and OSC 8 hyperlinks survive the
255
288
  # in-container tmux. `terminal-features` is a no-op on tmux < 3.4. Without
256
289
  # this, claude renders without 24-bit color (logo invisible) and hyperlinks
@@ -310,8 +343,8 @@ RUN printf '%s\n' \
310
343
  > /etc/profile.d/agentbox.sh \
311
344
  && chmod 0644 /etc/profile.d/agentbox.sh
312
345
 
313
- # Default to the vscode user (UID 1000) provided by base:ubuntu. The overlay
314
- # mount itself happens via `docker exec --user root`, so this is just the
315
- # default identity for interactive shells.
346
+ # Default to the vscode user (UID 1000) provided by base:ubuntu. /workspace is
347
+ # pre-chowned to vscode above so `agentbox create`'s in-container
348
+ # `git worktree add` (run as vscode via docker exec) can write to it.
316
349
  USER vscode
317
350
  WORKDIR /workspace
@@ -5,7 +5,21 @@ description: Generate an agentbox.yaml for the current AgentBox workspace. Invok
5
5
 
6
6
  # /agentbox-setup
7
7
 
8
- Goal: produce a `/workspace/agentbox.yaml` that captures this project's services, tasks, and box defaults so the in-box supervisor (`agentbox-ctl`) can boot the workspace deterministically.
8
+ ## Box layout (what you're configuring against)
9
+
10
+ Your user i `vscode` and you can use passwordless sudo to run commands as root.
11
+
12
+ `/workspace` is the box's plain writable filesystem — a per-box git worktree on a fresh `agentbox/<box-name>` branch (or a tar-piped copy of the host workspace for non-git projects). Anything you install or build into `/workspace` (incl. `node_modules`, `.next`, `target`, `.venv`) lives in the **container's writable layer** and is captured wholesale by `agentbox checkpoint` (`docker commit`) — so a setup task that runs the install once becomes a warm-start asset for every future box in the project. Everything is wiped on `agentbox destroy`.
13
+
14
+ Three bind mounts wire the box back to the host:
15
+
16
+ - **Host main repo's `.git/`** — bind-mounted RW at its identical absolute host path. In-box commits land on the host's branch refs (visible to `git log` on the host immediately); the box itself carries no SSH/git creds, so `git push` goes through the host relay (`agentbox-ctl git push`). The host's **working tree is never written to** — only refs/objects under `.git/`.
17
+ - **`~/.claude`** — a Docker named volume (`agentbox-claude-config`, shared across boxes by default) seeded from the host's `~/.claude` on each create so auth, skills, and plugins persist without leaking the host's home dir.
18
+ - **`agentbox.yaml`** — read by `agentbox-ctl` from `/workspace`. Tasks and services declared here are what the supervisor will run.
19
+
20
+ ## Goal
21
+
22
+ Produce a `/workspace/agentbox.yaml` that captures this project's services, tasks, and box defaults so the in-box supervisor (`agentbox-ctl`) can boot the workspace deterministically.
9
23
 
10
24
  `agentbox.yaml` is **declarative**. The supervisor reads it on box start, but you don't have to restart the box: after you write the file, `agentbox-ctl reload` (run from inside the box) makes the already-running supervisor re-read it and immediately run the declared tasks and autostart the services. See step 8.
11
25
 
@@ -23,10 +37,12 @@ Look at `/workspace`:
23
37
  ## 2. Pick services and tasks
24
38
 
25
39
  - **Services** = long-running. Web servers, watchers, queue workers, databases. `restart: on-failure` by default.
26
- - **Tasks** = one-shot. `pnpm install`, DB migrations, codegen, fixture loaders. Wire dependent services with `needs:` so they wait for the task to finish successfully.
40
+ - **Tasks** = one-shot. `pnpm install`, DB migrations, codegen, fixture loaders, install apt packages. Wire dependent services with `needs:` so they wait for the task to finish successfully.
27
41
  - Names: must match `[A-Za-z0-9_-]+`. Task names and service names share a namespace — no collisions.
28
42
  - No cycles in `needs:`.
29
- - **Always generate a dependency-install task** and make it the root of the `needs:` graph (every service that needs deps gets `needs: [install, …]`). The box runs on Linux; the host's `node_modules` (and `.next`, `target`, `.venv`) are macOS-native and now live in the box's writable upper layer, so they must be rebuilt **inside** the box. The task must be **idempotent and self-healing**: `agentbox-ctl` re-runs pending tasks on every box stop/start (the daemon dies with the container and is relaunched), so a plain `rm -rf node_modules && install` would wipe + reinstall on every start. Guard the rebuild with a marker file *inside* `node_modules` (the `.agentbox-installed` convention AgentBox uses internally): rebuild only when the marker is absent (fresh box, or a stale host-leaked `node_modules`), and be a fast no-op once it exists. Detect the package manager from the lockfile — never hardcode `pnpm`. See the worked example below.
43
+ - **Always generate a dependency-install task** and make it the root of the `needs:` graph (every service that needs deps gets `needs: [install, …]`). Future boxes start from a snapshot of the final filesystem so they won't need this, but updates or moving to a cloud provider might need to rebuild the container from scratch. The filesystem can be then later captured by `agentbox-ctl checkpoint --set-default`. The task must be **idempotent and self-healing**: `agentbox-ctl` re-runs pending tasks on every box stop/start (the daemon dies with the container and is relaunched), so a plain `rm -rf node_modules && install` would wipe + reinstall on every start. Guard the rebuild with a marker file *inside* `node_modules` (the `.agentbox-installed` convention AgentBox uses internally): rebuild only when the marker is absent (fresh box), and be a fast no-op once it exists. Detect the package manager from the lockfile — never hardcode `pnpm`. See the worked example below.
44
+ - **Add a comment to the beginning** of the file to explain what you did and what issues you encountered, so that future run might use this information in case the project evolves and you need to update the agentbox.yaml file.
45
+ -
30
46
 
31
47
  ## 3. Wire readiness probes (services only)
32
48
 
@@ -61,7 +77,7 @@ Per service:
61
77
 
62
78
  Sets per-project defaults for `agentbox create`/`claude`/`code`/`shell` — same shape as `~/.agentbox/config.yaml`. CLI flags still override. Common keys:
63
79
 
64
- - `box.hostSnapshot` (bool) — frozen APFS clone of the *host* workspace as overlay lower (renamed from `box.snapshot`).
80
+ - `box.hostSnapshot` (bool) — APFS-clone the *host* workspace into a per-box scratch dir before seeding `/workspace` (stabilizes the tar-pipe source).
65
81
  - `box.defaultCheckpoint` (string) — checkpoint new boxes start from (normally you set this via `agentbox-ctl checkpoint --set-default` at the end of setup — see section 9, not by hand).
66
82
  - `box.withPlaywright` (bool) — install `@playwright/cli` globally inside the box.
67
83
  - `box.vnc` (bool) — run Xvnc + noVNC on container port 6080.
@@ -76,6 +92,11 @@ Full key list (run on the host): `agentbox config list --keys`.
76
92
 
77
93
  ```yaml
78
94
  # yaml-language-server: $schema=https://agentbox.dev/schema/agentbox.schema.json
95
+ # This agentbox.yaml setup this Next.js project, and includes:
96
+ # - a postgres database because it's used in the project
97
+ # - an inngest server for queues
98
+ # - a fix to move .turbo/cache folder to the workspace to avoid a permission error during setup
99
+ # - ...
79
100
  defaults:
80
101
  box:
81
102
  withPlaywright: true
@@ -83,30 +104,23 @@ defaults:
83
104
  ide: cursor
84
105
 
85
106
  tasks:
86
- # Idempotent install. node_modules lives in the box's writable upper layer
87
- # (per-box, isolated, captured by `agentbox open --upper`). The host's
88
- # node_modules is macOS-native, so force a clean Linux build the first time
89
- # and self-heal a stale one but skip on every subsequent box start
90
- # (agentbox-ctl re-runs pending tasks after stop/start). Adjust the
91
- # lockfile detection to the project's package manager.
107
+ # Idempotent install. /workspace is the container's writable filesystem, so
108
+ # node_modules persists across pause/stop/start and is captured by
109
+ # `agentbox checkpoint`. The host's node_modules is macOS-native and is
110
+ # never copied in, so force a clean Linux build the first time but skip
111
+ # on every subsequent box start (agentbox-ctl re-runs pending tasks after
112
+ # stop/start). Adjust the lockfile detection to the project's package
113
+ # manager.
92
114
  install:
93
115
  command: |
94
116
  set -e
95
117
  MARKER=node_modules/.agentbox-installed
96
118
  [ -f "$MARKER" ] && { echo "deps installed (marker present) — skip"; exit 0; }
119
+ apt-get update && apt-get install -y postgresql-client
97
120
  rm -rf node_modules
98
121
  if [ -f pnpm-lock.yaml ]; then
99
122
  corepack enable >/dev/null 2>&1 || true
100
123
  pnpm install --frozen-lockfile || pnpm install
101
- elif [ -f yarn.lock ]; then
102
- corepack enable >/dev/null 2>&1 || true
103
- yarn install --frozen-lockfile || yarn install
104
- elif [ -f bun.lockb ] || [ -f bun.lock ]; then
105
- bun install
106
- elif [ -f package-lock.json ]; then
107
- npm ci || npm install
108
- else
109
- npm install
110
124
  fi
111
125
  touch "$MARKER"
112
126
 
@@ -149,44 +163,19 @@ services:
149
163
  1. Write the file to `/workspace/agentbox.yaml`.
150
164
  2. **Apply it live**: from inside the box run `agentbox-ctl reload`. The already-running supervisor re-reads the config and immediately runs the declared tasks and autostarts the services — no box restart needed. It prints the `added` / `removed` / `changed` diff. If it errors because the daemon isn't running, the config is still valid: the next `agentbox start` (or `agentbox create` in this workspace) picks it up automatically.
151
165
  3. Confirm with `agentbox-ctl status`: tasks should be `running` or `done`, autostart services `starting` or `ready`. If something failed, tail it with `agentbox-ctl logs <service>` and fix the config, then `agentbox-ctl reload` again.
152
-
153
- 4. **Then do section 9** — once the box is warmed up (deps installed, services ready), checkpoint it with `agentbox-ctl checkpoint --set-default` so future boxes start ready. This is the real final step; don't stop at hand-off.
166
+ 4. Checkpoint (snapshot) this box writable layer: once the box is warmed up (deps installed, services ready), checkpoint it with `agentbox-ctl checkpoint --set-default` so future boxes start ready.
154
167
 
155
168
  5. Tell the user:
156
169
 
157
170
  > I wrote `/workspace/agentbox.yaml` and ran `agentbox-ctl reload` so the supervisor is already running the declared tasks/services. To land the file on the host:
158
171
  > - I've created a checkpoint of the warm box state so future boxes start ready in seconds, no reinstall.
159
172
  > - commit it inside the box (`git add agentbox.yaml && git commit -m 'add agentbox config'`) — the box's `.git/` is bind-mounted, so the commit shows up on the host immediately; or
160
- > - on the host, tell the user to run `agentbox pull config` to update their original host workspace.
161
-
162
-
163
- ## 9. Checkpoint the warm state (do this at the very end)
164
-
165
- Once `agentbox-ctl status` shows the install task `done` and services `ready` — i.e. the box is fully warmed up — capture a **checkpoint** so future boxes in this project start from this exact state instead of cold.
173
+ > - on the host, tell the user to run `agentbox download config` to update their original host workspace.
166
174
 
167
- A checkpoint snapshots the box's writable layer, which includes everything you just did:
168
-
169
- - `node_modules` (and `.next`, `target`, `.venv`, build caches) — the expensive Linux-native install,
170
- - `.env` / `.env.*` / `secrets.toml` and any other gitignored config files present in `/workspace`,
171
- - any other files written during setup.
172
-
173
- A new box created from the checkpoint reuses all of it (the install task's marker is already present, so it no-ops), while git-tracked code still comes fresh from the host's current HEAD. Result: new boxes are ready in seconds with no reinstall and no missing env vars.
174
-
175
- **Run this from inside the box, as the final step:**
176
-
177
- ```sh
178
- agentbox-ctl checkpoint --set-default
179
- ```
180
-
181
- This routes through the host relay (no host shell needed), captures `<box-name>-<n>`, and writes `box.defaultCheckpoint` into the project's config so **every future `agentbox create` / `claude` in this project starts warm automatically**. Pass `--name <name>` for a stable name, or omit `--set-default` to capture without changing the default. Re-run it whenever the warm state meaningfully changes (e.g. after a dependency bump you want every new box to inherit).
182
-
183
- Then tell the user, e.g.:
184
-
185
- > I checkpointed the warm box state (node_modules, env files, build caches) and set it as this project's default — `agentbox create` will now spin up new boxes from it in seconds, no reinstall.
186
-
187
- ## 10. Known issues
175
+ ## 9. Known issues
188
176
 
189
177
  - For Nextjs/Vite/Tasnstack projects, makes sure to forward also websocket for hot reload.
190
- - **Turbo/Nx/Jest and other git-worktree-aware tools may try to write their cache to a read-only host path.** The box runs `/workspace` as a git worktree with the host repo's `.git/` bind-mounted at its absolute host path; tools that derive paths from git (Turbo's cache root = the worktree's git *common dir*) resolve outside `/workspace` and hit `EROFS` on the Mac path. Pin the cache into the writable overlay via the task/service `env:`, e.g. `TURBO_CACHE_DIR: /workspace/.turbo/cache` (or pass `--cache-dir`).
178
+
191
179
  - The `install` task is intentionally a no-op once `node_modules/.agentbox-installed` exists. Do **not** remove the marker guard to "force a fresh install" — that reinstalls on every box start. To force a one-off rebuild, delete `node_modules` (or just the marker) then run `agentbox-ctl reload`.
192
- - `.pnpm-store` default location is read only, so you need to point it to a writable location in the box's writable workspace eg: `PNPM_STORE: /workspace/.pnpm-store` and add `.pnpm-store/` to the `.gitignore` if the workspace root is git-tracked.
180
+
181
+ - Host-only CLI wrappers (portless, etc.) must be bypassed, eg some projects wrap the dev server with a host-side proxy (here: `portless projectname next dev --turbopack`). Override the service command: to call the underlying tool directly (`next dev --turbopack`)