Configuration keys

User config keys and how the layers resolve

AgentBox reads layered defaults at the start of every command. The same key shape lives in three files plus a runtime CLI-flag layer, so a preference can be a one-off flag, sticky for one project, or shared with your whole team.

You rarely need to touch config — every key has a built-in default and most surfaces also expose a one-off CLI flag. Config is for making a preference stick.

TIP

Don't memorize keys. agentbox config list prints every key with its current value and where it came from, and agentbox config list --include-advanced adds the advanced ones.

Config layers

AgentBox merges four layers on top of the built-in defaults. Highest layer that sets a key wins:

CLI flag > workspace defaults: > per-project > global > built-in default
LayerWhere it livesScope
CLI flagthe command you typethis invocation only, never persists
workspacethe defaults: block in agentbox.yamlcommitted, shared with the team
per-project~/.agentbox/projects/<hash>/config.yamlper machine, per user, not committed
global~/.agentbox/config.yamlevery project on this machine
built-inBUILT_IN_DEFAULTS in the CLIthe fallback for any unset key

The per-project <hash> is the first 16 hex chars of the SHA-1 of the project's absolute path. The workspace layer is found by walking up from the current directory to the nearest agentbox.yaml.

config set/unset/edit only write the --global or --project files (project is the default). The committed defaults: block is hand-edited — see agentbox.yaml for its full schema. engine.kind is the one key applied at CLI startup; every other key flows through the per-command effective-config load.

Config resolution order: the highest layer that sets a key wins; unset keys fall through to the built-in default.

The config command

Seven subcommands: get, set, unset, list, path, edit, list-projects. The default write scope is --project. Pass at most one scope flag.

# Read the effective value of a key (and where it came from)
agentbox config get box.provider

# Set a key (default scope is --project)
agentbox config set box.withPlaywright true

# Set a key globally for all projects
agentbox config set box.provider hetzner --global

# Remove a key from a scope (default --project)
agentbox config unset box.image --project

# List effective config; advanced keys hidden unless you ask
agentbox config list
agentbox config list --include-advanced

# List one layer's raw values
agentbox config list --scope global
agentbox config list --scope workspace

# Print or open a scope's file
agentbox config path --workspace
agentbox config edit --global

# Show directories that have per-project config recorded
agentbox config list-projects

config get --all shows every layer's value with its source — the fastest way to see why a key resolved the way it did:

$ agentbox config get box.provider --all
box.provider:
  effective: hetzner   (global ~/.agentbox/config.yaml)
  cli:       <unset>
  workspace: <unset>
  project:   <unset>   ~/.agentbox/projects/3f2a…/config.yaml
  global:    hetzner   ~/.agentbox/config.yaml
  default:   docker

<unset> is the literal token the CLI prints for an absent value. get, set, list, path, and list-projects all accept --json. set coerces the value to the key's declared type (bool/int/enum/string) and errors on an invalid enum or non-int. There is no config set --workspace; to change the committed defaults:, edit agentbox.yaml (or run config edit --workspace, which just opens that file).

WHY

agentbox config get <key> validates the key — an unknown key errors. Use it to sanity-check spelling before set.

HEADS UP

box.snapshot was renamed to box.hostSnapshot. The old name now errors with a migration hint — update any config or agentbox.yaml still using it. AgentBox is pre-1.0, so there are no compatibility aliases.

box.* — the box keys

The largest group. A pattern runs through it: a generic key plus per-provider overrides of the form <key><Provider> (e.g. box.sizeHetzner). The provider-specific form wins over the generic one for that provider. This applies to box.size*, box.image*, and box.defaultCheckpoint*.

Provider

KeyTypeDefaultMeaning
box.providerenum docker/daytona/hetzner/verceldockerbackend new boxes are created on
agentbox config set box.provider hetzner --global

See local Docker, Hetzner, Daytona, Vercel, and core concepts.

Resource limits (Docker)

KeyTypeDefaultMeaning
box.memoryint (MiB)0 (unlimited)hard memory ceiling; use --memory on create for byte/k/m/g strings
box.cpusint0 (unlimited)whole-core cap; use --cpus for fractional like 1.5
box.pidsLimitint0 (unlimited)max PID count
box.diskstring (advanced)emptybest-effort writable-layer size; no-op on overlay2 / macOS engines

VM size (cloud)

KeyTypeDefaultMeaning
box.sizestringemptygeneric cloud size; hetzner reads a server type (cx33), daytona reads cpu-memory-disk GB (4-8-20); docker and vercel ignore it
box.sizeDaytona / box.sizeHetznerstring (advanced)emptyper-provider override of box.size
box.sizeDocker / box.sizeVercelstring (advanced)emptyreserved — docker uses memory/cpus/disk; vercel uses vercelVcpus

Box image

KeyTypeDefaultMeaning
box.imagestring (advanced)agentbox/box:devgeneric image ref; the default is a sentinel cloud backends read as "boot from the prepared base snapshot"
box.imageDocker / box.imageDaytona / box.imageHetzner / box.imageVercelstring (advanced)emptyper-provider override; the cloud ones are written by agentbox prepare --provider <name>
box.imageRegistrystring (advanced, docker only)ghcr.io/madarco/agentbox/boxregistry to pull the prebuilt base from before building locally; empty = always build

