SKILL← All skills

Claude Desktop Setup

Make any repository work cleanly with Claude Code Desktop's preview + parallel git worktrees, regardless of language or framework.

Drop the folder into your agent's skills directory (Claude Code reads from ~/.claude/skills/claude-desktop-setup/).

SKILL.md
Download · 8 files
---
name: claude-desktop-setup
description: Make any repository work cleanly with Claude Code Desktop's preview + parallel git worktrees, regardless of language or framework. Generates .claude/launch.json, a SessionStart setup hook, a dev-server wrapper that gives each worktree collision-free ports, and isolated backing services (Redis DB index, database, frontend dev server, background worker). Use when the user wants to "make this repo Claude Code Desktop compatible", set up worktree previews, fix port collisions across worktrees, configure unique-port / per-worktree ports, or get the Preview button working in Desktop.
---

# Claude Code Desktop setup

Make the current repo boot a working preview in **Claude Code Desktop**, and — when it has more than one process or any stateful backing service — give every git worktree its own collision-free ports and isolated services so multiple Desktop sessions run in parallel without stepping on each other.

## Mental model — two layers

**Layer 1 (always): a working preview.** Desktop reads `.claude/launch.json` to know how to start the app and which port to open. The minimum viable setup is this one file.

**Layer 2 (when needed): per-worktree isolation.** Desktop creates a fresh git worktree per session (under `.claude/worktrees/`). If two worktrees both bind `:3000`, or share one Redis DB / one Postgres database, they collide. The fix is a tiny boot wrapper that derives **deterministic ports + service slots from the worktree's own path** — so the setup script and the boot script independently compute identical values, and no two worktrees ever overlap.

Skip Layer 2 for a single-process app with no backing services (a static site, a lone Next.js/Vite/Rails server) — Desktop's `autoPort` handles the one port. Add Layer 2 the moment there's a second port or a stateful service.

## The core trick (this is the whole idea)

```bash
hash_of() { printf '%s' "$1" | cksum | cut -d' ' -f1; }
WORKTREE_ROOT="$(git rev-parse --show-toplevel)"   # differs per worktree
APP="web"                                          # differs per app in a monorepo; any stable id for a single-app repo
export PORT=$(( 30000 + $(hash_of "$WORKTREE_ROOT:$APP")        % 10000 ))   # app server
export VITE_PORT=$(( 40000 + $(hash_of "$WORKTREE_ROOT:$APP:vite") % 10000 ))  # frontend
export REDIS_URL="redis://localhost:6379/$(( $(hash_of "$WORKTREE_ROOT:$APP:redis") % 16 ))"
```

`cksum` is everywhere (POSIX), stable for a given path, and differs across worktrees. The salt has **two axes**: the worktree root (so parallel worktrees don't collide) and the app id (so sibling apps in one monorepo worktree don't collide either) — plus the service name so each slot is independent. Anchor on the **worktree root** (`git rev-parse --show-toplevel`) — never `$PWD` or the branch name — so any script in any subdir agrees on the numbers. For a single-app repo `$APP` is just a constant; it costs nothing and keeps one formula for both cases.

---

## Procedure

### Step 1 — Detect the project (do this before asking anything)

Read, don't guess. Look for and read:

- **Dev command + port:** `package.json` scripts (`dev`/`start`), `Procfile.dev`, `Procfile`, `bin/dev`, `Makefile`, `Gemfile` (Rails → `bin/dev`/`bin/rails server`), `manage.py` (Django → `runserver`), `go.mod`/`main.go`, `Cargo.toml`, `docker-compose.yml`, `mix.exs`.
- **How the framework reads its port:** most read `$PORT` (Rails, Next.js via `-p`, Express, Django needs an arg, Vite via `--port`/config). Note the exact mechanism — it determines how the wrapper passes the port.
- **Backing services:** `docker-compose.yml`, `config/database.yml`, `config/cable.yml`, any `redis`/`REDIS_URL`/`DATABASE_URL` references, a separate frontend dev server (Vite/webpack), background workers (Sidekiq/Celery/BullMQ/Resque).
- **Secrets:** is there a `.env` / `.env.local`? Is it gitignored?
- **First-run needs:** dependency install (`npm install`, `bundle install`, `pip install`, `go mod download`), DB create/migrate/seed.
- **Existing Claude config:** read `.claude/settings.json` and `.claude/launch.json` if they exist — you'll MERGE, not clobber.
- **Monorepo?** Multiple app dirs each with their own manifest (e.g. `web/Gemfile`, `marketing/package.json`, `ios/`), a workspace file (`pnpm-workspace.yaml`, `turbo.json`, npm/yarn workspaces, Cargo workspace, Nx/Lerna), or obvious top-level app folders. If so, treat each previewable app separately — see "Monorepos" below.

Folder contents · 8 files

  • reference.md6.7 KB
  • SKILL.md11.6 KB
  • templates/dev-wrapper2.9 KB
  • templates/launch.json239 B
  • templates/settings.json196 B
  • templates/setup-worktree2.4 KB
  • templates/setup-worktree-monorepo2.2 KB
  • templates/worktreeinclude255 B

Members get the full folder as a single ZIP download.

Members read the full skill.

Join the Founding Club — every skill, field note, and drop while you're a member.