{"skill":{"slug":"git-worktree-setup","displayName":"git-worktree-setup","summary":"Use when the user explicitly asks to \"generate / update a git worktree auto-setup script for this repo.\" Note this skill is NOT triggered when a new worktree...","description":"---\nname: git-worktree-setup\ndescription: Use when the user explicitly asks to \"generate / update a git worktree auto-setup script for this repo.\" Note this skill is NOT triggered when a new worktree is created — the script and hook it produces are. Workflow is audit-the-repo-first, propose a draft plan, ask the user only the questions you can't infer, then write the tailored setup-worktree script + matching agent-tool hook config (Claude Code SessionStart / WorktreeCreate, Codex/Cursor manual + git hook, Gemini CLI, etc.). Also used to update an existing script as the project structure evolves.\nlicense: MIT\ncompatibility: Works with any agent that supports the Agent Skills format (Claude Code, Codex, Cursor, OpenCode, Gemini CLI, etc.). Generated setup script requires bash + git + standard POSIX utils (grep, awk, ln, cp, shasum).\n---\n\n# Git Worktree Setup\n\n## What this skill is / is not\n\n**Produces**: a tailored `scripts/setup-worktree.sh` (or similar) for the current repo + the matching agent-tool hook config that auto-invokes it + a manual entry-point as a safety net.\n\n**Is NOT**: the thing that runs every time a new worktree is created. **That's the hook.** This skill only runs when the user explicitly asks for it:\n- \"Set me up worktree auto-bootstrap\"\n- \"Every `git worktree add` requires me to manually install / copy `.env` — automate it\"\n- \"Project structure changed — update the worktree init script\"\n\n**Core working style: audit the repo yourself → put a concrete draft on the table → ask only the questions you couldn't infer → land it.**\n\nDon't dump 7 questions on the user upfront — that's annoying. Read the code, read the configs, infer everything inferable, **walk in with a draft proposal**, and let the user adjust.\n\n## 4-step workflow\n\n### Step 1: Audit the repo yourself (do not ask the user)\n\n**This is dynamic inference, not checking boxes off a static list.** The table below is **examples of common signals** — you must expand the investigation based on what you actually find. Any tool, any stack, any project-specific convention is fair game. Read unfamiliar config files; grep for unknown CLI names; if the README / CONTRIBUTING / Makefile / justfile / Taskfile mentions \"setup\" / \"bootstrap\" / \"install\" steps, read them — they often hold the repo's own definition of \"what a fresh machine needs.\"\n\n**Starting signals (examples, not exhaustive):**\n\n| What to look at | What to infer |\n|---|---|\n| `package.json` (root + `workspaces` field) | npm/pnpm/yarn? monorepo? what workspace globs? |\n| `pnpm-workspace.yaml` / `lerna.json` / `nx.json` / `turbo.json` | confirms monorepo tooling |\n| `pyproject.toml` / `Pipfile` / `uv.lock` / `requirements.txt` | Python? poetry / uv / pip? share `.venv`? |\n| `Cargo.toml` (with `workspace` section) | Rust? share `target/`? |\n| `go.mod` | Go? usually nothing to share |\n| `Gemfile` / `mix.exs` / `composer.json` / `pubspec.yaml` etc. | other ecosystems — infer their deps dirs analogously |\n| `.gitignore` | hunt ignored entries: `node_modules` / `.venv` / `.env` / `dist` / `*.state` etc. — these are the share/copy candidates; don't skip unfamiliar ignores either, they're often project-specific cache |\n| `.env.example` / `.dev.vars.example` / `apps/*/.dev.vars.example` / `config/*.example` | hints at which secret / config files need Copy |\n| `docker-compose*.yml` / `compose.yml` / `Dockerfile.dev` | stateful services list (pg/redis/mysql) + volume paths + host port bindings |\n| `wrangler.toml` / `fly.toml` / `serverless.yml` / `terraform/*` etc. | various IaC / platform configs often imply a local state directory |\n| Existence of `.claude/` / `.cursor/` / `.codex/` / `.aider*` / `.opencode/` etc. | infer the user's current agent tooling |\n| `Makefile` / `justfile` / `Taskfile.yml` / `bin/setup` / `script/bootstrap` | project's own setup entry point — its install / link / copy steps are gold for worktree bootstrap |\n| \"Getting started\" / \"Local dev\" sections in `README.md` / `CONTRIBUTING.md` / `docs/setup*.md` | the human-language \"what a fresh machine needs\" list |\n| `.github/workflows/*.yml` / `.gitlab-ci.yml` etc. | how CI sets up the env ≈ what local probably needs |\n| `scripts/setup-worktree.sh` / `scripts/setup-worktree.sh` / `bin/worktree-*` etc. | already exists? → decide new-build vs update mode |\n| Whether main repo's `node_modules/`, `apps/*/node_modules/`, `.venv/` etc. actually exist on disk | validates the inference + tells you what's currently linkable |\n| **Any unfamiliar top-level directory** | e.g. `references/`, `vendor/`, `third_party/`, `fixtures/` — could be deliberate shared resources; ls inside before asking (symlinks? large files? test data?) |\n\n**Expand actively**: each of the above can lead to further investigation. Reading `package.json`, you spot `husky` → check whether `.husky/` should be shared. You spot `playwright` → check whether browser cache (`~/.cache/ms-playwright`) should be shared. Reading `pyproject.toml`, you find `[tool.uv]` → where does uv put its cache. **Don't skip just because something isn't in the table.**\n\nBy the end of audit you should have:\n- a **resource candidate list** pre-classified into Share / Copy / Generate, each item with its source evidence\n- the **inferred agent tool** (based on config dir presence)\n- whether a **script already exists** (decides new vs update)\n- the **open questions worth asking** (items audit can't decide but are decision-critical)\n\n### Step 2: Walk in with a concrete draft (don't bombard with questions)\n\nAggregate the audit into a **resource list proposal**, three tiers laid out. **Give a concrete recommendation for what you can infer**; **mark \"needs confirmation\" for what you can't**. Example:\n\n> I went through the repo: looks like an npm-workspaces monorepo (`apps/api`, `apps/web`, `packages/*`), Cloudflare Workers + Vite. `.claude/settings.json` exists, so Claude Code.\n>\n> Here's what I'd configure for worktree auto-init:\n> - **Share (symlink)**: `node_modules`, `apps/*/node_modules`, `packages/*/node_modules`\n> - **Copy**: `apps/api/.dev.vars` (saw `.dev.vars.example`)\n> - **Hook**: `.claude/settings.json` add `SessionStart` calling `bash $(...)/scripts/setup-worktree.sh`\n> - **Manual entry point**: `bash scripts/setup-worktree.sh` always works\n>\n> A few I need to confirm:\n> 1. **`.wrangler/state`** (Cloudflare local D1/R2 state): share across worktrees? Share = all worktrees see same local DB; isolated = each its own. **Depends on whether you'll run `dev` in multiple worktrees concurrently.**\n> 2. Besides Claude Code, do you / your team also use Codex / Cursor / Gemini CLI? Want hooks for those too?\n> 3. Didn't see custom reference-repo / build-output sharing needs — confirm none?\n>\n> Look right?\n\n### Step 3: Tighten with 1-2 follow-ups based on the answer\n\nAfter the user answers, only ask the necessary follow-ups based on what they said. Common follow-ups:\n\n- User says \"yes, I run multiple worktrees concurrently\" → \"For stateful services (`pgdata`, SQLite WAL), do you want concurrent isolation (Copy) or sharing (Share)? Default recommendation is Copy to prevent corruption.\"\n- User says they also use Codex/Cursor/Gemini → \"I'm not familiar with X's hook mechanism — could you point me at the docs / how do you expect it to auto-run? Worst case I can hook in via git's `post-checkout`.\"\n- User mentions a custom resource → \"Share or Copy? Is it written to often?\"\n\n**Don't open another round of questions** — decide what you can decide.\n\n### Step 4: Generate + verify\n\n1. Copy [`setup-worktree.sh`](setup-worktree.sh) template into `<repo>/scripts/`\n2. Fill in the \"resource declarations\" block at the bottom per the agreed plan (leave the helper functions block as-is)\n3. Merge the matching hook config (from [`hook-config.json`](hook-config.json)) into `.claude/settings.json` (or whatever the tool's config location is; multiple tools = multiple hooks)\n4. **Run twice to verify idempotency**: first run links, second run skips everything\n5. In a freshly-created worktree, actually run `dev` / `test` end-to-end\n6. Report back: what was installed, what files changed, how to invoke manually\n\n**When updating an existing script**: use `Edit` to diff-edit the resource declarations block. **Don't touch the helper functions** unless they're genuinely outdated.\n\n## Three-tier strategy (the agent's classification framework)\n\n| Tier | Examples | Why | How |\n|---|---|---|---|\n| **Share** (symlink) | `node_modules`, package-manager caches, stateful DB shared across worktrees | saves disk + install time; multiple worktrees see same data | `ln -s $MAIN/<path> $WORKTREE/<path>` |\n| **Copy** | secrets / env files, signing keys, stateful files used concurrently | each worktree may diverge; mustn't break if main is deleted; mustn't get torn under concurrent writes | `cp -R` once (re-run skips) |\n| **Generate** | dev port, `COMPOSE_PROJECT_NAME`, local socket | must differ per-worktree | `hash(branch) % range` for ports; `clean_branch_name` for container names |\n\n**Stateful data**: in single-writer concurrent mode, must be Copy (Postgres, SQLite WAL are single-writer); for sequential use, can be Share. **This must be in Step 2's \"needs confirmation\" list — don't decide it for the user.**\n\n## Agent tool trigger reference\n\n| Agent tool | Trigger mechanism |\n|---|---|\n| Claude Code | `SessionStart` hook (most portable) / `WorktreeCreate` hook (only fires for `claude --worktree`, strict stdout contract: print only path, progress to `/dev/tty`) |\n| Codex | **No equivalent hook mechanism** currently — manual script + `post-checkout` git hook |\n| Cursor | Same as above |\n| Gemini CLI | **Not sure — ask the user for docs** |\n| Aider / others | **Not sure — ask the user for docs** |\n| Multi-tool / no agent tool | Universal fallback: `post-checkout` git hook + manual `bash scripts/setup-worktree.sh` |\n\n**Key principles**:\n- For tools you don't know, **don't make up hook configs**. Ask the user.\n- **Always preserve the manual entry point** `bash scripts/setup-worktree.sh`. Any hook breaking or tool-switching shouldn't leave you stuck.\n- Multi-tool? **Hook them all to the same script** — the script itself is idempotent.\n\n## Quick reference: common resources → default tier\n\n| Resource | Default tier | Note |\n|---|---|---|\n| Root `node_modules/` | Share | npm workspaces hoist target |\n| `apps/*/node_modules/`, `packages/*/node_modules/` | Share — **don't skip** | bundlers walk only one parent up from workspace; subpath exports like `zod/v3` only exist in the workspace's local install |\n| `.venv/`, `venv/` | Share (semi-readonly) | Python virtualenv shebangs are absolute-path-baked; same machine OK |\n| Build cache (`.next/`, `target/`, `dist/`) | Skip or Share | usually rebuilds fast enough |\n| `.env*`, `.dev.vars` | Copy | secrets can't be shared |\n| `*.wrangler/state`, `pgdata/`, `redis-data/` | **Depends on concurrency — list as needs-confirmation** | share/copy depends on concurrent use |\n| Dev port | Generate | hash branch |\n| `COMPOSE_PROJECT_NAME` | Generate | clean branch name |\n| Custom (reference-repo symlinks, build artifacts, etc.) | **Find during audit; if unsure list as needs-confirmation in Step 2** | |\n\n## Common mistakes (self-check while writing the script)\n\n- **Linking only root `node_modules`, missing workspaces**: symptom `Could not read from file: .../zod/v4`. Loop both `apps/*` and `packages/*`.\n- **`git worktree add` polluting stdout** (under `WorktreeCreate` hook): redirect with `>/dev/null 2>&1`, send progress to `/dev/tty`.\n- **Symlinking single-writer stateful directories**: concurrent `dev` corrupts. Step 2 must list as needs-confirmation.\n- **Not idempotent**: re-runs must skip everything. Template's `link_resource` handles this.\n- **Dead symlinks**: check `[ -e \"$target\" ]` before linking.\n- **Hardcoding the main repo path**: derive with `git rev-parse --git-common-dir`.\n- **Symlinking `.env`**: must be Copy (symlink edits leak across worktrees).\n- **Skipping audit and bombarding the user with questions**: audit first, infer what's inferrable; questions to the user are judgement calls, not facts.\n- **Deciding stateful policy for the user**: Step 2 must ask.\n\n## Implementation resources\n\n- Script template: [`setup-worktree.sh`](setup-worktree.sh)\n- Hook config candidates: [`hook-config.json`](hook-config.json)\n- Per-stack snippets: [`recipes.md`](recipes.md)\n\n## Verification checklist (run after generate / update)\n\n- [ ] Script runs on fresh `git worktree add` and exits 0\n- [ ] Re-run = no-op (all \"skip — already linked\")\n- [ ] `npm run dev` (or stack equivalent) actually starts, no \"module not found\"\n- [ ] Tests / typecheck pass in the new worktree\n- [ ] Removing main-repo's optional resource → script logs \"skip\" not error\n- [ ] Under `WorktreeCreate`: stdout contains only the worktree path\n- [ ] **Manual entry point** (`bash scripts/setup-worktree.sh`) also runs\n- [ ] Confirmed resource list matches what got generated\n","topics":["Git"],"tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":348,"installsAllTime":13,"installsCurrent":0,"stars":0,"versions":1},"createdAt":1777803845958,"updatedAt":1778492833926},"latestVersion":{"version":"1.0.0","createdAt":1777803845958,"changelog":"Initial release of git-worktree-setup.\n\n- Introduces an agent skill to generate or update a tailored git worktree auto-setup script (`setup-worktree.sh`) and agent tool hook config for the current repo.\n- Audits project structure to infer which resources should be shared or copied in new worktrees; proposes a concrete draft plan and only asks the user for information that can't be automatically determined.\n- Supports multiple agent tools (Claude Code, Codex, Cursor, OpenCode, Gemini CLI, etc.) and provides both auto and manual invocation options.\n- Designed to update the setup script as the project evolves, not to run on every new worktree—only on explicit user request.","license":"MIT-0"},"metadata":null,"owner":{"handle":"imsai-sh","userId":"s17eqbjgx2nbbdxmvpv1akjmbx83hrnc","displayName":"sai","image":"https://avatars.githubusercontent.com/u/14907300?v=4"},"moderation":null}