Worktree Sessions
Run the agent in its own git worktree, created inside the sandbox. The worktree files live in the VM; the host checkout’s git dir gains a worktrees/<name> registration (.git/worktrees/<name> in a normal checkout).
By default, agents-sandbox runs in the current directory (/workspace). To start an isolated development session in its own worktree, use --worktree <name>[:<base>] (-w). The daemon creates an isolated git worktree inside the VM, but because the checkout bound at /workspace resolves to the host’s git dir — contained in the bound root for a normal or bare checkout, and bind-mounted in separately for an outside worktree — the worktree’s registration also appears in the host’s git dir.
Warning: Each worktree registers in the host checkout’s git dir, and its
gitdirfile points at guest paths:.git/worktrees/<name>in a normal checkout;<bare-root>/.git/worktrees/<name>in a bare checkout whose bare root holds a.gitdirectory;<repo>.git/worktrees/<name>in a bare checkout whose git dir is itself a<repo>.gitdirectory. Hostgit worktree listshows these entries as prunable, but do not rungit worktree pruneon the host while any guest worktree exists, not only while a session is running — it would orphan the guest worktrees and their commits. To clean up, remove the worktree from ashellsession inside the VM first; the host registration disappears with it.
Note: Requires a daemon-based agent. Worktrees are created through the agent daemon’s worktree API, so
--worktreeonly works with daemon-based agents (opencode, opencode2); it is rejected forpi,claude-code,codex,hermes, andoh-my-pi, which run through the interactive TUI instead.
Basic usage
agents-sandbox # run in /workspace
agents-sandbox -w bugfix-fix-thing # run in an isolated worktree
agents-sandbox -w bugfix-fix-thing:main -y # worktree from local base ref
How it works
When you pass --worktree <name>:
- The launcher passes the name to the agent daemon inside the running VM via its worktree API.
- The daemon creates or reuses a worktree inside the VM under the guest home volume (
~/.local/share/opencode/worktree/); foropencode2(v2) the exact layout is~/.local/share/opencode/worktree/<short-project-id>/<name>(the id is a truncated project hash). The daemon’sgit worktree addruns against the checkout bound at/workspace, whose git dir is the host’s — inside the bound root for a normal or bare checkout, and bind-mounted in separately for an outside worktree — so the worktree also registers on the host underworktrees/<name>in that git dir (.git/worktrees/<name>in a normal checkout). - The launcher attaches the agent with the worktree directory as its working directory —
opencode attachtakes it via--dir, whileopencode2takes it as a positional argument. This is where the agent reads source files and writes edits. - The host repository’s working files are not modified, but the host’s git dir is not left untouched: it holds the
worktrees/<name>registration from step 2 (.git/worktrees/<name>in a normal checkout). Hostgit worktree listshows the entry as prunable, but a hostgit worktree prunewhile any guest worktree exists would orphan them and their commits.
Name and base semantics
--worktree <name>: opens the agent in an isolated worktree named<name>, reusing it if it already exists or creating it otherwise.--worktree <name>:<base>: on a fresh create, bases the worktree on the local base ref<base>; on reuse, the base is ignored and a warning is printed. The base must already resolve among the repository’s local refs (no fetch is performed), and it is validated before the worktree is created — an unresolvable base fails without creating anything.- Checkout state depends on the agent:
opencode(v1) leaves the worktree on its ownopencode/<name>branch; a given base is reset into it via the daemon’sstartCommand.opencode2(v2) leaves a detached HEAD at the base ref (or at the source tip without a base), so rungit switch -c <branch>to work on a branch.
Validation
<name>must be a slug for both agents: only lowercase letters, digits, and single hyphens. Names likefeature/fooare rejected immediately.<base>must already exist as a local ref: agents-sandbox never fetches from remotes.
Outside worktrees on the host
You can also launch a normal session from a git worktree you created on the host. A worktree that lives outside its
checkout binds its own root and gets its own identity; the checkout’s shared git dir is mounted read-write at its host
path so git resolves inside the VM. That mount is refused when the shared git dir sits under /workspace or /tmp,
where mounting would shadow the managed mount’s content. agents-sandbox then warns that
git may not resolve inside the VM, and git commands fail with fatal: not a git repository.
When to use
- Feature isolation: Develop a feature without touching the main branch’s files
- Experimentation: Try changes in an isolated path
- Parallel sessions: Run multiple branches simultaneously in different worktrees