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.
GitHub event ───► https://hooks.<your-golden>.boxd.sh/hooks/<trigger>


                  webhook(8) on your golden VM

                  ┌───────────────┴───────────────┐
                  ▼                               ▼
        fix-handler.sh                     teardown (shared)
  (forks golden, syncs the branch,      (destroys the fork when
   runs Claude, pushes/opens the PR)     the PR closes)
Three triggers fire the fix handler; teardown is the preview platform’s shared hook:
TriggerFires onResult
/boxd-fix or /boxd-preview --fix commentissue_commentFork golden → Claude → new PR (issue) or push to PR branch (PR)
boxd-fix label on an issueissues.labeledFork golden → Claude → new PR off the default branch
boxd-fix label on a PRpull_request.labeledFork golden → Claude → push to the PR branch
PR closedpull_request.closedDestroy the matching fork (shared with preview)
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 destroy. 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):
curl -fsSL https://boxd.sh/downloads/cli/install.sh | sh
Then run the skill in the repo:
/boxd-setup-fix
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:
StepWhatHow
1Confirm the planOne short message listing the golden, the fix webhooks, and what’s already present vs. missing
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 ssh <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. Auto-suspend kicks in after 30s of idle, 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 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

https://mintcdn.com/azin/Ax1V0serIwQf0x_2/images/icons/robot.svg?fit=max&auto=format&n=Ax1V0serIwQf0x_2&q=85&s=e91e744c2d3cd5da053167486b6834bf

Agent sandboxes

The primitive underneath the loop. Hand an agent a full VM.
https://mintcdn.com/azin/Ax1V0serIwQf0x_2/images/icons/copy.svg?fit=max&auto=format&n=Ax1V0serIwQf0x_2&q=85&s=f3623fe516eebf87b33b3a1022852286

Fork from a golden

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