boxd

Run Linux microVMs from your Convex backend with reactive machine state and command output stored in Convex tables, queryable in real time.

Installation

npm install @boxd-sh/convex

About boxd

The boxd Convex component lets you create, fork, and control full Linux microVMs from Convex actions, with machine state and command output stored in reactive Convex tables. It wraps the boxd API to handle authentication token management, owner-scoped access control, and idempotent lifecycle operations including pause, hibernate, wake, stop, and destroy. Queries over machine rows and execution history re-run automatically when state changes, so your UI stays current without polling.

Benefits

Use cases

how to run shell commands in a sandbox from Convex backend

The boxd Convex component exposes a `boxd.exec(ctx, { machineId, command, ownerId })` method that runs a shell command inside a Linux microVM, waits for exit, and records the result in a Convex table. Command history is readable reactively via `boxd.listExecutions(ctx, { machineId, ownerId })`, so your UI updates automatically when output arrives.

how to give each user their own isolated compute environment in Convex

The boxd component accepts an `ownerId` on every call, derived server-side from Convex auth. Machines created with an `ownerId` are only reachable by that same owner, and reads for any other owner return null or an empty array. This makes per-user or per-tenant machine isolation a single argument rather than a custom access control layer.

how to run AI agents with sandboxed code execution in Convex

The boxd component lets you create a microVM with `boxd.create`, run arbitrary commands with `boxd.exec`, read and write files, and expose a port publicly over HTTPS. Each machine boots in under 10ms and can be forked in under 200ms, making it suitable for spawning isolated environments for AI agent tasks without leaving the Convex action model.

how to fork a running VM and preserve its state in Convex

The boxd component provides `boxd.fork(ctx, { machineId })`, which copies a machine including its disk and memory into a new machine with the same owner. The fork completes in under 200ms. The new machine appears as a row in the same reactive Convex table as the original.

Frequently asked questions

What is the boxd Convex component and what does it do?

The boxd Convex component (@boxd-sh/convex) integrates the boxd microVM platform with a Convex backend. It lets you create, fork, pause, hibernate, and destroy Linux microVMs from Convex actions, and stores machine state and command execution history in reactive Convex tables so your frontend can subscribe to updates with ordinary queries.

How does the boxd component handle authentication and API keys?

You create a boxd API key with the boxd CLI and set it as a Convex environment variable using `npx convex env set BOXD_API_KEY bxd_...`. The key is bound into the component's own environment in `convex.config.ts` and never passed as a function argument. The component exchanges the key for a session token once, caches it in its own table, and reuses it until expiry.

How do I scope boxd machines to individual users in my Convex app?

Pass an `ownerId` derived from Convex auth on every boxd call. The component enforces that a machine created with a given `ownerId` is only accessible when that same `ownerId` is provided. Reads for other owners return null or empty arrays, and writes fail with a NOT_FOUND error, matching the behavior for machines that do not exist.

What are the execution time and output limits for boxd commands run from Convex?

Convex enforces a 10-minute action limit, so `boxd.exec` kills its command after a `timeoutMs` that defaults to 9 minutes and is capped at 9.5 minutes. Each stream returns up to 2 million characters, and the execution row in Convex stores the first 64,000 characters. For longer-running work, the README recommends starting commands with nohup in the background and polling with subsequent exec calls.

How do I test my Convex app that uses the boxd component without making real network calls?

The boxd component ships a test helper at `@boxd-sh/convex/test`. Register it with `convex-test` using `boxdTest.register(t)`, then mock `@boxd-sh/sdk/web` with `vi.mock` to intercept network calls. The component's own test suite in `src/component/setup.test.ts` demonstrates this pattern.

Links