> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boxd.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Per-PR preview URLs

> Comment /boxd-preview on a PR or issue → its own *.boxd.sh URL in seconds. Destroyed on PR close.

Comment `/boxd-preview` on a pull request and get a clickable `*.boxd.sh` URL back in seconds. Reviewers click it and land on a full Linux VM running the branch's exact code. Close the PR and the fork is destroyed automatically.

Each preview is a real VM forked from your golden, not a shared staging environment. Two reviewers can poke at two different PRs without stepping on each other's writes. The whole thing is wired up by one Claude Code slash command — [`/boxd-setup-preview`](/reference/skills).

## How it works

You keep one long-running **golden VM** with the app fully installed and running. It auto-suspends when nobody's hitting it, so idle cost stays near zero.

When someone comments `/boxd-preview`, a listener on the golden forks it (\~160ms), gets the fork serving the right code, and posts the fork's URL back as a comment. Forks land on the same worker as the source, so there's no network setup and no warm-up time.

What "the right code" means depends on where you comment:

| Comment                         | What the preview serves                                                         |
| ------------------------------- | ------------------------------------------------------------------------------- |
| `/boxd-preview` on a **PR**     | the PR's branch                                                                 |
| `/boxd-preview` on an **issue** | the golden as-is — no git work, the fastest path                                |
| `/boxd-preview branch=<ref>`    | any branch you name (works on issues **and** PRs)                               |
| `/boxd-preview --fix`           | the same, plus Claude makes a change — see [fix-on-issue](/agents/fix-on-issue) |

When a branch is synced, the platform picks the cheapest correct action from the diff against what the golden last served: **source-only changes hot-reload** (no rebuild), **dependency/schema changes rebuild**, **compose/env changes recreate**. Re-comment `/boxd-preview` any time to refresh the same fork. Closing the PR destroys it.

## Setup

<Note color="#E05A6D">
  **Set up a golden first.** Previews fork an existing golden, so run
  [`/boxd-setup-golden`](/preview-environments/set-up-a-golden) before this one.
</Note>

Then wire previews on top — **two ways**, with an identical runtime:

<Tabs>
  <Tab title="From your laptop">
    Install the boxd CLI (this also drops the skills), then run the skill in the repo:

    ```bash theme={"theme":"github-dark"}
    curl -fsSL https://boxd.sh/downloads/install.sh | sh
    ```

    ```text theme={"theme":"github-dark"}
    /boxd-setup-preview
    ```
  </Tab>

  <Tab title="Inside the golden (in-VM)">
    The golden already has Claude Code + the skills baked in. Open an agent shell
    on it and run the skill there — it wires the VM you're on directly, no `boxd machine
            exec`, no API key, no staging:

    ```bash theme={"theme":"github-dark"}
    boxd connect <golden>        # or: ssh <golden>.boxd
    ```

    ```text theme={"theme":"github-dark"}
    /boxd-setup-preview
    ```
  </Tab>
</Tabs>

<Note color="#E05A6D">
  Claude Code only for now — [reach out](mailto:contact@boxd.sh) if you want it packaged for Codex, OpenCode, or any other agent.
</Note>

Either way, the skill:

1. **Detects your stack** (docker-compose / npm / cargo / Procfile, …) and confirms the up / reload / rebuild commands with you — these are written to one config file on the golden, `/etc/boxd-platform.conf`. Nothing is committed to your repo.
2. **Probes fork-portability** and reports anything that breaks when the app is served from a fresh hostname (e.g. a dev server's host allowlist, hardcoded origins). You apply those fixes in your repo.
3. **Installs a `webhook(8)` listener** on the golden at `hooks.<golden>.boxd.sh` and registers two GitHub webhooks: the `/boxd-preview` comment trigger and a PR-close teardown. The HMAC secret stays on the golden and in GitHub's webhook config — never in your repo.

Every run logs to the golden (`/var/log/golden-preview/<vm>.log`), so a stuck preview is always debuggable.

## Patterns

### Refresh on new commits

Re-comment `/boxd-preview` after pushing. The same fork (named for the PR/issue) is re-synced in place — `git fetch` + reset, then hot-reload or rebuild as the diff demands. No fork churn; reviewers refresh the same URL.

### Stable URL per PR

The fork is named for the PR/issue number, so a PR gets a predictable `https://<repo>-pr-<n>.boxd.sh` that survives across refreshes. Handy for screenshot diffs and Playwright runs targeting the preview.

### Preview the golden as-is

`/boxd-preview` on an **issue** with no branch skips all git work and just serves the golden's current state — a fast way to hand someone a throwaway copy of the running app.

### Multi-service apps

If your app is more than one service (api + web + worker), put the orchestration inside the golden's `pm2` / `systemd` / `docker compose` setup. The fork inherits it, and the `up` command you set during setup brings everything back against the new code.

### Prefer automatic on every PR open?

The skill is on-demand (you comment to trigger), which keeps forks to PRs people are actually reviewing. If you'd rather fork automatically on every `pull_request` open/synchronize, wire a GitHub Actions workflow that calls `boxd machine fork` + `boxd machine exec` instead — the `boxd` CLI reads `BOXD_API_KEY` from the environment. [Reach out](mailto:contact@boxd.sh) if you want this as a turnkey variant.

## FAQ

<AccordionGroup>
  <Accordion title="What happens if 5 PRs get previews at once?">
    You get 5 forks, one per PR. The default cap is 10 VMs per user. Email `contact@boxd.sh` if you need more.
  </Accordion>

  <Accordion title="Does the fork have access to my real database?">
    Only if your golden does. By default the golden runs a local DB and the fork inherits a snapshot. Perfect for preview data. Wire it to a real DB the same way you would in any CI workflow.
  </Accordion>

  <Accordion title="Does the fork cost money while nobody's clicking it?">
    Forks auto-suspend on network idle and resume sub-ms on the next request. A PR sitting open over the weekend costs effectively nothing. Issue-mode previews that have no PR-close event are also reclaimed by a periodic TTL sweep.
  </Accordion>

  <Accordion title="Why didn't my dependency change show up?">
    The platform rebuilds only when the diff touches the paths you marked as rebuild triggers (lockfiles, schema, …) during setup. If a change isn't reflecting, check `/var/log/golden-preview/<vm>.log` on the golden — the deploy step logs which action it picked and why.
  </Accordion>
</AccordionGroup>

## Next

<Columns cols={2}>
  <Card title="Deploy on push" icon="https://mintcdn.com/azin/Ax1V0serIwQf0x_2/images/icons/rocket-2.svg?fit=max&auto=format&n=Ax1V0serIwQf0x_2&q=85&s=a1c1fe369620246bf94ebe0008da9032" href="/preview-environments/deploy-on-push" width="16" height="16" data-path="images/icons/rocket-2.svg">
    Ship to your golden on every push to main.
  </Card>

  <Card title="Fix on issue" icon="https://mintcdn.com/azin/Ax1V0serIwQf0x_2/images/icons/bug.svg?fit=max&auto=format&n=Ax1V0serIwQf0x_2&q=85&s=793936d309dacb75c015231f4754aa3e" href="/agents/fix-on-issue" width="16" height="16" data-path="images/icons/bug.svg">
    `/boxd-fix` or `/boxd-preview --fix` — Claude makes the change, you get a PR with a preview URL.
  </Card>
</Columns>