HEADS UP

Setting the generic box.image to a provider-native snapshot id breaks creates on other providers. Prefer the per-provider box.image<Provider> keys (which is what prepare writes). If a stale box.image blocks creates, clear it with agentbox config unset box.image --project.

Default checkpoint per project

KeyTypeDefaultMeaning
box.defaultCheckpointstringemptycheckpoint new boxes start from when --snapshot isn't given; set via agentbox checkpoint set-default
box.defaultCheckpointDocker / …Daytona / …Hetzner / …Vercelstring (advanced)emptyper-provider overrides; set via checkpoint set-default --provider <name>

See checkpoints and pausing.

Create-time toggles

KeyTypeDefaultMeaning
box.hostSnapshotboolpromptuse a frozen APFS clone of the host workspace as overlay lower (renamed from box.snapshot)
box.withEnvboolfalsecopy host env/config files (.env*, secrets.toml, agentbox.yaml, …) into /workspace, bypassing gitignore
box.withPlaywrightboolfalseinstall @playwright/cli@latest in the box at create
box.vncbooltruerun the per-box Xvnc + noVNC stack
box.autoApproveHostActionsboolfalseauto-approve host-action confirms (git push, cp, gh PR writes, checkpoint) for this box without a prompt; for unattended orchestration of trusted boxes. Each bypass is logged as a relay event. See orchestration
box.resyncOnStartbooltrueon starting a session, merge the host's current branch + overlay changes (box wins on conflict, warns the agent)
box.bundleDepthintadaptivecap git-bundle history shipped to cloud sandboxes; 0 = full history; ignored for docker
box.dockerCacheSharedboolfalseshare the in-box docker image cache across boxes; only one box can run at a time when set

See teleport a project, environment, browser and screen, sync and git, and Docker in Docker.

Config-volume isolation

KeyTypeDefaultMeaning
box.isolateClaudeConfig / box.isolateCodexConfig / box.isolateOpencodeConfigboolfalsegive the box its own agent config volume instead of the shared one

Vercel only

KeyTypeDefaultMeaning
box.vercelVcpusint2vCPUs (RAM is coupled at 2048 MB/vCPU); only 1/2/4/8 are accepted
box.vercelTimeoutMsint2700000 (45 min)max session length before auto-snapshot; persistent mode auto-resumes
box.vercelNetworkPolicystringempty (allow-all)egress lock: allow-all, deny-all, or a comma-separated domain allowlist (github.com,*.npmjs.org)

See Vercel.

checkpoint.*

KeyTypeDefaultMeaning
checkpoint.maxLayersint (advanced)3max stacked checkpoint layers before a new checkpoint is materialized flattened instead of layered

See checkpoints and pausing.

Agent sessions — claude / codex / opencode

KeyTypeDefaultMeaning
claude.sessionNamestringclaudetmux session name for the claude agent
codex.sessionNamestringcodextmux session name for the codex agent
opencode.sessionNamestringopencodetmux session name for the opencode agent
claude.dangerouslySkipPermissionsbooltruelaunch claude with --dangerously-skip-permissions (auto-accept tool use)
codex.dangerouslySkipPermissionsbooltruelaunch codex with --dangerously-bypass-approvals-and-sandbox

WHY

The permission-skip defaults are on precisely because each box is a throwaway sandbox the agent can't escape — that's the whole point of AgentBox. Turn them off per-box with --no-dangerously-skip-permissions if you want approval prompts. See core concepts and run an agent.

attach

KeyTypeDefaultMeaning
attach.openInenum split/window/tab/samesplitwhere agentbox claude|codex|opencode opens the attached session under tmux, cmux, or iTerm2
attach.cmuxStatusbooltruewhen attached inside cmux, reflect the box agent's activity on its cmux workspace (colour + description)

split uses a tmux split-window / cmux new-split / iTerm2 vertical split (same workspace). tab opens a new tmux window / a new cmux surface (a tab in the current pane, same workspace) / a new iTerm2 tab. window opens a new tmux window / a separate cmux workspace / a new iTerm2 window. Outside tmux/cmux/iTerm2 every value behaves like same. See access your box.

attach.cmuxStatus surfaces a box's agent state in the cmux sidebar. While you're attached inside a cmux surface, AgentBox reflects the agent's live activity on the box's cmux workspace via its colour and description — blue/"working" while the agent runs, amber/"needs input" when it asks a question or is waiting, and the tint clears when idle. The workspace's original colour and description are restored when you detach. When you open several boxes from one project as tabs in the same workspace (--attach-in tab), AgentBox also flags the individual tab whose agent needs input via a cmux notification (tab badge + reorder + a desktop notification), so you can tell which box is waiting; the flag clears when you focus that tab. (cmux only renders its status pills for workspaces running an agent it recognizes; a box runs the agent inside the container, so AgentBox drives the always-visible workspace colour/description and the per-tab highlight instead.) No effect outside cmux; set to false to disable.

code / shell

