# How to run OpenCode in a cloud sandbox Install `opencode-ai` with npm in a Linux microVM, store the provider key as a secret, then run `opencode run --auto` on a checkout. **On Runtime, OpenCode's permissive defaults are safe to leave on.** OpenCode starts with most permissions set to allow, and `--auto` approves the rest that are not explicitly denied. Inside a Runtime sandbox that power stops at the edge of a Firecracker microVM with its own kernel, running Ubuntu 24.04 and Node.js 24. The provider key is a Runtime secret: the machine sees a placeholder and the host's proxy supplies the real value only to the provider's API. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the agent waits on the model. OpenCode 1.18.32 was the current npm release on 25 September 2026. | Setup | OpenCode runs | Runtime appears as | | -------------------------- | --------------- | -------------------------------- | | Agent on a remote checkout | In a sandbox | The machine it works on | | Agent on your laptop | On your machine | An MCP server with sandbox tools | ## The provider key OpenCode reaches models through the AI SDK and Models.dev. Its GitHub workflow hands Anthropic's key to the agent as `ANTHROPIC_API_KEY`, so store the key under that name: ```bash no-run printf %s "$ANTHROPIC_API_KEY" | npx withruntime secrets set ANTHROPIC_API_KEY --host api.anthropic.com ``` The variable appears in every sandbox of your account holding a placeholder. Only HTTPS requests to `api.anthropic.com` leave with the real key in their headers. No file or process in the sandbox can leak the value, because it never enters the machine ([secrets sandboxes never see](/docs/security#secrets-sandboxes-never-see)). ## Run OpenCode against a repo ```ts check import { writeFile } from "node:fs/promises"; import { Sandbox } from "withruntime"; const repo = "https://github.com/your-org/your-repo"; const task = "The CSV export drops the last row. Find out why, fix it and add a regression test."; await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 3600 }); const prep = { check: true, timeoutMs: 600_000 } as const; await sbx.exec("npm install -g --prefix /workspace/.local opencode-ai", prep); await sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"], prep); await sbx.network.set({ internet: true, allow: ["api.anthropic.com", "models.opencode.ai", "registry.npmjs.org"], }); const run = await sbx.exec( ["opencode", "run", "--auto", "-m", "anthropic/claude-sonnet-4-5", "--format", "json", task], { cwd: "/workspace/app", env: { OPENCODE_DISABLE_AUTOUPDATE: "1" }, timeoutMs: 1_800_000, onStderr: (text) => process.stderr.write(text), }, ); const events = run.stdout .split("\n") .filter(Boolean) .map((line) => JSON.parse(line)); console.log(run.exitCode, events.length, "events"); await sbx.exec("git add -A && git diff --cached > /workspace/opencode.patch", { cwd: "/workspace/app", check: true, }); await writeFile("opencode.patch", await sbx.files.readText("/workspace/opencode.patch")); ``` ```python check import sys, json from withruntime import Sandbox repo = "https://github.com/your-org/your-repo" task = "The CSV export drops the last row. Find out why, fix it and add a regression test." with Sandbox.create(disk_mib=8192, timeout_seconds=3600) as sbx: sbx.exec("npm install -g --prefix /workspace/.local opencode-ai", check=True, timeout_ms=600_000) sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"], check=True, timeout_ms=600_000) sbx.network.set(internet=True, allow=["api.anthropic.com", "models.opencode.ai", "registry.npmjs.org"]) run = sbx.exec( ["opencode", "run", "--auto", "-m", "anthropic/claude-sonnet-4-5", "--format", "json", task], cwd="/workspace/app", env={"OPENCODE_DISABLE_AUTOUPDATE": "1"}, timeout_ms=1_800_000, on_stderr=sys.stderr.write, ) events = [json.loads(line) for line in run.stdout.splitlines() if line] print(run.exit_code, len(events), "events") sbx.exec("git add -A && git diff --cached > /workspace/opencode.patch", cwd="/workspace/app", check=True) with open("opencode.patch", "w") as file: file.write(sbx.files.read_text("/workspace/opencode.patch")) ``` What matters in that code: - **`opencode run`** is OpenCode's non-interactive mode: it takes the message as arguments, works until the agent finishes and exits, with no TUI. - **`--auto`** approves every permission request that no rule denies. Explicit `"deny"` rules in a repo's `opencode.json` are still enforced. - **`-m provider/model`** picks the model in OpenCode's `provider/model` form. - **`--format json`** prints raw JSON events, one per line, instead of the formatted view. - **The allow list** has a third host. OpenCode's source loads its model catalogue from `models.opencode.ai` (a public list, no key involved), so leaving it reachable keeps model names resolving. - **`OPENCODE_DISABLE_AUTOUPDATE`** stops update checks during a run that should use exactly the version you installed. OpenCode's network guide says it respects `HTTPS_PROXY` and `NODE_EXTRA_CA_CERTS`, which the sandbox image already sets, so it trusts the proxy that adds your key with no extra step. ## Useful `opencode run` flags From OpenCode's CLI and permissions docs, 25 September 2026: | Flag | Does | | ---------------------- | ----------------------------------------------------- | | `--auto` | Approves permissions that are not explicitly denied | | `-m`, `--model` | Model as `provider/model` | | `--agent ` | Uses a named agent from the config | | `-f`, `--file` | Attaches files to the message | | `--format json` | Raw JSON events | | `-c`, `--continue` | Carries on the last session | | `-s`, `--session ` | Carries on a given session; add `--fork` to branch it | | `--dir ` | Directory to run in | For repeated tasks on one checkout, `opencode serve` inside the sandbox and `opencode run --attach` avoid a cold start per task; start the server with `sbx.spawn` so it outlives the command that launched it ([the network](/docs/sandbox-environment#the-network)). ## Give OpenCode sandboxes as tools OpenCode on your own machine can hand code execution to Runtime. OpenCode defines MCP servers under `mcp` in its config, with `type: "local"` and the command as an array. In `~/.config/opencode/opencode.json`: ```json no-run { "$schema": "https://opencode.ai/config.json", "mcp": { "runtime": { "type": "local", "command": ["npx", "-y", "withruntime", "mcp"], "enabled": true } } } ``` The first Runtime call returns a sign-in link and a code. Approve **Connect agent** in the browser and the whole tool set appears, with nothing secret in the config ([MCP](/docs/mcp#add-it-to-your-agent)). OpenCode also takes `type: "remote"` with a `url`, which fits `https://api.withruntime.com/mcp` ([remote connection](/docs/mcp#remote-connection)). | Tool | Lets OpenCode | | ---------------------------- | --------------------------------------------- | | `runtime_sandbox_create` | Start a clean microVM for untrusted code | | `runtime_sandbox_exec` | Run builds and tests there | | `runtime_sandbox_files_list` | List and glob the sandbox's files | | `runtime_image_build` | Bake dependencies into an image for next time | | `runtime_sandbox_manage` | Pause, wake or stop the machine | ## Price of a session Runtime bills the CPU a sandbox uses at $0.025 per vCPU-hour, with a floor of a twentieth of a vCPU, and reserved memory at $0.0075 per GiB-hour. With 2 vCPUs and 4 GiB, a session costs $0.03125 an hour while the model thinks and $0.08 an hour with both cores compiling ([pricing](/docs/pricing)). Token charges come from your model provider. The free trial gives 50 sandbox hours without a card: ```bash no-run npx withruntime sandbox run --trial -- node --version ``` Other agents set up the same way: [Claude Code](/integrations/claude-code) and [Goose](/integrations/goose). To run a fleet of them, read [a sandbox for coding agents](/use-cases/coding-agent-sandbox). ## Sources Checked 25 September 2026. - [OpenCode intro](https://opencode.ai/docs/): `npm install -g opencode-ai` - [CLI](https://opencode.ai/docs/cli/): `opencode run` and its flags, `OPENCODE_DISABLE_AUTOUPDATE` - [Permissions](https://opencode.ai/docs/permissions/): `--auto` and the permissive defaults - [MCP servers](https://opencode.ai/docs/mcp-servers/): `mcp`, `type: "local"`, `command`, `type: "remote"` - [Network](https://opencode.ai/docs/network/): `HTTPS_PROXY` and `NODE_EXTRA_CA_CERTS` - [OpenCode source, models-dev.ts](https://github.com/sst/opencode/blob/dev/packages/core/src/models-dev.ts): the model catalogue at `models.opencode.ai` - [opencode-ai on npm](https://www.npmjs.com/package/opencode-ai): version 1.18.32 Facts on this page were checked on 25 September 2026.