Skip to content
Runtime

How to run Goose in a cloud sandbox

Install the goose CLI with its download script in a Linux microVM, set provider and model by environment, and run goose run -t.

Runtime gives goose a disposable Linux machine, and it removes the keyring problem at the same time. goose's Docker guide notes that its keyring settings do not work on Ubuntu in a container. The guide has you pass the API key as an environment variable instead. On Runtime, that variable holds only a placeholder. The key is a Runtime secret, and the host's proxy adds the real value to requests to the provider. Every sandbox is a Firecracker microVM with its own kernel and Ubuntu 24.04. While goose waits on the model, 2 vCPUs and 4 GiB cost $0.03125 an hour. The newest stable tag on 25 October 2026 was v1.56.0.

Direction goose runs Runtime is
Headless task on a repo In a sandbox The machine, driven by the SDK
goose session on your laptop On your machine A stdio extension with sandbox tools

Store the provider key

goose reads provider settings from the environment: GOOSE_PROVIDER, GOOSE_MODEL, and the provider's own key variable. For Anthropic, that variable is ANTHROPIC_API_KEY. Only the key is sensitive, so only the key is stored as a secret:

Terminalprintf %s "$ANTHROPIC_API_KEY" | npx withruntime secrets set ANTHROPIC_API_KEY --host api.anthropic.com

Each sandbox in your account now starts with ANTHROPIC_API_KEY set to a placeholder. GOOSE_DISABLE_KEYRING tells goose not to look for a system keyring. The proxy adds the real key only to HTTPS requests to api.anthropic.com (secrets sandboxes never see). Any other provider that goose supports works the same way, with its own variable and host.

A headless run from your code

TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";const repo = "https://github.com/your-org/your-repo";const task =  "Upgrade the project to the current major version of its test runner and fix what breaks.";const installGoose =  "curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash";await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 3600 });const once = { check: true, timeoutMs: 600_000 } as const;await sbx.exec("sudo apt-get update && sudo apt-get install -y bzip2", once);await sbx.exec(installGoose, once);await sbx.exec(["git", "clone", "--depth", "1", repo, "/workspace/app"], once);// goose is installed; from here it may reach the model API and nothing else.await sbx.network.set({ internet: true, allow: ["api.anthropic.com"] });const run = await sbx.exec(  [    "goose",    "run",    "--no-session",    "--with-builtin",    "developer",    "--output-format",    "json",    "--max-turns",    "60",    "-t",    task,  ],  {    cwd: "/workspace/app",    env: {      GOOSE_PROVIDER: "anthropic",      GOOSE_MODEL: "claude-sonnet-4-5-20250929",      GOOSE_MODE: "auto",      GOOSE_DISABLE_KEYRING: "1",      GOOSE_DISABLE_SESSION_NAMING: "true",    },    timeoutMs: 1_800_000,    onStderr: (text) => process.stderr.write(text),  },);console.log(run.exitCode, JSON.parse(run.stdout));await sbx.exec("git add -A && git diff --cached > /workspace/goose.patch", {  cwd: "/workspace/app",  check: true,});await writeFile("goose.patch", await sbx.files.readText("/workspace/goose.patch"));
Pythonimport sys, jsonfrom withruntime import Sandboxrepo = "https://github.com/your-org/your-repo"task = "Upgrade the project to the current major version of its test runner and fix what breaks."install_goose = ("curl -fsSL https://github.com/aaif-goose/goose/releases/download/"                 "stable/download_cli.sh | CONFIGURE=false bash")with Sandbox.create(disk_mib=8192, timeout_seconds=3600) as sbx:    sbx.exec("sudo apt-get update && sudo apt-get install -y bzip2",             check=True, timeout_ms=600_000)    sbx.exec(install_goose, 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"])    run = sbx.exec(        ["goose", "run", "--no-session", "--with-builtin", "developer",         "--output-format", "json", "--max-turns", "60", "-t", task],        cwd="/workspace/app",        env={            "GOOSE_PROVIDER": "anthropic",            "GOOSE_MODEL": "claude-sonnet-4-5-20250929",            "GOOSE_MODE": "auto",            "GOOSE_DISABLE_KEYRING": "1",            "GOOSE_DISABLE_SESSION_NAMING": "true",        },        timeout_ms=1_800_000,        on_stderr=sys.stderr.write,    )    print(run.exit_code, json.loads(run.stdout))    sbx.exec("git add -A && git diff --cached > /workspace/goose.patch",             cwd="/workspace/app", check=True)    with open("goose.patch", "w") as file:        file.write(sbx.files.read_text("/workspace/goose.patch"))

Step by step:

  • bzip2 is installed first because the Linux release is a .tar.bz2 file. goose's install guide suggests installing it when extraction fails.
  • CONFIGURE=false skips the interactive goose configure step. The script installs to $HOME/.local/bin. In a sandbox, that is /workspace/.local/bin, which is already first on PATH.
  • The allow list is one host. goose ships as a single binary, so once it is installed, it needs no package registry. Add the registries that your project's tests install from.
  • --with-builtin developer loads goose's built-in developer extension, which gives it shell and file editing. With no config file, no other extension loads.
  • GOOSE_MODE=auto lets goose run tools without asking. GOOSE_DISABLE_SESSION_NAMING saves the extra model call that goose otherwise makes to name the session.
  • --no-session writes no session file. --max-turns caps the turns taken without user input. The default is 1000.
  • --output-format json returns the result once the run completes. Use stream-json to watch events as they happen.

goose run options worth knowing

From goose's CLI command reference, 25 October 2026:

Option Purpose
-t, --text <TEXT> The instruction
-i, --instructions <FILE> Instructions from a file
--recipe <FILE> A recipe with a prompt field, for repeatable jobs
--provider, --model Override GOOSE_PROVIDER and GOOSE_MODEL
-q, --quiet Print only the model's response
--output-format json, stream-json Structured output after or during the run
--max-tool-repetitions <n> Stops identical tool calls repeating in a loop

A recipe is goose's way to repeat a job across many repos. One YAML file holds the prompt, instructions and extensions. Each sandbox runs goose run --recipe. To keep a checkout between recipes, pause the sandbox instead of stopping it.

Add Runtime as a goose extension

goose calls MCP servers extensions. To give a goose session on your laptop Runtime's tools for one run:

Terminalgoose session --with-extension "runtime:npx -y withruntime mcp"

The runtime: prefix names the extension. Its tools therefore appear as runtime__runtime_sandbox_create and so on, not under npx. To keep the extension, add a stdio extension to ~/.config/goose/config.yaml:

YAMLextensions:  runtime:    type: stdio    name: runtime    enabled: true    cmd: npx    args: ["-y", "withruntime", "mcp"]    envs: {}    env_keys: []    timeout: 300

The first Runtime call prints a link and a code. Approve Connect agent in the browser. Every tool then loads, and the YAML holds no key (MCP). goose also accepts remote servers as streamable_http extensions. https://api.withruntime.com/mcp works with that type.

Tool What goose gets
runtime_sandboxes_create A fresh microVM, ready when the call returns
runtime_sandboxes_exec Commands run away from your laptop
runtime_sandboxes_desktop_screenshot A look at a desktop running in the sandbox
runtime_secrets Keys for the sandbox to use without seeing

Cost

Runtime charges for the CPU a sandbox actually uses, at $0.025 per vCPU-hour, with a floor of a twentieth of a vCPU. Reserved memory costs $0.0075 per GiB-hour. A 2 vCPU, 4 GiB goose run costs $0.03125 an hour while the model works, and $0.08 an hour at full CPU (pricing). The model provider bills tokens on your key. A new account gets 100 free hours of a 1 GB machine in its first 30 days, without a card:

Terminalnpx withruntime sandboxes run -- uname -a

Other open agents on Runtime: OpenCode and OpenHands. For many repos at the same time, see 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