Sandbox setup
Install the sandbox plugin, add a sandbox account, and choose what needs your approval.
This page walks you through giving your local OpenCode agent remote sandboxes: install @gitterm/opencode-sandbox, add an account, and decide what needs your approval. Read Sandboxes overview first if you are not sure what a sandbox is. Every field is listed in the Sandbox plugin reference.
Before you start
- OpenCode installed, and a project that is a Git checkout.
sandbox_syncuses Git to decide which files to upload. - One of:
- a key for E2B, Daytona, Vercel, Boat, exe.dev, or Railway, for a direct account, or
- a Gitterm account, for a managed account.
Not sure which? See Managed and direct accounts.
Steps
-
Install the plugin:
Shell opencode plugin add @gitterm/opencode-sandboxThis adds
@gitterm/opencode-sandboxto your global OpenCode config. -
Add an account. In your OpenCode config, replace the plugin entry with an object that has
options:JSONC { "plugins": [ { "package": "@gitterm/opencode-sandbox", "options": { "provider": "e2b", "apiKey": "{env:E2B_API_KEY}" }, }, ], }With an
apiKeyit is a direct account; without one, a managed account. For several accounts, name them underaccounts. -
Optional: set limits and exclusions, turn on public previews, and pre-approve routine actions.
-
Restart OpenCode and ask the agent:
Text Which sandbox account are you using?You should see the selected account and provider, where the key comes from, whether it is present, who is charged, the limits, and the provider's limitations. The key itself is never shown. If the key is missing, fix the variable and restart OpenCode.
Direct accounts
A direct account uses your own provider key: it has provider and apiKey. The provider bills your account. No Gitterm login is needed.
Never type the key into the config. Use OpenCode's substitution, which fills in the value when OpenCode loads the config:
// From an environment variable (set it before starting OpenCode)
"apiKey": "{env:E2B_API_KEY}"
// From a file
"apiKey": "{file:~/.secrets/e2b}"The key stays in the OpenCode process and is sent only to that provider's API. If it is empty or the provider rejects it, the tools fail with an error. They never fall back to another account.
Some providers need more than apiKey:
exe.dev and Railway never delete a sandbox on their own. allowUnboundedLifetime is how you accept that a sandbox left behind by a crash keeps running and billing until you destroy it. Without it, creation is refused. Optional fields, such as an E2B template or a Vercel runtime, are in Account fields.
Managed accounts
A managed account has no apiKey and uses your Gitterm plan. The Gitterm deployment holds the provider account.
-
Sign in with the Gitterm CLI:
Shell npm install -g @gitterm/cli gitterm loginYou should see
Logged in as <your email>. Instead of logging in, you can setGITTERM_API_TOKENbefore starting OpenCode. -
Add the account. On gitterm.dev, pick a size:
JSONC "options": { "size": "medium" }On a self-hosted deployment, add its address. Without
providerit uses the deployment's default: the only provider it offers, or the one its admin prefers. Setproviderto pick another:JSONC "options": { "serverUrl": "https://gitterm.example.com", "provider": "daytona" }
The provider must be enabled on the deployment and allowed by your plan. If it isn't, the tools say which providers the deployment offers, and that adding apiKey uses your own account instead. Creation also checks your run allowance and your workspace limit, which counts sandboxes too.
Several accounts
Name each account under accounts, and pick the one the tools use with account:
"options": {
"account": "e2b",
"accounts": {
"e2b": { "provider": "e2b", "apiKey": "{env:E2B_API_KEY}" },
"gitterm": { "size": "medium" }
}
}The account name is what approval rules match. A single account in options is named after its provider, or gitterm when it has none.
Limits and exclusions
limits caps what the agent can start. exclude lists extra glob patterns that sandbox_sync never uploads. Secret-like files are always left out; see Security.
"options": {
"provider": "e2b",
"apiKey": "{env:E2B_API_KEY}",
"limits": { "maxSandboxes": 2, "maxLifetimeMinutes": 60, "defaultLifetimeMinutes": 30, "maxJobMinutes": 30 },
"exclude": ["fixtures/large/**"]
}The values above are the defaults. What each limit does is in Limits.
Setup snapshots
For a project with a slow setup, let the agent save a sandbox once dependencies are installed. The project's next sandboxes start from it, ready to run.
"options": { "provider": "e2b", "apiKey": "{env:E2B_API_KEY}", "snapshots": true }- Works on E2B, Daytona, Vercel and Boat, with your own key or a Gitterm plan, and on Gitterm's own machines. On a plan, snapshots need Pro or Growth; see Plans.
- The agent gets a
sandbox_snapshottool. OpenCode asks before each save or delete; allowgitterm.sandbox.snapshotunder Approvals to skip the prompt. - A project can have several snapshots, such as one with dependencies and one with dependencies and a database. New sandboxes start from the project's newest one unless the agent picks another.
- When a lockfile changed since a snapshot, the agent is told. It can then save a replacement, which deletes the old one. Until it does, the old one is still used.
- On Vercel, saving a snapshot ends the sandbox it was saved from.
- Snapshots stay in the provider account until deleted. On a Gitterm plan they are listed under Agent sandboxes in the dashboard, where you can delete them.
To start every sandbox from a snapshot you made yourself, set snapshot on the account instead. The agent then does not manage snapshots for that account.
"options": { "provider": "e2b", "apiKey": "{env:E2B_API_KEY}", "snapshot": "my-snapshot:latest" }Approvals
OpenCode asks you before each of these actions. The resource is what a saved rule matches.
These need no approval: sandbox_list, sandbox_job (including cancelling a job), sandbox_artifact (it downloads to a staging directory only), and sandbox_destroy. A denied action stops before anything is uploaded, created, or written.
To approve routine work once, add permissions rules to opencode.json. This example allows creating sandboxes and running commands on the e2b account, and always denies public previews:
{
"permissions": [
{ "action": "gitterm.sandbox.provision", "resource": "e2b:e2b", "effect": "allow" },
{ "action": "gitterm.sandbox.exec", "resource": "e2b:*", "effect": "allow" },
{ "action": "gitterm.sandbox.public", "resource": "*", "effect": "deny" },
],
}The publicPreviews option skips the public-previews prompt, so a deny rule for gitterm.sandbox.public has no effect while it is on.
Use the CLI instead
The Gitterm CLI has the same sandbox commands (gitterm sandbox ...) and the same settings, including publicPreviews. The difference: it reads them from ~/.config/gitterm/sandbox.json, and keys come from apiKeyEnv, the name of an environment variable. A literal apiKey or token in that file is refused. See CLI reference.