Vercel provider backlog: 9 items done + plans for the rest#22
Merged
Conversation
Adds `@agentbox/sandbox-vercel` (`--provider vercel`), a fourth backend
built on @vercel/sandbox (Firecracker microVMs + snapshots), composed via
the shared CloudBackend scaffolding like Daytona/Hetzner.
- Base env baked once via `agentbox prepare --provider vercel` (Vercel can't
build from a Dockerfile): boot node24 → provision.sh → sandbox.snapshot().
- Persistent sandboxes give pause/resume for free (stop auto-snapshots,
get({resume:true}) resumes); destroy purges the box's snapshot.
- Public HTTPS preview URLs via sandbox.domain(port); no in-box dockerd
(no nested containers) and no SSH (custom tmux attach helper over the SDK).
- Checkpoints store the Vercel snapshot id in the cloud-checkpoint manifest.
- OIDC auth decodes the JWT's owner_id/project_id and passes explicit creds
(the SDK's env-OIDC path needs Vercel-CLI linkage a box doesn't have).
Wires registry/argv-prefix/CLI, config (ProviderKind + defaultCheckpointVercel
+ schema), relay resolveCloudBackend, and a launchDockerd opt-out in the cloud
scaffold. Includes unit tests + docs (cloud-providers.md, vercel-backlog.md).
Enumerate the P0 live-smoke items (nothing run end-to-end against real Vercel yet — both dev OIDC tokens were expired), P1 functional gaps (VNC on AL2023, attach latency/ttyd, published-CLI asset staging, builder cleanup, OIDC expiry, per-provider resource config), and P2 deferred parity work (checkpoint list view, per-project snapshot tier, prune, fork, ports, networkPolicy).
…shot status on prepare skip Two bugs found during the first live e2e: - `destroy` purged `currentSnapshotId`, which for a box that hasn't paused is still the snapshot it booted from — so destroying any box deleted the shared base snapshot (and broke every subsequent create with a 410). Guard the purge with `currentSnapshotId !== sourceSnapshotId` so a box's own auto-snapshot is still cleaned but the base / checkpoint source survives. - `prepare`'s skip-fast treated "Snapshot.get didn't throw" as "exists", but the SDK resolves deleted/failed tombstones too (status field). Require status === 'created' so a deleted base triggers a real rebuild. Verified live: prepare bakes the base, create boots from it (user=vscode, /workspace on agentbox/<box>, claude/codex/opencode present, docker correctly unavailable), public *.vercel.run URL resolves, and destroy preserves the base.
…udo works Vercel's AL2023 base ships /etc/sudoers without an includedir for /etc/sudoers.d (and with non-0440 perms), so provision.sh's NOPASSWD drop-in for vscode was silently ignored: `sudo -n` as vscode failed with "a password is required", which broke the cloud workspace seed ($SUDO rm/mkdir/chown) and would break ctl-launch / carry too. provision.sh now appends the includedir, normalises perms to 0440, and visudo-validates. Surfaced while running the remaining P0 live e2e (pause/resume + checkpoint round-trip), now validated 11/11 from the host against a re-baked base. Also: - scripts/vercel-live-e2e.sh: harness for #5/#6 + the destroy/base regression. Reads live SDK status (agentbox list reports cloud boxes as optimistically running), moves the /workspace marker over `agentbox cp`, reads the snapshot id from the checkpoint manifest, uses --carry skip for non-TTY runs. - packages/sandbox-vercel/test/live-state.mjs: live Vercel status helper. - docs/vercel-backlog.md: #5/#6 marked validated; three live bugs documented. - docs/vercel-sandbox-findings.md: platform issues written up for Vercel.
…ner + vercel `agentbox checkpoint ls` showed only docker + daytona; hetzner and vercel cloud checkpoints were invisible. Generalize the command over a CLOUD_BACKENDS list so all four providers are handled uniformly: - ls: merge hetzner + vercel snapshot rows (with the *default marker) - set-default: accept --provider hetzner|vercel and resolve their stores - rm: remove hetzner/vercel snapshots (symmetric with daytona) and sweep the box.defaultCheckpointVercel dangling pointer on delete Closes backlog #13.
…ized pruneCloud The orphan-sandbox prune was daytona-only. Generalize pruneDaytona into a provider-agnostic pruneCloud over a CLOUD_PRUNE_PROVIDERS list so vercel and hetzner (both previously unwired despite working backend.list()) enumerate cloud sandboxes and offer to delete the ones missing from state.json. Closes backlog #15.
The vercel runtime-assets resolver already looked under runtime/vercel/, but stage-runtime.mjs never populated it, and buildVercelAttach only resolved attach-helper.js from the monorepo dist — so --provider vercel worked only from a monorepo checkout. Stage attach-helper.js + provision.sh + ctl/shims + baked config into runtime/vercel/, and add the next-to-dist candidate to resolveAttachHelperPath. Verified all 11 runtime assets resolve from the staged tree with the monorepo fallback disabled. Closes backlog #9.
…expiry) OIDC dev tokens expire on a ~12h cycle and resolveCredentials has no headless refresh, so a long `agentbox prepare --provider vercel` (or CI) can outlive the token. Document the access-token trio as the recommended path for long/headless jobs in cloud-providers.md, and surface the same guidance in the `vercel login` prompt + option labels. Closes backlog #11 (documentation half; auto-refresh stays unbuilt).
prepare left the builder for Vercel's reaper out of caution that delete might cascade to the snapshot. Verified live that it doesn't: a snapshot stays status:created (256MB) and boots a fresh sandbox after its source is deleted. prepare.ts now deletes the builder (step 8) best-effort, after the snapshot id is persisted, so a delete failure leaves at most a lingering sandbox, never a broken bake. Closes backlog #10.
…vercelTimeoutMs)
vcpus and session timeout were hardcoded (2 / 45min). Add flat config keys
box.vercelVcpus + box.vercelTimeoutMs (matching the box.defaultCheckpointVercel
convention) and thread them: config -> providerOptions (vercel-only) ->
cloud-provider resource/timeout overrides -> CloudProvisionRequest.timeoutMs +
resources.cpu -> Sandbox.create({ resources: { vcpus }, timeout }). daytona /
hetzner are untouched (they don't set the override keys). Region stays fixed
iad1 (Vercel constraint).
Verified live: vercelVcpus=4 yields sandbox.vcpus===4 (default 2).
Closes backlog #12.
agentbox-vnc-start hardcoded --web=/usr/share/novnc, but the AL2023 bake git-clones noVNC to /usr/local/share/novnc. websockify does os.chdir(--web) at startup, so the missing dir raised FileNotFoundError and it never bound 6080 (the "agentbox-vnc-start failed: websockify did not bind 6080" symptom). Everything else (Xvnc, vncpasswd, websockify, noVNC assets) was present and Xvnc bound 5901. Resolve the web dir from [/usr/share/novnc, /usr/local/share/novnc] (Debian/Ubuntu first, so docker + hetzner are unaffected). Verified live: 6080 binds, vnc.html HTTP 200, web root /usr/local/share/novnc. The script is in the prepare fingerprint, so the next prepare auto-rebakes. Closes backlog #7.
…s route
The cloud scaffold minted a preview URL per services.*.expose.port, but on
Vercel a URL only routes to a port declared at Sandbox.create({ ports }), and
only [6080, 8788] were declared — so service URLs 404'd. Read the expose ports
before provision and thread them via CloudProvisionRequest.exposePorts; the
vercel backend's buildExposedPorts merges the non-privileged ones (<1024 is a
Vercel 400) onto the base set, capped at Vercel's 4-port limit. daytona/hetzner
ignore the field (one WebProxy routes all ports).
Verified live: expose 3000 -> ports [6080,8788,3000], and the public
domain(3000) URL returns 200 from an in-box server. Unit-tested buildExposedPorts
(privileged-drop, dedupe, 4-cap).
Closes backlog #17.
Surface Vercel's networkPolicy as a config-driven egress lock (the safety win
the backlog flagged, cf. the hetzner firewall). New box.vercelNetworkPolicy:
'allow-all' (default), 'deny-all', or a comma-separated domain allowlist.
Threaded config -> providerOptions (vercel-only) -> CloudProvisionRequest.networkPolicy
-> Sandbox.create({ networkPolicy }); parseNetworkPolicy maps the string to the
SDK shape. daytona/hetzner ignore it (hetzner locks egress via its own firewall).
Verified live: a deny-all box can't resolve example.com; an example.com-allowlist
box reaches example.com (200) but not api.github.com. Unit-tested parseNetworkPolicy.
extendTimeout deferred (niche; session length is set at create via vercelTimeoutMs).
Closes backlog #18 (networkPolicy half).
…tems The 9 actionable items are done. Write concrete implementation plans (from this session's investigation) into the backlog for the heavier/interactive remainder so they can be picked up on the host: - #4 relay round-trip: why nested doesn't work + the host runbook (E2E_RELAY=1) - #8 ttyd attach: bake ttyd + 4th port + ws client rewrite (needs a re-bake) - #14 per-project snapshot tier: prepared-state projects[<hash>] mirroring daytona/hetzner - #16 Sandbox.fork: SDK is ready; needs a finalizeCloudBox refactor of the shared create() + an `agentbox fork` command + a branch-semantics decision
…ection) Two issues Cursor Bugbot flagged on the vercel provider: 1. provision.sh installed the relay-routing git shim at /usr/local/bin/git *before* the VNC step's `git clone` of noVNC. The shim intercepts `clone` (no real-git fallback) and routes to the host relay, which doesn't exist during the bake. It happened to work only because bash had already hashed `git`->/usr/bin/git at the earlier `git config` step — fragile. Move the gh+git shim install dead-last (after every git/gh use, before the /tmp trim). 2. buildRunCommand shell-quoted env *values* but interpolated env *keys* raw into a `bash -lc` string that runs as root — a key like `x;rm -rf /` would inject. Reject keys that aren't POSIX env-var names. Unit-tested the injection guard (valid value still quoted; bad key throws).
- backend.ts: call parseNetworkPolicy(req.networkPolicy) once into a local instead of twice in the conditional spread (truthiness gate + value could diverge if it ever gained side effects). - host-actions.ts: dedupe resolveCloudBackend's triplicated try-catch into a shared loadCloudBackend helper. Kept the per-provider literal `'@agentbox/sandbox-'+'<name>'` import specifiers (not `+ name`) so esbuild still constant-folds + inlines each package via noExternal — a runtime variable specifier would MODULE_NOT_FOUND in the published CLI.
…el AL2023 Found while verifying the git-shim-ordering fix: in a booted vercel box `command -v git` resolves to /opt/git/bin/git (Vercel prepends /opt/git/bin ahead of /usr/local/bin), so the relay-routing shims at /usr/local/bin are inert at runtime — agent-initiated `git push`/`gh pr` hit the real binaries instead of routing through the relay. Document the finding + a host fix plan (prepend /usr/local/bin in the login-shell profile.d shim). Tied to #4.
Sandbox.fork in @vercel/sandbox@2.0.1 just reads the source's last existing snapshot and creates from it -- no fresh snapshot, no memory, no live filesystem read. On Vercel (cold, stop-only snapshots) that is strictly weaker than the existing checkpoint create + create --snapshot path. Mark #16 won't-build with the evidence and a revisit condition (provider ships live/memory snapshots).
…mant hetzner projects tier The per-project snapshot tier already exists: it's the `checkpoint create --set-default` + `box.defaultCheckpoint<Provider>` flow (per-project via hashProjectPath), and auto-capture at end of setup is driven cross-provider by the /agentbox-setup skill (`agentbox-ctl checkpoint --set-default`). The `projects[<hash>]` map #14 proposed would duplicate the checkpoint store, and the Hetzner `projects` field it was modelled on was never wired. - vercel-backlog #14 rewritten as Closed/redundant - removed dormant PreparedProjectSnapshot type + projects field (+ export, test) - reconciled hetzner-backlog deferred notes (answers the inline docker question) - custom-system-CLAUDE.md: clarify vercel snapshots STOP the box; checkpoint only at end of setup, ask for confirmation, else rely on idempotent yaml tasks
- env-loader: read Vercel creds only from ~/.agentbox/secrets.env (drop .env.local harvesting); matches the daytona/hetzner model. Project .env/.env.local belong to the app, not the host CLI. - credentials/cli: token-trio is the primary path (saved to secrets.env); OIDC must be in the shell env or secrets.env. Updated prompts + status msg. - stage-runtime: stage attach-helper.js's transitive ./chunk-<hash>.js into runtime/vercel/ (hash changes each build, so walk the import graph). Without it 'agentbox shell' on a vercel box died ERR_MODULE_NOT_FOUND. - docs: cloud-providers + vercel-backlog reflect secrets.env-only auth.
The old Phase D trusted the 'agentbox shell ... git push' exit code, but on vercel 'shell' goes through the laggy attach pump whose exit code reflects the attach wrapper, not the in-box command — yielding a false PASS on 2026-05-29 (commit never reached origin). Phase D now gates on ground truth: poll origin for the box branch 'agentbox/<box>' appearing after the push (it's absent before). Doc: revert #4 to unconfirmed and record the false-positive analysis.
A third, default-recommended auth mode for the Vercel provider that drives the official 'sandbox'/'sbx' CLI through its browser OAuth, then reuses the CLI's own credentials for our @vercel/sandbox SDK calls — no token to paste, and no 12h OIDC expiry friction. - cli-store.ts: platform-aware reader for the Vercel CLI store (auth.json / config.json); the live vca_ access token is read straight from it on every call (never copied to secrets.env), so the CLI is the self-refreshing source of truth. Only VERCEL_AUTH_SOURCE=cli + team/project ids are cached. - sbx-cli.ts: detect/install/login/refresh driver (mirrors portless.ts). - vercel-rest.ts: minimal fetch wrappers (projects + user) for project pick. - sdk.ts: CLI branch in resolveCredentials() + ensureFreshCredentials(), which triggers the CLI's lazy token refresh (via 'sbx list') when near expiry, with in-process single-flight. Called at the top of every backend op + prepare + attach-helper. - credentials.ts: third default 'cli' select option, runCliLogin() (install prompt -> browser login -> project pick-from-list -> persist), shared writeManaged(), CLI-aware status. PAT-trio and OIDC modes are unchanged, so headless/CI is unaffected. Live-verified end-to-end 2026-05-29 (login -> prepare -> create -> destroy).
The CLI-login auth mode keeps the OAuth token in the Vercel CLI's own store, not in secrets.env (which only carries the VERCEL_AUTH_SOURCE=cli marker + team/project). So the in-box agentbox couldn't use --provider vercel. Add carry entries for the CLI store (auth.json + config.json), mapping the macOS host path (and a Linux host candidate) onto the box's ~/.local/share/com.vercel.cli/ so the in-box CLI-mode resolver reads the live token. optional:true everywhere, so PAT/OIDC users (and hosts without the store) are unaffected.
Owner
Author
|
bugbot run |
Verified end-to-end on box relayv1: in-box agentbox-ctl git push of commit fc6d54de reached origin (git ls-remote confirmed) via the bridge/poller/runGitRpc chain. Root cause of prior failures was a stale host-relay process lacking the vercel executor, plus the secrets.env/chunk/PATH fixes already committed. Records the stale-relay gotcha + ensureRelay follow-up.
The Phase 7 `vercel login --status` rendering for CLI-login mode (async printStatus + s.auth==='cli' branch + relativeExpiry + detectSbx probe) was dropped from 392d38a by a concurrent worktree revert; restore it.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit dd48da9. Configure here.
- vercel-rest.test.ts: non-null assertions on fetchMock.mock.calls[0] so tsc --noEmit (the CI typecheck step) passes under strict null checks. - credentials.test.ts: clear VERCEL_AUTH_SOURCE in setup so the CLI-login marker (set by cli-auth.test.ts in the same worker, or present in the dev machine's secrets.env) can't leak into the trio/none cases.
… the wizard findProjectRoot walks up to the first ancestor agentbox.yaml, so running the wizard fixture in place resolves to the monorepo root: the wizard never fires and the box inherits the root carry/tasks. Document copying the fixture to a temp dir, and fix the smoke-test commands (absolute CLI path) accordingly.
uploadCarryPaths ran its mkdir/tar/chmod/chown one-liner via backend.exec with no user, so Vercel's exec took the default path and wrapped it in `sudo -u vscode -H bash -lc '<cmd>'`. That extra bash -lc nesting mangled the command's $(...)/$var/while parent-chain-chown — $parent expanded empty, `dirname "."` looped forever, and the exec hung (120s/attempt → ~425s with retries, surfacing as 'Stream ended before command finished'). Run the extract as root (user:'root'), which is what the command was already written for (the parent-chain chown comment says 'mkdir -p ran as root') and keeps Vercel on its single bash -lc path. Hetzner/Daytona ignore opts.user (they already run as their default/root user), so this only changes Vercel. Verified live: the exact chown chain hangs 425s as vscode, runs in ~1s exit 0 as root. Added a regression assertion that carry execs with user:'root'.
Per review: don't rely on Hetzner/Daytona ignoring exec opts.user. Gate the user:'root' on backend.name === 'vercel' so the other providers keep their existing (working) carry path unchanged even if they later honor user:. Vercel needs root because its non-root exec wraps in sudo -u vscode -H bash -lc, whose nesting hangs this command. Files still end up vscode-owned (the command chowns to uid 1000), so the in-box vscode user can write them. Tests cover both the vercel (user:root) and non-vercel (unset) paths.
Vercel interactive attach (shell/claude/codex/opencode) was a laggy send-keys/capture-pane poll bridge (attach-helper.ts) because the bundled @vercel/sandbox SDK has no stdin/PTY channel. Replace it with the official `sandbox` CLI's real PTY. - build-attach.ts: emit `sbx exec --sudo [-i] --project <p> --scope <team> <name> -- sudo -u vscode -H bash -lc '<inner>'`. -i only for interactive shell/agent; detached pre-start + logs run non-interactively (live stream). <inner> reuses the shared cloud renderInnerCommand (now exported) so the tmux ensure + footer-aware config + `exec tmux attach` match hetzner/daytona. - Token passed via child env VERCEL_AUTH_TOKEN (not argv → no ps leak): added AttachSpec.env, threaded through wrapped-pty/run.ts (ptySpawn + fallback) and the spawn sites (_cloud-attach runWrappedAttach + runDetached, shell, logs). - Default sbx exec user is vercel-sandbox, so --sudo + `sudo -u vscode -H` runs tmux as the box user in /workspace (passed directly as argv, no outer bash -lc, avoiding a double-reparse). - Deleted attach-helper.ts + its tsup entry + the stage-runtime chunk staging. - credentials.ts: ensureSbxInstalled() now runs for every login mode so attach has the CLI; buildVercelAttach throws an actionable error if it's missing. PoC + live e2e validated (default user, live streaming, env-token auth, tmux-as-vscode, detached pre-start creates a reattachable session). Hetzner/ Daytona attach untouched (no AttachSpec.env). Interactive typing/resize/detach is the remaining manual TTY check.
… as _) sbx exec forwards neither TERM nor the locale (unlike ssh -t), so the box attach session landed in TERM=unknown + an ASCII POSIX locale (charmap ANSI_X3.4-1968). tmux then collapsed Claude Code's Unicode glyphs (logo, braille spinner, box-drawing) to '_'. Prepend `export LANG=C.UTF-8 LC_ALL=C.UTF-8 TERM=xterm-256color` to the attach inner so the tmux server + the agent render UTF-8. Verified live: charmap becomes UTF-8 and ─ ▲ ⠋ ✔ render correctly.
…us shows The cloud create flow registered the box with the host relay BEFORE allocating its per-project index, so the relay recorded projectIndex=undefined and wrote status.json to the legacy no-index path (<id>-<mnemonic>/). But the saved box record got projectIndex=N, so the host reader (agentbox list / wrapped-pty footer / readBoxStatus) derived the <id>-<N>-<mnemonic>/ path and found nothing -> the AGENT column was always empty for cloud boxes even while claude ran. Allocate projectIndex first and pass it into registerBoxWithRelay so the relay keys status.json on the same path the reader uses. Verified live: a fresh vercel box now writes status.json to <id>-1-<name>/ matching its record. (Existing cloud boxes self-heal on the next start/resume — that re-register already passes projectIndex.)
… protocols The leader/Actions footer only matched a raw 0x01 byte. TUIs like Claude Code can switch the terminal into the kitty keyboard protocol or xterm modifyOtherKeys, where Ctrl+a (and plain letters) arrive as escape sequences (ESC[97;5u / ESC[27;5;97~) instead of raw bytes — so the leader silently stopped working under those modes. Teach the input router to decode those encodings for both the leader (Ctrl+a) and the chord keys, while staying precise so cursor/mouse/function CSI sequences still forward untouched. Tests cover kitty + modifyOtherKeys leader, kitty-encoded chords, mixed raw-leader/kitty-chord, double-Ctrl+a literal, and the negative cases (cursor keys and unmodified kitty keys are NOT treated as the leader).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Nine Vercel-provider backlog items — each investigated, implemented, live smoke-tested on Vercel, and committed:
checkpointlist/set-default/rm made provider-complete (hetzner + vercel) via aCLOUD_BACKENDSloopprune --provider vercel(+ hetzner) via a generalizedpruneCloudruntime/vercel/tree (attach-helper + provision.sh + ctl/shims) so--provider vercelworks from the published CLI bundledrive+agent+queue wait-for— automate boxes from a stateless CLI #10 delete the builder sandbox afterpreparesnapshots it (verified the snapshot survives its source's deletion)box.vercelVcpus/box.vercelTimeoutMsconfig →Sandbox.create({ resources: { vcpus }, timeout })ghandgitshims (Claude Code PR badge) #7 fix VNC: resolve the noVNC web dir so websockify binds 6080 on AL2023 (was hardcoded to/usr/share/novnc; AL2023 clones to/usr/local/share/novnc)agentbox.yamlservice ports so their preview URLs route (declare non-privileged ports at create, capped at Vercel's 4)box.vercelNetworkPolicy(allow-all/deny-all/ domain allowlist)Plus a docs commit with host-actionable plans for the 4 remaining heavier/interactive items: #4 relay round-trip, #8 ttyd attach, #14 per-project snapshot tier, #16
Sandbox.fork.Test plan
pnpm typecheck && pnpm lint && pnpm testgreen (592 tests; +11 new unit tests:buildExposedPorts,parseNetworkPolicy)snap_jxQPP…):vercelVcpus=4→sandbox.vcpus===4; VNC binds 6080 +vnc.html200;expose 3000→ publicdomain(3000)200;deny-allblocks egress + allowlist permits only listed domains; builder-cleanup snapshot survival; fullpreparebake--provider vercelfrom the published (non-monorepo) CLI bundle — staging done, end-to-end run pendingNote: this branch is based on
fork-104454; if that was squash-merged intomain, the PR range may include already-merged commits — rebase ontomainif so.Note
Medium Risk
New cloud backend touches credentials, box lifecycle, checkpoints, relay polling, and published CLI assets; several paths were live-tested but full host relay git round-trip from a Vercel box remains unverified in automation.
Overview
Adds a fourth sandbox backend, Vercel Sandbox (
--provider vercel), as@agentbox/sandbox-vercel: Firecracker microVMs on AL2023, one-timeagentbox prepare --provider vercelbase snapshot, SDK exec/upload/preview URLs (no SSH, no nested Docker). Attach uses a stagedattach-helper.jstmux bridge over the SDK; checkpoints store Vercel snapshot ids in the shared cloud-checkpoint manifest.Wires the provider through the CLI (registry,
vercelsubcommand/login, argv sugar), relayresolveCloudBackend, and shared cloud scaffolding: optionallaunchDockerd: false, plus create-timeexposePorts,timeoutMs, andnetworkPolicy(used by Vercel for vCPU/timeout/egress). Config gainsbox.defaultCheckpointVercel,box.vercelVcpus,box.vercelTimeoutMs,box.vercelNetworkPolicy.checkpointandpruneare generalized over daytona/hetzner/vercel;stage-runtime.mjsstagesruntime/vercel/(including attach-helper chunks) for the published CLI.Also:
agentbox.yamlcarry:for Vercel CLI OAuth store paths; VNC noVNC web-root detection for AL2023; destroy avoids deleting the shared base snapshot whencurrentSnapshotIdaliases the source; Hetzner prepared-state drops the unusedprojectsmap (docs aligned). Extensivedocs/vercel-*and cloud-provider updates; relay/git PATH fix on AL2023 is documented in the backlog (provision + profile shim).Reviewed by Cursor Bugbot for commit dd48da9. Configure here.