Skip to main content
Label any GitHub issue or PR boxd-fix — or drop a /boxd-fix (or /boxd-preview --fix) comment — and you get back Claude’s fix: a new PR with a live preview URL for issues, or a commit pushed straight to the existing PR for PRs. Each run gets its own fork, destroyed on PR close.

How it works

Fix builds on the preview platform: it reuses the same on-golden listener, fork, branch-sync, and teardown, and adds the Claude + PR step on top. No GitHub Actions, no runner queue, no BOXD_API_KEY repo secret.
Three triggers fire the fix handler; teardown is the preview platform’s shared hook: Live status lands on the issue/PR as a comment that updates while Claude works (✓ preview VM booted, 🤖 Claude is reading the code, ⏳ opening the PR / pushing the fix). The fork stays alive while the PR is open so reviewers can poke at it. PR close triggers boxd machine remove. The whole thing is wired up by a single Claude Code slash command.

Set it up

Fix is the agent layer, so set up the chain first: /boxd-setup-golden/boxd-setup-preview/boxd-setup-fix. With those done, wire fix on top — two ways:
Install the boxd CLI on your laptop (this also drops the skill):
Then run the skill in the repo:
Claude Code only for now — reach out for Codex, OpenCode, or any other agent.
/boxd-setup-fix stages the fix handler, registers the three fix webhooks (reusing the preview platform’s HMAC secret), creates the boxd-fix label, and sets up a headless-browser MCP for screenshot verification. It needs no Claude token — every boxd VM ships logged into Claude, and a fork is a full copy of the golden, so Claude runs in the fork already authenticated. What you’ll be asked for, once: That’s it — nothing to paste. Label any issue boxd-fix and the loop runs.
Optional — run fixes under a different Claude identity. By default the fork uses the golden’s own inherited Claude login. To use a different account (e.g. a dedicated service identity, or a headless golden with no login), run claude setup-token in your terminal and paste the printed token into the one-liner the skill prints — it lands at /etc/boxd-fix/claude.token and takes precedence over the inherited login. The value never appears in chat.

Patterns

What the bot actually does

The agent reads the issue/PR body, the linked files, and the project’s AGENTS.md / CLAUDE.md. The app is already running on the forked golden (forks inherit the running state), so for UI changes it takes a “before” screenshot at https://<fork>.boxd.sh, makes its changes, verifies them via chrome-devtools-mcp (navigate_pagewait_forevaluate_script), takes an “after” screenshot, commits, and exits. The handler on the golden then pushes the result:
  • Issue trigger: force-push to a fresh boxd-fix/issue-<N> branch and open a new PR with the preview URL pinned to the top.
  • PR comment / PR label trigger: push commits directly onto the PR’s existing head branch — Claude appears as a co-author on the PR.

Customizing the prompt

The skill ships a default prompt at /opt/boxd-platform/claude-prompt.md on the golden. To override it per-repo, commit .github/claude-prompts/fix-issue.md to your repo — the handler picks it up automatically on each trigger after a git fetch. Bias the prompt toward your conventions: which tests to run, which files to avoid, which style guide to follow.

Triggering from a PR comment

/boxd-fix on a PR comment runs Claude against that PR’s branch (not main), then pushes commits straight onto the PR. Useful for “hey Claude, the heading should be smaller” review feedback.

Triggering by label on a PR

Labeling a PR boxd-fix works the same as a /boxd-fix comment — fork → Claude → push to the PR branch.
The PR is opened (or commits are pushed) by your user account using a gh token persisted on the golden during /boxd-setup-golden. No “Allow Actions to create PRs” org toggle needed.

Trust caveat

A fork is a full copy of the golden, so it inherits the golden’s Claude login (and its gh auth) — the same login every boxd VM ships with. If your app on the fork is reachable by untrusted parties, treat those credentials as exposed on it; the cleanup hook destroys forks promptly on PR close, which is the main mitigation. (An optional override token at /etc/boxd-fix/claude.token, if you set one, is inherited the same way.) The trade-off vs. the prior GHA-based design: no BOXD_API_KEY round-trip, no GHA queue, no runner minutes — Claude auth lives on your own VM instead of GitHub Secrets.

FAQ

The fork stays alive until you close the PR. SSH in with boxd connect <fork-name>, tail /var/log/golden-preview/<fork-name>.log for the full Claude transcript, then run claude --resume <session_id> to take over interactively.
A fork is ~160ms, then you pay for the time the VM is up. The preview platform sets forks to idle-suspend, so a typical fix run is a few minutes of active VM time. End-to-end (label → PR opened) we’ve measured ~2 minutes for a small change.
A golden (/boxd-setup-golden) with the preview platform on it (/boxd-setup-preview). Fix layers on that — it reuses the preview platform’s fork/sync/teardown and adds only the Claude run. A preview-only golden stays free of the Claude token until you run /boxd-setup-fix.
Tail the global handler log: boxd machine exec <golden> -- 'tail -f /var/log/golden-preview.log'. The HMAC check is the most common failure — webhook(8) returns 200 with body Hook rules were not satisfied on HMAC mismatch (it intentionally doesn’t 401, so attackers can’t probe for the URL). Re-run /boxd-setup-fix to rotate the secret.
Today the slash command targets Claude Code. For Codex, Cursor, or OpenCode wiring, email contact@boxd.sh and we’ll prioritize.

Next

Agent sandboxes

The primitive underneath the loop. Hand an agent a full VM.

Fork from a golden

Where the warm copy comes from. ~160ms per fork.