
Devbox
- 5 installs
- 1 repo stars
- Updated May 28, 2026
- buildatscale-tv/agent-skills
devbox is a Claude Code skill that creates, configures, and tears down Namespace cloud devboxes with SSH, GitHub auth, and port tunnels.
About
devbox creates, manages, and tears down Namespace devboxes from a static spec. A developer uses it to spin up an isolated cloud dev environment with SSH aliases, GitHub auth, and forwarded ports, or to fan out multiple variant boxes. When the request involves dispatching work to an agent, an OpenCode profile layers on agent dispatch and monitoring.
- Creates, configures, and tears down Namespace devboxes with SSH and GitHub auth
- Opens port tunnels from the devbox to localhost and supports multi-variant parallel boxes
- Optionally dispatches agent work (issue, ad-hoc, variants) via an OpenCode profile
Devbox by the numbers
- 5 all-time installs (skills.sh)
- Ranked #1,085 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
devbox capabilities & compatibility
Requires a Namespace account and an OPENCODE_API_KEY secret for agent dispatch images.
- Capabilities
- execute plan
- Works with
- github · docker
- Use cases
- devops · ci cd · orchestration
- Runs
- Local or remote
- Pricing
- Bring your own API key
What devbox says it does
Create, manage, and tear down Namespace devboxes.
Create and manage Namespace devboxes. Each box gets its own name, SSH alias, and forwarded ports.
Namespace devboxes provide Docker automatically (`setup_docker_client: true`).
npx skills add https://github.com/buildatscale-tv/agent-skills --skill devboxAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 1 |
| Last updated | May 28, 2026 |
| Repository | buildatscale-tv/agent-skills ↗ |
What it does
Provision, tunnel into, and tear down Namespace cloud devboxes, optionally dispatching agent work to them.
Who is it for?
Provisioning isolated Namespace devboxes and fanning out parallel variant environments.
Skip if: Local-only work, since it depends on Namespace devbox and nsc tooling.
When should I use this skill?
You need to create, look up, or tear down a Namespace devbox, or dispatch agent work to one.
What you get
A named Namespace devbox with configured SSH, GitHub auth, and forwarded ports, plus clean teardown when done.
- provisioned Namespace devbox
- configured SSH and GitHub auth
- port tunnels to localhost
By the numbers
- 6 dispatch parsing modes
- default agent port 4096, app port 4321
Files
/devbox
Create and manage Namespace devboxes. Each box gets its own name, SSH alias, and forwarded ports.
When the request involves agent work (an issue, ad-hoc task, or variant comparison), follow the OpenCode profile after the base lifecycle:
- OpenCode profile for boxes with
opencode serve
Parsing the /devbox argument
| Pattern | Mode | What to do |
|---|---|---|
| "tear down issue 32", "destroy that devbox", "kill the variants" | Teardown | Jump to Teardown section |
| "status", "how's issue 32 doing" | Status | Jump to Lookup + status check |
| "<N> variants/versions of <work>", "fan out <N> <work>" | Multi-variant | Run lifecycle N times in parallel. Requires an agent profile. |
| "issue 32", "#32", "ticket 42", bare integer | Issue dispatch | Run lifecycle once. Requires an agent profile. |
| "create a sponsors page", "refactor auth", any task description | Ad-hoc dispatch | Run lifecycle once. Requires an agent profile. |
| "give me a devbox", "spin up a box", no task specified | Plain devbox | Run lifecycle only (no agent dispatch). |
---
Lifecycle
Identifiers
Compute before starting. Report connection details to the user immediately.
| Value | Issue mode | Ad-hoc / plain mode |
|---|---|---|
PREFIX | issue-<N>- | <slug>- (lowercase, alphanum + hyphens, max 30 chars) |
BRANCH | agent/issue-<N> | agent/<slug> (skip for plain devbox) |
APP_PORT | 30000 + N | Pick a free port in 30100-30999 |
TUNNEL_PORT | 40000 + N | APP_PORT + 10000 |
REPO | from --repo flag, else git remote get-url origin | same |
Step 0: Resolve image
Before creating the devbox, determine which image to use. Check in this order:
1. User-specified image ("use my opencode image", "use the rails image") — look it up:
devbox image list -o json | jq -r '.[] | .name'2. `Dockerfile.devbox` in the project root — if it exists, this project defines its own devbox image. Check if a matching image is already built, and build/rebuild if needed:
if [ -f Dockerfile.devbox ]; then
IMAGE_NAME="${REPO_NAME}-devbox"
EXISTING=$(devbox image list -o json | jq -r --arg name "$IMAGE_NAME" '.[] | select(.name==$name) | .name')
if [ -z "$EXISTING" ]; then
echo "Building image $IMAGE_NAME from Dockerfile.devbox..."
devbox image build ./ -f Dockerfile.devbox --name "$IMAGE_NAME" \
--secrets OPENCODE_API_KEY=<sec_id>
fi
fiThe <sec_id> comes from nsc vault list or a prior vault add. Check the agent profile for secret setup.
3. No Dockerfile.devbox, no user preference — fall back to the spec's default (builtin:agents).
Override the spec's image: line via sed if using a non-default image.
Custom images: Namespace supports any Docker base image — you are not limited to builtin:agents or builtin:base. If the project needs a specific runtime (e.g. ruby:3.3.9-slim, node:22), create a Dockerfile.devbox in the project root. Namespace converts any image into its optimized format.
Do NOT install Docker in `Dockerfile.devbox`. Namespace devboxes provide Docker automatically (setup_docker_client: true). Only add application-level dependencies (runtimes, libraries, tools) to the image. Docker commands like docker compose up work out of the box in session commands.
Step 1: Create
Resolve the repo from --repo flag or git remote get-url origin. Derive REPO_NAME (the final path segment) for use in session commands.
If the project has a `devbox.yaml` in the root, use it directly — it already contains the image, sessions, and repo config. Only rewrite name_prefix::
mkdir -p .devbox-tmp
REPO=$(git remote get-url origin 2>/dev/null | sed 's|.*github.com[:/]||;s|\.git$||')
REPO_NAME=$(basename "$REPO")
if [ -f devbox.yaml ]; then
sed 's/^name_prefix:.*/name_prefix: <PREFIX>/' devbox.yaml > .devbox-tmp/spec.yaml
else
# No project spec — build one from the skill's base template
sed 's/^name_prefix:.*/name_prefix: <PREFIX>/' .agents/skills/devbox/devbox.yaml > .devbox-tmp/spec.yaml
[ -n "$IMAGE_NAME" ] && sed -i 's/^image:.*/image: '"$IMAGE_NAME"'/' .devbox-tmp/spec.yaml
[ -n "$REPO" ] && echo "repository: github.com/$REPO" >> .devbox-tmp/spec.yaml
# Append sessions per the OpenCode profile instructions
fi
devbox create --from .devbox-tmp/spec.yaml 2>&1 | tee .devbox-tmp/create.log
NAME=$(grep -oE 'ssh [^ ]+\.devbox\.namespace' .devbox-tmp/create.log | head -1 | awk '{print $2}' | sed 's/\.devbox\.namespace$//')
echo "devbox: $NAME"When a project devbox.yaml exists, skip the "Add sessions to spec" step in the agent profile — sessions are already defined.
Step 2: Configure
devbox configure-ssh "$NAME" >/dev/null
devbox setup-github "$NAME" || echo "setup-github skipped (gh CLI not on image)"setup-github requires gh on the devbox. It ships with builtin:agents / builtin:base but not with custom base images (e.g. ruby:*-slim). The command is non-critical — repo cloning works via the spec's repository: line regardless.
Step 3: Open tunnels
Forward ports from the devbox to localhost. Adjust the remote targets to match whatever the devbox runs (values below are defaults from the Constants table).
ssh -fN -o LogLevel=ERROR -o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
-L <TUNNEL_PORT>:localhost:<TUNNEL_REMOTE_PORT> \
-L <APP_PORT>:<APP_BIND_HOST>:<APP_PORT_INTERNAL> \
"$NAME.devbox.namespace"For plain devbox requests, stop here. Report the box name + SSH alias.
For agent dispatch requests, continue with the relevant profile.
---
Teardown
| Step | Command |
|---|---|
| Kill tunnels | pkill -f "ssh.*<NAME>.devbox.namespace" |
| Expire box | devbox expire <NAME> --force |
---
Lookup
Box names encode the dispatch identity via name_prefix:
- Issue:
issue-<N>-<random>(e.g.issue-32-rsep2bmaq4) - Ad-hoc:
<slug>-<random>
devbox list -o json | jq -r '.[] | select(.name | startswith("issue-32-")) | .name'Or by deterministic port (issue mode): lsof -iTCP:40032 -sTCP:LISTEN.
---
Constants
| Name | Default | What it's for |
|---|---|---|
APP_PORT_INTERNAL | 4321 | Dev server port inside the box (Astro default) |
APP_BIND_HOST | [::1] | Astro binds IPv6; tunnel target must match |
TUNNEL_REMOTE_PORT | 4096 | Agent server port inside the box (OpenCode default) |
Change these when the spec's session command moves to a different stack or agent runtime.
Common overrides by framework:
| Framework | APP_PORT_INTERNAL | APP_BIND_HOST |
|---|---|---|
| Astro | 4321 | [::1] |
| Rails | 3000 | localhost |
| Next.js | 3000 | localhost |
| Vite | 5173 | localhost |
Files
devbox.yaml- static Namespace devbox spec.name_prefix:is rewritten per dispatch viased.profiles/opencode.md- OpenCode agent dispatch and monitoring.prompts/issue.md,prompts/adhoc.md- prompt templates (used by agent profiles).
Host env
gh auth statusgreen; GitHub auth is forwarded into the box.
# Minimal Namespace devbox spec. Repo-agnostic, runtime-agnostic.
# name_prefix is rewritten per dispatch. Repo is passed via --checkout.
# Agent profiles add their own sessions/services via SSH after creation.
name_prefix: agent-
image: builtin:agents
size: M
volume_size_gb: 100
auto_stop_idle_timeout: 1h
OpenCode Agent Dispatch
For devboxes that will run an OpenCode agent. Follow the base SKILL.md lifecycle, but before Step 1 (Create), set up the image and append the opencode session to the spec.
Prerequisites: Custom image with secrets
OpenCode needs an API key (OPENCODE_API_KEY) available in the devbox environment. The simplest way is a thin custom image that attaches vault secrets.
Check if a custom image already exists:
devbox image list -o json | jq -r '.[] | select(.name | test("builtin") | not) | .name'If one exists with your secrets, skip to the next section. Otherwise:
1. Create vault secrets
echo "$OPENCODE_API_KEY" | nsc vault add --description "OpenCode API key" --revealable
# Returns: sec_xxxAdd any other secrets your app needs the same way (e.g. echo "$GEMINI_API_KEY" | nsc vault add ...).
2. Build the image
You can use any Docker base image — you are not limited to Namespace's builtin images. If the project needs a specific runtime, use that as the base (e.g. ruby:3.3.9-slim, node:22-slim). Install OpenCode in the Dockerfile:
RUN curl -fsSL https://opencode.ai/install | bashBuild with devbox image build, using -f if the Dockerfile has a non-default name:
devbox image build ./ -f Dockerfile.devbox --name my-opencode-agent \
--secrets OPENCODE_API_KEY=sec_xxxIf you don't need a custom runtime, extend from builtin:agents:
mkdir -p .devbox-tmp
DIGEST=$(devbox image list -o json | jq -r '.[] | select(.name=="builtin:agents") | .digest')
echo "FROM public.registry.namespace.systems/namespacelabs.dev/internal/devbox/userimages/ext@$DIGEST" > .devbox-tmp/Dockerfile
devbox image build .devbox-tmp/ --name my-opencode-agent \
--secrets OPENCODE_API_KEY=sec_xxxNote: builtin:agents already includes OpenCode. Custom base images need the curl | bash install line.
Before Step 1: Add sessions to spec
After the sed for name_prefix, append sessions to the spec.
Session command rules (mandatory)
Every session command MUST follow these rules. Violations will cause silent failures:
1. Wrap in `/bin/bash -c '...'` — not bare commands, not -lc. Slim base images may not have login shells. 2. Use absolute paths — cd /workspaces/$REPO_NAME, never cd $REPO_NAME or relative paths. Sessions start from an undefined cwd. 3. Use `exec` for the final long-running process — ensures proper signal handling and cleanup.
Required sessions
1. Docker Compose services (if docker-compose.yml exists in the project)
Run infrastructure via Docker Compose. Never run databases/caches natively — always use the project's compose file. Docker is provided by the Namespace devbox runtime — do NOT install Docker in Dockerfile.devbox.
- name: services
command: |
/bin/bash -c '
cd /workspaces/$REPO_NAME
exec docker compose up
'2. App server (if the user requests the app to run)
Must wait for dependencies before starting. Determine the start command from the project (Procfile.dev, bin/dev, package.json).
- name: app
command: |
/bin/bash -c '
cd /workspaces/$REPO_NAME
until pg_isready -h localhost -q 2>/dev/null; do sleep 1; done
bundle exec rails db:prepare
exec bin/dev
'Adapt the wait and start commands per framework:
| Framework | Wait for deps | Install deps | Start command |
|---|---|---|---|
| Rails | until pg_isready -h localhost -q 2>/dev/null; do sleep 1; done | bundle install --quiet (skip if in image) | bin/dev or bin/rails server |
| Next.js | (skip if no DB) | npm install (skip if in image) | npm run dev |
| Astro | (skip if no DB) | npm install (skip if in image) | npm run dev |
3. OpenCode (always added)
OpenCode MUST start from /workspaces/$REPO_NAME — if started from any other directory, the web UI won't discover the git project and sessions created via the API won't be visible. It MUST bind to 0.0.0.0 on port 4096 to be reachable via the SSH tunnel.
- name: opencode
command: |
/bin/bash -c '
export PATH="/root/.opencode/bin:$PATH"
mkdir -p /root/.config/opencode
echo "{\"permission\":{\"*\":\"allow\"}}" > /root/.config/opencode/opencode.json
cd /workspaces/$REPO_NAME
exec opencode serve --hostname 0.0.0.0 --port 4096
'Then continue with Step 1 (devbox create).
Model selector
If the user specified --model X/Y or "with model X/Y" (e.g. opencode-go/glm-4.6), note it for the session creation step.
Step A: Wait for health + create session
OpenCode does not require authentication by default (OPENCODE_SERVER_PASSWORD is not set). Do not pass -u opencode:$PASS unless you have explicitly set a server password.
Wait for the server to become healthy, then query /project to get the correct project ID before creating a session:
until curl -fsS http://localhost:$TUNNEL_PORT/global/health >/dev/null 2>&1; do
sleep 3
done
PROJECT_ID=$(curl -fsS http://localhost:$TUNNEL_PORT/project | jq -r '.[] | select(.worktree | endswith("/'$REPO_NAME'")) | .id')
SID=$(curl -fsS -X POST http://localhost:$TUNNEL_PORT/session \
-H 'Content-Type: application/json' \
-d "{\"projectID\":\"$PROJECT_ID\"}" | jq -r '.id')Without projectID, the session lands under the global project and won't appear in the web UI when viewing the repo project.
If a model override was specified, pass it in the session body: {"projectID":"...","model":{"providerID":"<X>","id":"<Y>"}}
Step B: Compose prompt + dispatch
Compose the prompt from prompts/issue.md or prompts/adhoc.md. Substitute placeholders, then send via the local tunnel (no SSH or file upload needed):
curl -fsS -X POST "http://localhost:$TUNNEL_PORT/session/$SID/message" \
-H 'Content-Type: application/json' \
-d '{"parts":[{"type":"text","text":"<PROMPT>"}]}' > /dev/null 2>&1 &Monitoring
All monitoring commands go through the local tunnel — no SSH needed:
| Check | Command |
|---|---|
| Session info | `curl -s http://localhost:$TUNNEL_PORT/session \ |
| Full transcript | curl -s http://localhost:$TUNNEL_PORT/session/$SID/message |
| Projects | curl -s http://localhost:$TUNNEL_PORT/project |
| Server log | devbox session connect $NAME --session opencode |
| Check for PR | gh pr list --repo <REPO> --head <BRANCH> |
{{TASK}}
You are working on GitHub issue #{{ISSUE}}: {{TITLE}}
{{BODY}}
Source: {{URL}}
Setup already done for you:
- Branch
{{AGENT_BRANCH}}is checked out in the workspace - Dependencies are installed
- The dev server is running on port {{APP_PORT_INTERNAL}} with hot
reload enabled, so the reviewer will see your changes live in their browser as you save files
Notes:
- {{LOCKFILE_GUIDANCE}}
Implement the change end-to-end, then:
1. commit with a clear subject line 2. git push -u origin {{AGENT_BRANCH}} 3. gh pr create --head {{AGENT_BRANCH}} --title "<your commit subject>" --body "Closes {{URL}}"
Do not stop until the PR is open.
/devbox
Create, manage, and tear down Namespace devboxes from any AI agent. Supports GitHub issue dispatch, ad-hoc tasks, multi-variant model comparison, and plain devbox management.
/devbox issue 32
/devbox create a sponsors page with logos
/devbox create 3 variants of: design a homepage for a cabinet maker
/devbox give me a box with Gitea in Docker
/devbox tear down issue 32Agent profiles layer on runtime-specific dispatch:
profiles/opencode.mdfor OpenCode agent dispatchprofiles/claude.mdfor Claude Code dispatch
See SKILL.md for the full instruction set.
Requirements
- Namespace Devbox CLI - devbox management
curl -fsSL get.namespace.so/devbox/install.sh | bash
devbox login- Namespace Cloud CLI (
nsc) - vault secrets
curl -fsSL https://get.namespace.so/cloud/install.sh | bash
nsc login- GitHub CLI - repo access and PRs
gh auth loginRelated skills
FAQ
What does devbox provision?
It creates Namespace devboxes, each with its own name, SSH alias, and forwarded ports, from a static spec.
Can it run agent work?
Yes. When the request involves an issue, ad-hoc task, or variants, the OpenCode profile layers on agent dispatch and monitoring.