Back to the catalog

OKF bundle

Bundle OKF 0.1 · 15 conceitos · gannonh/devbox

Open source Repository Open in the app JSON README (API)

About

# OKF bundle

## Specs

* [Cloud devboxes on Vercel Sandbox](https://github.com/gannonh/devbox/issues/2) - approved GitHub epic for the first cloud provider; its five sub-issues are tracked as GitHub issues.
* [Vercel provider convergence](https://github.com/gannonh/devbox/issues/7) - the current phase, its acceptance evidence, and signoff.

## ADRs

* [ADRs index](/adrs/index.md) - architecture decisions and history.
* [Digest-pinned Vercel image promotion](/adrs/0001-vercel-image-promotion.md) - public digest pin, dual-project smoke, and reviewed promotion.
* [Vercel provider convergence](/adrs/0002-vercel-provider-convergence.md) - direct SDK lifecycle, digest pin, and evidence-gated release.
* [noVNC access-code pairing](/adrs/0003-novnc-access-code-pairing.md) - the printed display link pairs the browser on click.
* [Image pin as a build output](/adrs/0004-image-pin-as-build-output.md) - three channels, zero CI-authored pull requests.
* [Zero-configuration public app ports](/adrs/

Details

Kind
OKF bundles
Topic
Developer tools
Publisher
gannonh
Origin
okf_github
Category
dados
Version
0.1
Stars
7
Last push
2026-09-06T21:49:12Z
Repository state
ativo
Language
TypeScript
License
MIT
Added
2026-09-09 05:03:59
Updated
2026-09-09 05:03:59
Origin id
gannonh/devbox:docs/index.md

README

# @gannonh/devbox

`@gannonh/devbox` creates an isolated Ubuntu dev container for each Git worktree. Every container has its own network namespace and a desktop you can open in a browser.

The default image includes Node, Bun, git, `gh`, ripgrep, fd, fzf, tmux, Chromium, and Pi. You can switch the coding agent to Claude Code or Codex. The generated configuration follows the devcontainer specification and also works in Codespaces and Cursor.

Devbox runs containers on your machine by default. It can also run them in a Vercel Sandbox. See [Providers](#providers). Local boxes need `.devcontainer/devcontainer.json`. Run `init` when you want the generated `.devbox/` + `.devcontainer/` default. Vercel boxes need neither.

## Quick start

```bash
npx @gannonh/devbox init                         # generate default .devbox/ + .devcontainer/
npx @gannonh/devbox my-branch                    # worktree + local container shell

npx @gannonh/devbox --provider vercel my-branch  # Vercel Sandbox; no init
```

`init` lists each file it creates. Booting a local box prints its display URL. With OrbStack, the URL has the form `http://<container>.orb.local:6080/vnc.html`. Vercel boxes print an HTTPS URL.

To run devbox from this repository:

```bash
npm run build
node dist/cli.js --help
```

## Requirements

- Node.js 22 or newer
- OrbStack or another Docker runtime for local boxes. OrbStack provides the `<container>.orb.local` URLs.
- `@devcontainers/cli` for local boxes, installed with `npm install -g @devcontainers/cli`
- Git 2.45 or newer for `worktree --relative-paths`
- An authenticated GitHub CLI, set up with `gh auth login`
- Host configuration in `~/.pi` if you use Pi

## What devbox changes

- `init` writes `.devbox/` and `.devcontainer/` in the current repository. That pair is the generated local default, not a local-provider requirement. Local boxes need `.devcontainer/devcontainer.json`; they do not need `.devbox/`. If `.devbox/` is missing, `init` overwrites an existing `devcontainer.json`. Vercel boxes need neither. Delete both directories to undo `init`.
- The local provider runs `docker build` and `docker exec` from the devcontainer configuration. It runs `.devbox/provision.sh` inside the container.
- Devbox copies the token from `gh auth token` into the box so Git can push. It also copies Pi configuration from `~/.pi`, excluding sessions and the npm cache.
- Devbox loads project environment variables only when you pass `--env PATH`. It does not copy the dotenv file itself.
- Local boxes pull base images and install dependencies. Devbox sends no telemetry.
- The Vercel provider clones the GitHub origin into a Vercel Sandbox and creates HTTPS routes. Anyone with an app route URL can reach that port.
- Devbox stores provider preferences and metadata under `$XDG_STATE_HOME/devbox`, or `~/.local/state/devbox` when `XDG_STATE_HOME` is unset.

Run `npx @gannonh/devbox <branch> --rm` to remove a box, its worktree, and its branch. Uncommitted work in that worktree may be lost. If you installed the package globally, remove it with `npm uninstall -g @gannonh/devbox`. After removing all boxes, delete the state directory above to clear stored preferences and metadata.

## Commands

```bash
npx @gannonh/devbox init                              # generate default .devbox/ + .devcontainer/
npx @gannonh/devbox <branch>                          # boot a local box
npx @gannonh/devbox <branch> --env PATH               # load dotenv values for this run
npx @gannonh/devbox <branch> --attach                 # enter a running box
npx @gannonh/devbox <branch> --pause                  # pause it but keep its resources
npx @gannonh/devbox <branch> --stop                   # stop the box but keep its resources
npx @gannonh/devbox <branch> --rm                     # remove the box, worktree, and branch
npx @gannonh/devbox <branch> --url                    # print provider routes
npx @gannonh/devbox <branch> --open                   # open the first route
npx @gannonh/devbox --list                            # list local boxes
```

`--attach` reuses the environment stored with the box. Passing `--env` again replaces it. `--pause` pauses a local container and resumes it without restarting the display. On Vercel, pause and stop retain one persistent snapshot, and attach resumes that snapshot without recloning or reinstalling dependencies. `--stop` rejects `--env` because stopping a box transfers no environment values.

## How it works

`npx @gannonh/devbox <branch>` fetches `origin`, creates a worktree from `origin/<default>`, builds the image if needed, starts the container, and opens a shell at `/workspace` as a non-root user. Set `DEVBOX_START_POINT=local` to create the worktree from the local default branch instead.

Each worktree gets a separate container and network namespace, so two worktrees can bind the same port. Xvfb, fluxbox, x11vnc, and noVNC provide the browser desktop. `xdg-open` uses Chromium inside the box, which keeps OAuth consent flows inside the container.

## Coding agents

`.devbox/provision.sh` contains setup blocks for three agents. Pi is enabled by default.

| Agent | Package | Authentication |
| --- | --- | --- |
| Pi | `@earendil-works/pi-coding-agent` | copied from host `~/.pi` |
| Claude Code | `@anthropic-ai/claude-code` | `ANTHROPIC_API_KEY` |
| Codex | `@openai/codex` | `OPENAI_API_KEY` or `codex --login` |

To switch agents, enable the matching block in `.devbox/provision.sh`. If you disable Pi, also remove the `~/.pi` mount from `.devcontainer/devcontainer.json`.

## Providers

| Provider | Runs on | Address | Source code |
| --- | --- | --- | --- |
| `local` | OrbStack or Docker on your machine | `<container>.orb.local:<port>` with OrbStack | local worktree, including uncommitted files |
| `vercel` | Vercel Sandbox | Vercel HTTPS routes | authenticated GitHub origin, using pushed commits only |

Devbox remembers the provider for each repository until you pass `--provider` again. It prints a notice before using a remembered Vercel provider.

### Vercel Sandbox

The Vercel provider runs without a local Docker runtime and makes the display available over HTTPS. Run `init` only if you want `.devbox/post-create.sh` or explicit `forwardPorts`. A missing `devcontainer.json` still exposes noVNC `6080`.

```bash
npx @gannonh/devbox --provider vercel my-branch
npx @gannonh/devbox my-branch --password
npx @gannonh/devbox my-branch --pause
```

The Sandbox clones the GitHub origin. Dirty files and unpushed commits remain on your machine.

On first use, devbox prints the Vercel team and project, then asks for confirmation in a TTY. It checks credentials in this order:

1. `VERCEL_TOKEN`, `VERCEL_TEAM_ID`, and `VERCEL_PROJECT_ID`
2. `VERCEL_OIDC_TOKEN`
3. Vercel device authentication scoped by `.vercel/project.json`

The display URL contains a one-use access code. Opening the complete URL exchanges the code for a session cookie. If the URL is stale or incomplete, run `--password` and enter the printed code in the pairing form.

In the remote terminal, `Ctrl-C` reaches the foreground process. `Ctrl-]` disconnects without stopping the Sandbox. Each VM session owns one devbox-managed tmux session, so a reconnect reaches the same foreground process while that VM session remains alive. A forced local CLI close has the same reconnect behavior.

`--pause` stops the Vercel Sandbox session and retains its latest snapshot. The next boot or attach restores that snapshot, refreshes GitHub credentials, dotenv values, Pi configuration, display services, and public relays, then opens the terminal without recloning or reinstalling dependencies. The snapshot ID and source session are stored in mode-`0600` host metadata. `--stop` reports the same Vercel snapshot as paused. `--rm` deletes the Sandbox and retained snapshots after verification.

The terminal shell derives a devbox-owned tmux socket from `sandbox.currentSession().sessionId`. A same-session attach reuses that socket and launches `tmux new-session -A -s devbox`, so user processes survive WebSocket reconnects. A snapshot resume creates a new VM session and a new socket. Processes from the prior VM session end, while runtime setup, display services, and public relays restart. The configured Vercel timeout applies to each new or snapshot-resumed VM session.

Vercel Sandbox is a bounded development VM, not continuously available VPS hosting. Use a separately managed VM or Vercel Functions for continuously available services.

After checkout, devbox reads `package.json` files without executing them and suggests common application ports such as Vite's `5173`. It also scans npm workspace members. Approved ports become public without recreating the Sandbox. To skip the prompt, pass the ports explicitly:

```bash
npx @gannonh/devbox --provider vercel my-branch --expose-ports 5173
```

On the boot that creates the sandbox, `--timeout <minutes>` sets the Sandbox timeout (1-1440 minutes; default 60) and `--vcpus <n>` sets the Sandbox vCPUs (1 or an even number up to 32; 2048 MB of memory per vCPU; Vercel defaults to 2). Both are stored per branch like the image, so neither resizes an existing box: changing one later conflicts, and `--rm` plus a fresh boot is the way to change them.

```bash
npx @gannonh/devbox --provider vercel my-branch --timeout 90 --vcpus 4
```

Run your project's ordinary dev command. Devbox publishes each approved port through a small relay inside the sandbox that forwards HTTP and WebSocket traffic to `localhost:<port>`, so a loopback-bound server works without `--host`, and Vite's `server.allowedHosts` check passes without a config change. Until the app starts listening, the URL returns a `502`; it serves the app as soon as the server is up, with no new URL. See [ADR 0007](docs/adrs/0007-relay-backed-public-app-routes.md).

See the [Vercel provider reference](docs/reference/vercel-provider.md) for command details, configuration order, and recovery behavior.

<details>
<summary>Runtime image pinning</summary>

Vercel Sandboxes boot from an OCI image. Published packages contain the digest of the image that passed their smoke tests. Repository checkouts use the `nightly` channel instead. The source tree contains no digest because `scripts/vercel/emit-image-pin.mjs` writes it into `dist/` during publication.

Set `DEVBOX_VERCEL_IMAGE` to a fully qualified digest to test a locally built image. Published releases reject this override. See the [image supply chain runbook](docs/runbooks/vercel-image-supply-chain.md) for channels, rollback, and cleanup.

</details>

## Maintainer CI and releases

<details>
<summary>Workflows, secrets, and credentialed checks</summary>

Unit tests cover provider logic without live credentials. Vercel checks run in scheduled or manually dispatched workflows.

| Workflow | Trigger | Checks |
| --- | --- | --- |
| CI | every push and pull request | lint, types, build, and tests without credentials |
| Nightly | scheduled on `main`, or manually dispatched at any ref | image build, publisher and consumer smoke tests, and prerelease publication |
| Release | manual run from the default branch | stable tag promotion after terminal smoke tests, UAT, and the five-run benchmark |

Pull requests receive no cloud credentials. Labels do not authorize credentialed runs. To test a branch against Vercel, dispatch Nightly for that ref. Pass `publish` to install the result as `npx @gannonh/devbox@dev-<branch>`. Credentialed runs require the repository owner and the protected `vercel-provider-smoke` environment.

Repository secrets include the Vercel consumer credential triad, the GitHub fixture token and repository details, and the expected fixture file and content. The workflow maps the Vercel values to `VERCEL_TOKEN`, `VERCEL_TEAM_ID`, and `VERCEL_PROJECT_ID` for the smoke process.

The smoke run checks the exact Git revision, terminal signal and detach behavior, image identity, and resource cleanup. Evidence contains one-way fingerprints rather than fixture values, tokens, or Vercel IDs. A final redaction step runs before upload, including after failures. If cleanup finds ambiguous duplicate resources, follow the manual procedure in the supply chain runbook instead of running `--rm`.

See the [Vercel provider convergence issue](https://github.com/gannonh/devbox/issues/7) and the [documentation index](docs/index.md) for design history and maintainer procedures.

</details>

## Status

Stable releases publish to the npm `latest` tag after their nightly build passes the release checks above.

## License

[MIT](LICENSE)

More