This page needs JavaScript. For agents, the same site as Markdown: https://instabox.sh/llms.txt (below), every page at its URL plus .md.
# InstaBox
> InstaBox gives each agent a Linux machine of its own in the cloud. Start with one command, then read only the page you need.
## Key facts
- API base URL: https://api.instabox.sh. Every body is JSON. Lifecycle calls (create, start, stop, suspend, resume, delete) and the other endpoints that list it need an `Idempotency-Key` header (any unique string); `exec` and Secrets take none. Deleting a machine or snapshot also takes an optional `X-Confirm-Delete` header, its ID or exact name: any other value is `409 delete_confirmation_required` and nothing is deleted.
- Exec: `POST /v1/machines/{id}/exec` takes `cmd` (a shell string, run with `bash -lc`) or `argv` (a program and its arguments, run with no shell), not both: `{"argv": ["printf", "%s|", "a b", "$X"]}` prints `a b|$X|`. Send `Accept: text/event-stream` to get the output as it is written: `stdout`/`stderr` events (`{"data"}`), then an `exit` event with the result (or `error`); the CLI does this with `instabox exec --stream`. Exec returns when the command exits, even if it left a server running in the background; redirect that server’s stdout and stderr to a file (`nohup ./server >server.log 2>&1 &`), since its later writes to exec’s output fail with a broken pipe. Exec output is UTF-8 text: without streaming each stream is cut at 1 MiB (`truncated`), and bytes that are not UTF-8 become U+FFFD (`invalidUtf8`), so read files with `GET /v1/machines/{id}/files/content` or `instabox pull`/`cp`, not `exec cat`; `instabox exec` exits 65 when the command exited 0 but its output was binary.
- Auth: send an API key (`ibk_...`) as `X-API-Key: <key>` or `Authorization: Bearer <key>`, for example `curl -H "X-API-Key: $INSTABOX_API_KEY" https://api.instabox.sh/v1/machines`. Create one in the dashboard (**API keys**) or with `instabox keys create --name N`; the CLI uses `INSTABOX_API_KEY` from the environment. A bad key gets a 401 whose `error.code` says why: `missing_key`, `malformed_key`, `invalid_key`, `expired_key` or `revoked_key`; a key without the scope a route needs gets `403 missing_scope`. Details: https://instabox.sh/docs/api.md
- Quick start: `npx instabox@latest sh` signs in, installs the `instabox` CLI and the instabox agent skills (`~/.claude/skills`, `~/.agents/skills`), and starts a machine; `--no-skills` installs no skills. Or `curl -fsSL https://api.instabox.sh/install.sh | sh` for the CLI alone, which with `INSTABOX_API_KEY` set needs no sign-in. Or call the HTTP API directly with the API key.
- Default template: `agent-browser` (Debian, Docker, Node.js, Bun, Python, Go, Rust, a desktop and Chromium); the free plan creates from it or `ci` only (or from a snapshot). `universal` is the same without the desktop preinstalled.
- Not every common CLI is preinstalled: GNU `time`, `rg` (ripgrep) and `htpasswd` need `sudo apt-get update && sudo apt-get install -y time ripgrep apache2-utils` (the image ships without apt lists, so run `apt-get update` first). `herdr`/`orca` omit Docker.
- Machine: a Firecracker microVM, Debian 13 (trixie) amd64, kernel 6.18.54, 4 vCPUs / 8 GiB by default, a 16 GiB root disk (8 GiB on `herdr` and `orca`) and a 20 GiB persistent disk at `/data` (home is `/data/home`). Python 3.13 with `python3 -m venv` and pip on every template. Per-template specs: the Machine specs table in Limits.
- `/tmp`: RAM tmpfs sized to about half guest RAM (~2 GiB on 2/4, ~4 GiB on 4/8; ~1M inodes), not the `/data` disk. Big staging: `TMPDIR=$HOME/tmp` (home is `/data/home`; the top of `/data` is root-owned) or remount `/tmp`. Details: Limits → `/tmp` and shared memory.
- Guest defaults: soft `ulimit -n` is 1024; `fs.inotify.max_user_watches` is about 32k–64k (`sysctl -w` raises inotify machine-wide until restart; `ulimit -n` raises nofile for that shell and its children only, so run it in the same exec as the workload). Details: Limits → File watches and open files.
- Snapshots: `create --snapshot` without an explicit size uses the plan `machineSpec` (often 4/8), not the source size — pass `--vcpus`/`--mem-mib`. `rootSizeBytes`/`dataSizeBytes` are logical disk sizes, not stored bytes. Details: Limits → Snapshot create size.
- Swap: none by default (`Swap: 0B`). On 2/4, heavy LTO links often OOM; add a swapfile under `/data` with `sudo /usr/sbin/swapon` (not on user PATH); it lasts one boot unless listed in `/etc/fstab`. Details: Limits → Swap.
- OOM: the guest kernel kills the victim (often exit 137); the machine stays running. API/CLI have no `oomKilled` flag or OOM event yet — confirm with `dmesg | grep -i oom`. Details: Limits → Out-of-memory (OOM).
- App builds on `universal` / `agent-browser`: write under `/data/home` (`/data` itself is root-owned); `cargo` and `rustup` are wrappers for the root-owned toolchain in `/opt/rust` (`cargo install` works; a new toolchain needs `sudo rustup`, or your own rustup with `~/.cargo/bin` first on `PATH`, which `exec` does not do for you); no `zip` and no JDK (Debian 13 has no `openjdk-17` package): `apt install zip`, `openjdk-21-jdk` (or Temurin). Details: Limits → App builds on `universal` / `agent-browser`.
- Upload speed: what a VM sends is capped at ~50 Mbit/s per VM (~6 MB/s), so ~100 MB out (`instabox pull`, a release upload, a public-port response) is ~15–20 s; downloads into the VM are not capped. Not the monthly egress quota. Keep big artifacts on `/data` or in a snapshot. Details: Limits → Outbound bandwidth.
- Sizes (vCPU/GiB): Free 4/8 only; Pro 2/4, 4/8, 8/16; Builder 2/4 up to 16/32; Team 2/4 up to 32/64. `GET /v1/orgs` (`instabox workspace ls --json`) lists each workspace's as `allowedSpecs`. A paid machine moves to another of them while stopped: `instabox resize <machine> --vcpus N --mem-mib M` (on a running or paused one add `--restart`, from outside the machine) or `PATCH /v1/machines/{id}` `{"vcpus": N, "memMiB": M}`, applied at its next start (files stay; a start its host has no room for fails with `no_capacity` and the machine stays stopped at the new size). Running or paused is `409 operation_conflict`: stop it first (a paused machine cannot be stopped: start it, then stop it, which is what `--restart` does); another size, or a free machine, `400 spec_not_allowed`.
- Disk: one per machine, `/data`, 20 GiB by default; at create it comes with the size, so leave `persistentDiskGiB` out (another size is `400 spec_not_allowed`; `diskGiB` is the TypeScript SDK option name, and in a REST body it is `400 unknown_field`). A paid machine changes its size with `instabox resize <machine> --disk N [--restart]` or `PATCH /v1/machines/{id}` `{"persistentDiskGiB": N}`: 1-1024 GiB; it grows while running (no restart) or at the next start, and shrinks only while stopped when the data plus 10% (at least 1 GiB) fits (else `409 disk_too_small`); at most 200 GiB on Pro, 500 on Builder and 1024 on Team and Enterprise (`429 quota_exceeded`). The system disk is the template's; only admins grow it (`rootDiskGiB` is `400 spec_not_allowed`). PATCH ignores fields it does not know, so `diskGiB` there changes nothing.
- Plan limits: Free 1 machine, 5 snapshots, idle pause fixed at 30 min. Pro 500 machines, 100 running. Builder 1,000 machines, 200 running. Team unlimited machines, 500 running. Paid plans choose the idle time (5-30 min, rounded up to a 5 min step; below 5 or above 30 is refused) or turn it off; the free plan refuses another value (https://instabox.sh/docs/machines.md#auto-pause).
- Plans: Free $0, Pro $20/month + usage, Builder $100/month + usage, Team $500/month + usage, Enterprise Custom.
- Usage prices: vCPU $0.004 per vCPU-hour, Memory $0.00225 per GiB-hour, Storage $0.00011 per GiB-hour, Egress $0.02 per GiB. Runtime is billed per second, only while running. Details: https://instabox.sh/docs/pricing.md
## CLI cheat sheet
```
instabox login sign in with a device code (or set INSTABOX_API_KEY)
instabox templates list templates
instabox create --name N [--template T | --snapshot S]
instabox create --name N --setup-file PATH then run a script in it (at most 64 KB)
instabox ls [--json] your machines
instabox get <machine> [--json]
instabox exec <machine> -- <cmd...> run one command; exits with its code
instabox exec --stream <machine> -- <cmd...> print the output as it is written
instabox exec --background <machine> -- <cmd> start a detached job, print its ID
instabox jobs ls|logs|wait|kill <machine> background jobs (a CLI feature over exec)
instabox agent prompt|events|steer|interrupt|ls <machine> drive Claude Code or Codex in the machine (a CLI feature over exec)
instabox logs <machine> [-f] console log + recent operations; never wakes it
instabox ps <machine> [--all] [--json] list its processes
instabox ssh <machine> a shell over SSH
instabox files <machine> [PATH] list a directory or print a file
instabox cp ./x.tgz <machine>:/data/home/x.tgz copy a file in (or out: cp <machine>:PATH .)
instabox push <machine> ./big.tar large uploads: push/cp (HTTP API, parallel), not scp/rsync over SSH
instabox suspend|resume <machine> pause and resume, memory kept
instabox stop|start|rm <machine>
instabox restart <machine> power-cycle a hung machine (stop, start), disks kept
instabox resize <machine> --disk N [--restart] disk full? resize /data to N GB (paid plans; a shrink needs --restart)
instabox resize <machine> --vcpus N --mem-mib M [--restart] another of your plan's sizes (paid plans; applies while stopped, --restart from outside the machine)
instabox auto-suspend <machine> 10m|0 idle time before pause (0: off, paid plans)
instabox snapshot save <machine> --name N then create --snapshot N
instabox fork <machine> [--count N] copy on its host in seconds (no snapshot)
instabox port publish <machine> <port> a public HTTPS URL for a port (--private: token-gated link)
instabox port-forward <machine> <port> a private localhost tunnel until Ctrl-C (or LOCAL:REMOTE)
instabox keys create --name N an API key, printed once
instabox usage counts and limits
```
Each page below is Markdown. The same page for people is at the URL without .md. Every page in one file: https://instabox.sh/llms-full.txt
## Get started
- [Quick start](https://instabox.sh/docs/start.md): From nothing to a shell in your own cloud machine.
- [Concepts](https://instabox.sh/docs/concepts.md): The few words the dashboard, the CLI and the API use.
- [Integrate with the SDK](https://instabox.sh/docs/integrate.md): The calls an app needs: create, pause and resume, delete, a shell, the desktop, and usage.
## Guides
- [Machines](https://instabox.sh/docs/machines.md): Lifecycle, sizes, auto-pause, logs, labels and secrets.
- [Snapshots](https://instabox.sh/docs/snapshots.md): Save a machine once, start new ones from it.
- [Connecting over SSH](https://instabox.sh/docs/ssh.md): With the CLI, or one ssh line for any terminal.
- [Public and private ports](https://instabox.sh/docs/ports.md): Give a web server in a machine an HTTPS URL, for anyone or only for people with the link.
- [Desktop: see it and control it](https://instabox.sh/docs/desktop.md): Watch a machine's desktop, let an agent drive it, and share a link to it.
- [Org Secrets](https://instabox.sh/docs/secrets.md): Credentials added to HTTPS headers by the outbound proxy, scoped to your org.
- [Webhooks](https://instabox.sh/docs/webhooks.md): Signed POSTs when a sandbox is ready, pauses, stops, fails or is deleted.
- [Agent sign-up](https://instabox.sh/docs/agent-auth.md): An agent with no browser signs itself up; the account owner approves later with a code.
- [API keys and SDK](https://instabox.sh/docs/keys-sdk.md): Drive machines from code: TypeScript, HTTP, or the CLI with a key.
## Reference
- [SDK reference](https://instabox.sh/docs/sdk.md): Every class, method and option of @insforge/instabox-sdk.
- [CLI reference](https://instabox.sh/docs/cli.md): Every command. Add --help to any of them for the details.
- [Pricing](https://instabox.sh/docs/pricing.md): Plans, what each includes, and the unit prices of usage.
- [Limits](https://instabox.sh/docs/limits.md): What each plan allows, and the machine specs. Account and GET /v1/usage show yours.
## API reference
- [API overview](https://instabox.sh/docs/api.md): Authentication, operations, idempotency and errors: what every endpoint shares.
- [Machines](https://instabox.sh/docs/api/machines.md): Create, list, change and delete machines.
- [Lifecycle](https://instabox.sh/docs/api/lifecycle.md): Start, stop, pause and resume machines.
- [Commands and files](https://instabox.sh/docs/api/commands.md): Run a command in a machine, and read, upload and download its files.
- [Snapshots](https://instabox.sh/docs/api/snapshots.md): Save a machine, then start new machines from it.
- [Operations](https://instabox.sh/docs/api/operations.md): Follow a change to a machine until it is done.
- [SSH](https://instabox.sh/docs/api/ssh.md): Log in to a machine with ssh or mosh.
- [Public ports](https://instabox.sh/docs/api/ports.md): Give a web server in a machine an HTTPS URL.
- [Secrets](https://instabox.sh/docs/api/secrets.md): Org credentials, sandbox selections and delivery status.
- [Account](https://instabox.sh/docs/api/account.md): Templates, your usage and limits, and who a key belongs to.
## Use cases
- [CI with instabox](https://instabox.sh/docs/ci.md): Send GitHub Actions jobs to instabox with runs-on: instabox-medium, or run a command on instabox from any CI.
## Optional
- [OpenAPI document](https://api.instabox.sh/v1/openapi.json): every endpoint an API key calls, as OpenAPI 3.1 JSON