agentleFS
dennisrongodennisrongo/claude-skills/skills/worktree-sandbox/SKILL.md

worktree-sandbox

Skill1 starsChanged 3 months agoMITView on GitHub

Give every git worktree its own sandboxed Docker stack - its services (API, frontend dev server, database, whatever the project runs) plus a dedicated Chromium - so parallel sessions can run and browser-test different branches and API versions at the same time with no port, cookie, or profile collisions and no change to the application repo. Stacks are watchable live and drivable by agents over CDP. Use this skill whenever the user says "spin up this branch", "run each worktree separately", "sandbox my browser testing", "preview what's running", "which browser is mine", "wt up", or "wt ls" - even if they don't name the skill. Not for deciding what to test or writing e2e tests (e2e-verify), or for recording a test as video (record-browser-test).

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 2 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Before the first wt up on a machine, read references/setup.md (prerequisites, every config field, private package feeds, HTTPS, file …

    line 32
  2. Distinctive:

    Read the repo's own dev scripts and README to fill in the commands and ports.

    line 35
  3. Very specific:

    Always give the branch when passing claude arguments, and put them after --, or PowerShell binds them to wt's own switches.

    line 61
  4. Distinctive:

    If something only works with a repo change, stop and tell the user what and why.

    line 81
  5. Very specific:

    Run wt which first. Sessions started with wt claude have WT_SLOT, WT_CDP_URL, and WT_VIEW_URL set and playwright / chrome-devtools MCP …

    line 87
  6. Very specific:

    Never stop, restart, attach to, or -Purge another slot's stack.

    line 94
  7. Very specific:

    When browser work starts, give the live-view URL so the user can watch or take over.

    line 116

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Worktree Sandbox

Each worktree gets a slot (1–20) running one Docker Compose stack. All services in a stack share one network namespace, so the API and the dev server keep the ports the app hardcodes, and the stack's own Chromium reaches them on localhost exactly as on a normal dev machine — even when the frontend hardcodes the API's address. Stacks can't see each other. Per slot, only two ports reach the host, both on 127.0.0.1:

WhatHost URL
Live view of the stack's browser (noVNC, interactive)http://localhost:<7900+slot>/vnc.html
CDP endpoint for agents (Playwright / Chrome DevTools MCP)http://127.0.0.1:<9220+slot>

The tooling ships in this skill: scripts/wt.ps1 (PowerShell 7, runs on Linux, macOS, and Windows/WSL2) and the browser image in docker/browser/. The services come from ~/.wt/config.json — any image, command, port, and working folder — and wt generates each stack's Compose file from it. Config and per-branch state live in ~/.wt/, never in a repo.

  • Before the first wt up on a machine, read references/setup.md (prerequisites, every config field, private package feeds, HTTPS, file ownership).
  • To write the services block for a stack, read references/stacks.md (ready-made recipes). Read the repo's own dev scripts and README to fill in the commands and ports; never guess a port the app doesn't use.

When to use this skill

  • The user wants several branches or worktrees running at once, each testable in a browser.
  • An agent needs a browser pointed at its worktree's code while other sessions run theirs.
  • The user wants to watch, or take over, what agents are doing in their browsers.

Commands

The branch argument defaults to the current worktree's branch.

CommandDoes
wt initCreates ~/.wt/config.json from assets/config.example.json. Once per machine.
wt up <branch> [-NoBuild]Creates the worktree if missing (a new branch starts from the latest base), refreshes shared base worktrees, assigns a slot, starts the stack, and runs hooks.afterUp once for a newly started stack (for example to open the live view; skip with -NoHook).
wt lsEvery slot: each service's health, view and CDP URLs.
wt whichSlot, ports, and URLs for the current worktree.
wt logs <branch> [-Service <name>|browser] [-Follow]Container logs.
wt claude <branch> [-- <claude args>]Starts Claude Code in the worktree with MCP wired to that slot's browser.
wt dashboard [-NoOpen]Writes and opens a page tiling every stack's live view side by side. The page checks the slot ports every few seconds, so tiles and branch names appear, change and disappear as stacks start and stop; no reload needed.
wt reload <branch>Reopens the start page (and browser.extraUrls) in the stack's browser once their services answer, replacing stale tabs. A newly started stack does this by itself.
wt down <branch> [-Purge]Stops the stack. -Purge also deletes its volumes, browser profile, and slot.
wt chown <branch>Returns ownership of container-written files in the worktree to the user.

Always give the branch when passing claude arguments, and put them after --, or PowerShell binds them to wt's own switches.

wt below is the alias from references/setup.md, which works inside a PowerShell session. From bash or any other shell there is no alias, and pwsh -File rejects --, so call it as:

pwsh -NoProfile -Command "& '<skill-dir>/scripts/wt.ps1' claude <branch> -- -p 'smoke test'"

Rules

1. The application repo is never changed

The whole point is a clean tree. wt writes nothing into the worktree except build output that is already gitignored.

❌ "The frontend hardcodes port 5000, so I edited its config to read the port from an env var." ✅ "The frontend keeps calling localhost:5000; inside slot 3 that is slot 3's API. No repo files changed."

If something only works with a repo change, stop and tell the user what and why. Before reporting done, run git status --porcelain in the worktree and quote it; any sandbox-caused line is a failure to report, not to hide.

2. Use only your own slot

Run wt which first. Sessions started with wt claude have WT_SLOT, WT_CDP_URL, and WT_VIEW_URL set and playwright / chrome-devtools MCP servers already pointed at the slot. Without them, connect with Playwright's chromium.connectOverCDP("<your CDP url>").

❌ "Slot 2's browser was free, so I used it." / "I restarted all stacks to pick up my change." ✅ "Slot 4 (feat/x): driving http://127.0.0.1:9224; other slots untouched."

Never stop, restart, attach to, or -Purge another slot's stack. -Purge on your own slot only when the user asks.

3. Open the app inside the stack's browser, never the host's

On the host, a hardcoded API address reaches nothing, or another stack.

❌ Opening http://localhost:3000 in the host browser or a separately launched Chrome. ✅ Navigating the stack browser (via CDP or the live view) to the app's normal dev URL.

4. A stack is up only when observed up

wt up returning is not the app running: package restores can take minutes.

❌ "Stack started, the page is working." ✅ "wt ls: slot 4 api:up web:up; the page loaded with title <title>."

A check you didn't run is not run, never passed. starting for more than a few minutes means read wt logs -Service <name> and quote the first error.

5. Tell the user where to watch

When browser work starts, give the live-view URL so the user can watch or take over. If another skill is driving the test (e2e-verify, if installed), hand it your slot's CDP URL as the browser to use; without it, drive the pages yourself through the MCP tools.

❌ Driving the stack's browser for ten minutes and reporting only "tests passed". ✅ "Watch at http://localhost:7904/vnc.html; starting the checkout flow now."

Report

End any sandbox task with this block:

Sandbox: slot <n> · branch <branch> · view http://localhost:<port>/vnc.html · CDP http://127.0.0.1:<port>
Health (wt ls): <service>:<up|starting|running|-> for each service
Repo clean: <quoted git status --porcelain output, or "clean (empty output)">
Not run: <checks skipped, or "none">

Troubleshooting

SymptomCause and fix
Edits don't hot-reloadWorktree on NTFS (/mnt/c/..., C:\). Move worktrees into the WSL filesystem, or set "polling": true and wt up again.
Restore fails with 401Private package feed needs credentials in the container. references/setup.md §5.
A service container exitsWrong image version or command for this project. Read wt logs -Service <name>, then fix its image / command in config.
A service stays startingIt listens on a different port than its port in config. Check its log for the address it printed.
No free slotsAsk the user which stopped branch to wt down -Purge. Never pick one yourself.
Worktree files owned by rootwt chown (also runs on wt down).
Live view blankChromium restarts on its own; check wt logs -Service browser.
Live view says the site can't be reachedChromium opened the start page before the services were up and kept the error. Once wt ls shows the services up, run wt reload <branch>.
macOS over SSH: keychain cannot be accessed ... does not allow user interaction on pullDocker's credential helper needs the login keychain, which an SSH session can't unlock. Run the first wt up from a terminal on the Mac itself so images are pulled and built there; wt ls, which, logs and down need no pull and worked over SSH. Running wt on the other machine with docker.context (references/setup.md) avoids this: pulls through a context worked.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.