GETTING STARTED

Quick start

Give yourself super powers. Install one binary, hand your coding agent the skills, and let it build sandboxes where it can go wild without touching your machine.


Prerequisites

devsandboxes drives a container runtime directly: no devcontainer CLI, no daemon to set up (its own starts on demand). You need:

  • A running docker, podman or Apple container (macOS). The default is container on macOS and docker elsewhere; pick another with DEVSANDBOX_RUNTIME=docker|podman|container.
  • git, for the worktrees extra instances get.
  • curl, to fetch devcontainer Features.

Install

The package is devsandboxes; the binary it installs is devsandbox.

TERMINAL
npm i -g devsandboxes
devsandbox --help

npx devsandboxes --help   # without installing

Native binaries for Linux x64/arm64, macOS arm64 and Windows x64, plus the typed Node API.

Give your agent the skills

The repo ships two agent skills:

  • devsandbox-cli: how to use the CLI.
  • config-toml-spec: the config format.

Install them with skills.sh, or copy them by hand:

TERMINAL
npx skills add nemikolh/devsandboxes

Asks which agents to install them for: Claude Code, Codex, Cursor and many more. Takes them from the default branch.

Write a config

A config root is a folder holding one devsandboxes.toml (or devsandboxes.yaml, same schema). It lives outside your repos and describes every sandbox; each sandbox points at a repo with folder, relative to the config root. This guide uses this layout, with web being any git repository:

LAYOUT
~/code/
├── sandboxes/
│   └── devsandboxes.toml
└── web/            # your repo

With your agent

Paste this into your agent and let it do the typing:

Prompt for your coding agentPaste into Claude Code, Codex or any agent with a shell.

Create a devsandbox config dir at ~/code/sandboxes with a devsandboxes.toml holding a sandbox for my repo at ~/code/web, plus a postgres service it can use.

  1. Read the devsandbox-cli and config-toml-spec skills first (load them if they are installed, otherwise read them from https://github.com/Nemikolh/devsandboxes/tree/main/skills). Follow them over your own assumptions: unknown config keys are hard errors.
  2. Find my devsandbox config dir: the folder holding devsandboxes.toml, passed to devsandbox as -C <config dir>. If you cannot tell which one, ask me.
  3. Look at ~/code/web to pick the base image, devcontainer Features and postCreateCommand it needs (package manager, language toolchains); if it has a .devcontainer/devcontainer.json, port that instead.
  4. Put the shared parts (features, caches, persist-shell-history) in a [template.base] the sandbox extends, and add a [services.database] on postgres:16 with scope = "global", listed in the sandbox's services.
  5. Validate with devsandbox -C <config dir> ls and fix every error it reports before going on.
  6. Run devsandbox -C <config dir> run <sandbox name>, then devsandbox -C <config dir> exec <instance> <the repo's test command>, and report what happened.
  7. Ask me before anything destructive: devsandbox rm, gc, rebuild --force, service rebuild, deleting files or branches.
fill in before sending Agent skills (opens in a new tab)

By hand

Put this in ~/code/sandboxes/devsandboxes.toml:

devsandboxes.toml
[services.database]
image = "postgres:16"
scope = "global"            # one container shared by all instances

[template.base]
caches = ["pnpm"]
persist-shell-history = true
[template.base.features]
"ghcr.io/devcontainers/features/node:1" = { version = "lts" }

[sandbox.web]
extends = "base"
folder = "../web"           # the repo, relative to this folder
services = ["database"]
image = "mcr.microsoft.com/devcontainers/base:ubuntu"
postCreateCommand = "pnpm install"

[sandbox.web] is a devcontainer definition in TOML: image, features and postCreateCommand mean what they mean in devcontainer.json. It extends the base template, which deep-merges into it (tables recurse, arrays concatenate), so every sandbox extending base shares the pnpm cache and the Node feature. [services.database] is a postgres sidecar; scope = "global" makes every instance share one container instead of getting its own.

Check it from the config root. ls lists the sandboxes and fails loudly on unknown keys:

TERMINAL
cd ~/code/sandboxes
devsandbox ls
OUTPUT
NAME  SOURCE                                             FOLDER  SERVICES  EXTENDS
web   image mcr.microsoft.com/devcontainers/base:ubuntu  ../web  database  base

The dashboard

From the config root, run devsandbox with no arguments to open the dashboard: every instance and service live, with the actions of the CLI one key away.

TERMINAL
devsandbox

Select web and press r to run an instance, t for a terminal inside it, ? for every key binding. Run it again and the second instance gets its own git worktree, so two agents never share a working tree. The dashboard tour walks through each tab next to a preview you can play with.

Next steps

Source: site/src/content/docs/quick-start.mdxEdit this page on GitHub(opens in a new tab)

MENU /
View on GitHub
EXAMPLES
All examplesEvery recipe on one page.Parallel coding agentsSeveral coding agents on one repo, fully isolated from one another.One shared PostgresOne development database for all your sandboxes and their instances.Private services per instanceEvery instance gets its own Postgres and Redis, so agents never touch each other's data.Shared package cachesNew sandboxes stop downloading the same packages again.ssh-agent and git pushAgents push over ssh with your host's keys, which never enter the container.Port forwarding on demandOpen a sandbox's dev server or database from your host, without restarting anything.Attach VS CodeOpen any instance in VS Code with one key.devcontainer FeaturesAdd Node, Rust or the GitHub CLI to any image, in TOML.Babysit pull requestsAn agent keeps your open PRs merged with their base, and pings you when it can't.Port a devcontainer.jsonTurn an existing devcontainer.json into a devsandbox config.