Skip to content
Runtime

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. --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. The microVM runs Ubuntu 24.04 and Node.js 24. The provider key is a Runtime secret. The machine sees only 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.19.4 was the current npm release on 25 October 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 passes Anthropic's key to the agent as ANTHROPIC_API_KEY. Store the key under that name:

Terminalprintf %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 the real value never enters the machine (secrets sandboxes never see).

Run OpenCode against a repo

TypeScriptimport { 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"));
Pythonimport sys, jsonfrom withruntime import Sandboxrepo = "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. It has 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. That is a public list and involves no key. Keeping it reachable lets model names resolve.
  • OPENCODE_DISABLE_AUTOUPDATE stops update checks during a run. The run then uses exactly the version you installed.

OpenCode's network guide says it respects HTTPS_PROXY and NODE_EXTRA_CA_CERTS. The sandbox image already sets both. So OpenCode trusts the proxy that adds your key, with no extra step.

Useful opencode run flags

From OpenCode's CLI and permissions docs, 25 October 2026:

Flag Does
--auto Approves permissions that are not explicitly denied
-m, --model Model as provider/model
--agent <name> 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 <id> Carries on a given session; add --fork to branch it
--dir <path> Directory to run in

For repeated tasks on one checkout, run opencode serve inside the sandbox and use opencode run --attach. This avoids a cold start for each task. Start the server with sbx.spawn, so it keeps running after the command that launched it (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{  "$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. The config holds no secrets (MCP). OpenCode also accepts type: "remote" with a url, which suits https://api.withruntime.com/mcp (remote connection).

Tool Lets OpenCode
runtime_sandboxes_create Start a clean microVM for untrusted code
runtime_sandboxes_exec Run builds and tests there
runtime_sandboxes_files_list List and glob the sandbox's files
runtime_images_build Bake dependencies into an image for next time
runtime_sandboxes_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. It bills 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. With both cores compiling, it costs $0.08 an hour (pricing). Token charges come from your model provider. Every account gets 100 free hours of a 1 GB machine in the first 30 days, with no card:

Terminalnpx withruntime sandboxes run -- node --version

Other agents set up the same way: Claude Code and Goose. To run a fleet of them, read a sandbox for coding agents.

Sources

Checked 25 October 2026.

Facts on this page were checked on 25 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card