KeyTypeDefaultMeaning
code.ideenum vscode/cursor/autoautowhich IDE agentbox code launches; auto prefers code, falls back to cursor
code.waitbooltrueblock on agentbox-ctl wait-ready before opening the IDE
code.timeoutMsint120000wait-ready timeout
code.autoTerminalsbooltruegenerate /workspace/.vscode/tasks.json so the IDE auto-opens log panels
shell.userstringvscodedefault in-container user for agentbox shell
shell.loginbooltruepass -l to bash (load login profile)
shell.tmuxbooltruerun inside a detachable tmux session (Ctrl+a d to detach)

See access your box.

browser

KeyTypeDefaultMeaning
browser.defaultenum agent-browser/playwright/bothagent-browserdefault browser stack in the box; playwright or both implies box.withPlaywright

See browser and screen.

queue & autopause

queue.* schedules background -i jobs; autopause.* pauses idle boxes.

KeyTypeDefaultMeaning
queue.enabledbooltruerun agentbox claude|codex|opencode -i <prompt> jobs through the host-wide FIFO queue
queue.maxConcurrentint5max simultaneously-running boxes before -i jobs queue; override with --max-running <n>
queue.maxWorkingint0 (off)max agents actively working at once before -i jobs queue; override with --max-working <n>
queue.idleGraceSecondsint15debounce before an agent frees its working slot; only used when maxWorking > 0
queue.openInenum none/split/window/tabnonewhen a background -i job's box becomes ready, open an attached terminal onto it (a tmux/cmux split, window, or tab); none opens nothing
autopause.enabledbooltruelet the relay periodically pause idle boxes when more than maxRunningBoxes run
autopause.maxRunningBoxesint5target ceiling of running boxes before idle ones get paused
autopause.idleMinutesint5minutes a box must be continuously idle before it's eligible for auto-pause
agentbox config set queue.maxConcurrent 3 --global
agentbox config set autopause.idleMinutes 10 --global
agentbox config set queue.openIn split --global

By default a background -i run just queues and prints its job line. Set queue.openIn to split, window, or tab and the host relay opens an attached terminal onto the box the moment its worker finishes creating it — no need to find the box and attach by hand. It only fires when the submitting shell is inside tmux, cmux, or iTerm2. Under cmux, split splits the pane you submitted from (falling back to the parent workspace, then a new workspace), tab adds a tab in the parent workspace, and window opens a separate workspace; iTerm2 opens relative to the frontmost window. Unlike attach.openIn there is no same mode (the box is created asynchronously, so it is always a fresh terminal).

cmux: allow socket control

The box is opened by the relay's queue worker, a detached host process — not a cmux-initiated one. cmux's default socketControlMode: cmuxOnly only trusts processes cmux itself started, so it blocks the worker and nothing opens. To use queue.openIn under cmux, set socketControlMode to automation (or password) in ~/.config/cmux/cmux.json and run cmux reload-config. tmux and iTerm2 need no such change.

Auto-pause only ever targets a box whose live agent has settled to idle for idleMinutes. A box where any agent (Claude, Codex, or OpenCode) is working, compacting, or waiting on you is never auto-paused. If a box does get paused while you still need it, agentbox drive …, agentbox shell, and agentbox unpause all resume it on demand (drive auto-unpauses before it reaches the session).

See background and parallel and checkpoints and pausing.

cloud / engine / portless / relay / vnc / maintenance

The remaining infrastructure knobs — mostly advanced.

KeyTypeDefaultMeaning
cloud.useCurrentBranchboolfalseon daytona/hetzner, start boxes on the host's current branch instead of forking agentbox/<box-name>; overridden by --use-branch / --from-branch
engine.kindenum orbstack/docker-desktop/other/autoautooverride docker-engine auto-detection; the one key applied at CLI startup
portless.enabledboolpromptmap each box web app to https://<box-name>.localhost via the Portless proxy (Docker Desktop only)
portless.stateDirstring (advanced)emptyhost Portless state dir to share into boxes
relay.portint (advanced)8787host relay TCP port
vnc.containerPortint (advanced)6080container-side noVNC port
maintenance.pruneProjectConfigsbooltrueperiodically delete ~/.agentbox/projects/<hash>/ dirs whose source folder is gone
maintenance.pruneProjectConfigsEveryint50run the orphan sweep every N successful agentbox create

See web apps and tunnels, local Docker, sync and git, and browser and screen.

Where the files live

$ agentbox config path --global
/Users/you/.agentbox/config.yaml
$ agentbox config path --project
/Users/you/.agentbox/projects/3f2a8c1d9e0b4a76/config.yaml
$ agentbox config list-projects
3f2a8c1d9e0b4a76  /Users/you/Projects/myapp
  • Global: ~/.agentbox/config.yaml
  • Per-project user: ~/.agentbox/projects/<sha1-16-of-abs-path>/config.yaml
  • Workspace (committed): the defaults: block in agentbox.yaml

For the defaults: block and the full agentbox.yaml schema, see agentbox.yaml; for secrets and env files, see environment. The served JSON schema lives at /schema/user-config.schema.json.

On this page