Claude
Skills
Sign in
Back

worktree

Included with Lifetime
$97 forever

Create an isolated git worktree from the correct base branch and check it out into a clean, gitignored directory. Use when the user asks to make a worktree, spin up a parallel/isolated workspace, work on something without disturbing the current checkout, branch off the current work, or run multiple agents on the same repo at once. Picks the base branch smartly — the current feature branch when you are on one, otherwise the develop integration branch — so worktrees continue your in-progress work by default instead of forking from the wrong place.

General

What this skill does


# Worktree

Create a git worktree off the **right base branch**, in a clean gitignored
directory, with the safety checks that keep the main checkout and `.gitignore`
correct. This skill only **creates** and **lists** worktrees. Removing and
pruning merged worktrees is `release-cleanup`'s job — do not delete here.

## Contract

Inputs:

- Repository root (must be inside a git work tree)
- Optional worktree/branch name (the new branch to create)
- Optional explicit base branch override (`from <base>` / `--base <base>`)
- Optional `--fetch` flag to refresh the base from origin before branching

Outputs:

- A new worktree directory at `.worktrees/<name>` checked out on a new branch
- The resolved base branch and why it was chosen
- A warning if the base is behind its remote (local mode does not auto-fetch)
- The path to `cd` into, ready for a parallel session

Creates/Modifies:

- Adds `.worktrees/` to `.gitignore` and commits that change if not already ignored
- Creates a new branch and a new worktree directory
- Never touches the current working tree's tracked files, never switches the current branch

External Side Effects:

- None by default (local tips only, no network)
- Only with `--fetch`: a single `git fetch origin <base>` to refresh the base ref

Confirmation Required:

- Before writing to `.gitignore` and committing it (one-time, only if `.worktrees/` is not yet ignored)
- Before reusing an existing branch instead of creating a new one
- Before overwriting or reusing a worktree path that already exists

Delegates To:

- `release-cleanup` to verify promotion and prune merged worktrees and branches
- `git-safety` if a branch about to live in a worktree may contain secrets

## Base Branch Selection (the core behavior)

The base is resolved in this order. **Local tips only — no automatic fetch.**

1. **Explicit override.** If the user named a base (`/worktree fix-auth from develop`
   or `--base release/1.4`), use it verbatim.
2. **On a feature branch → branch off the current branch.** If the current branch
   is not one of the protected/integration branches, the worktree forks from it.
   This is the default: you stay on your in-progress work and explore a sibling
   line without disturbing the current checkout.
3. **On a protected branch or detached HEAD → branch off `develop`.** If the
   current branch is `master`, `main`, `develop`, or `staging`, or HEAD is
   detached, fork from the integration branch instead of an integration branch's
   tip-as-feature. Prefer local `develop`; if no `develop` exists, fall back to
   the repository's default branch.

```text
current branch          ->  base the worktree forks from
----------------------      ----------------------------
feat/foo  (feature)     ->  feat/foo        (continue current work)
bugfix/x  (feature)     ->  bugfix/x        (continue current work)
master / main           ->  develop         (or default branch if no develop)
develop / staging       ->  develop
detached HEAD           ->  develop         (or default branch if no develop)
explicit "from <base>"  ->  <base>          (always wins)
```

Protected/integration set (never used as a "feature" base in step 2):

```
master  main  develop  staging
```

## Phase 1: Verify Repo and Resolve Inputs

```bash
git rev-parse --is-inside-work-tree            # must be true; else STOP
TOPLEVEL="$(git rev-parse --show-toplevel)"
CURRENT="$(git symbolic-ref --quiet --short HEAD || echo DETACHED)"
git worktree list                              # show what already exists
```

Resolve the **new branch name**:

- If the user gave a name, use it as the new branch name and the directory name.
- If no name was given, ask for one. Do not invent a throwaway name.
- Sanitize the directory name from the branch name (a branch like `feat/foo`
  becomes directory `.worktrees/feat-foo` while the branch stays `feat/foo`).

## Phase 2: Resolve the Base Branch

```bash
PROTECTED='master|main|develop|staging'

# Integration fallback, resolved to a ref that actually exists locally.
# Prefer local develop, then the remote-tracking origin/develop (still local,
# no fetch), then the repo's default branch.
if git show-ref --verify --quiet refs/heads/develop; then
  FALLBACK=develop
elif git show-ref --verify --quiet refs/remotes/origin/develop; then
  FALLBACK=origin/develop   # new branch will fork from and track origin/develop
else
  DEF="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD | sed 's#^origin/##')"
  DEF="${DEF:-master}"
  git show-ref --verify --quiet "refs/heads/$DEF" && FALLBACK="$DEF" || FALLBACK="origin/$DEF"
fi

# Apply the precedence. BASE is the start-point ref passed to `git worktree add`.
if [ -n "$EXPLICIT_BASE" ]; then
  BASE="$EXPLICIT_BASE"
elif printf '%s\n' "$CURRENT" | grep -qxE "$PROTECTED" || [ "$CURRENT" = DETACHED ]; then
  BASE="$FALLBACK"          # on a protected/detached ref -> integration branch
else
  BASE="$CURRENT"           # on a feature branch -> continue current work
fi
echo "Base: $BASE  (current: $CURRENT)"
```

`BASE` is always a concrete start-point (a local branch like `develop`, a
remote-tracking ref like `origin/develop`, or the user's explicit base). Report
the resolved base and the reason before creating anything.

## Phase 3: Freshness Check (warn, do not fetch)

Local mode is the default: branch from the local tip of `$BASE`. If the base has
an upstream and is behind it, warn — do not silently fetch.

```bash
if git rev-parse --verify --quiet "$BASE@{upstream}" >/dev/null; then
  BEHIND="$(git rev-list --count "$BASE..$BASE@{upstream}" 2>/dev/null || echo 0)"
  [ "$BEHIND" -gt 0 ] && echo "WARNING: local $BASE is $BEHIND commit(s) behind its remote. Using local tip. Pass --fetch to update first."
fi
```

Only if the user passed `--fetch`:

```bash
git fetch origin "$BASE"
git update-ref "refs/heads/$BASE" "origin/$BASE"   # only when safe / fast-forward
```

Do not fetch by default. Do not rewrite a base branch that has local commits not
on the remote — warn and use the local tip instead.

## Phase 4: Ensure `.worktrees/` Is Gitignored

The worktree directory must never be tracked. Verify, and fix once if needed.

```bash
if ! git -C "$TOPLEVEL" check-ignore -q .worktrees; then
  # .worktrees/ is not ignored yet — confirm, then add and commit
  printf '\n# Local git worktrees (created by the worktree skill)\n.worktrees/\n' >> "$TOPLEVEL/.gitignore"
  git -C "$TOPLEVEL" add .gitignore
  git -C "$TOPLEVEL" commit -m "chore: ignore .worktrees/ directory"
fi
```

This is the only commit the skill makes, and only the first time in a repo.
Confirm before committing in a shared repo.

## Phase 5: Create the Worktree

```bash
NAME="<sanitized-name>"
BRANCH="<new-branch-name>"
DEST="$TOPLEVEL/.worktrees/$NAME"

# Guard: destination must not already exist
[ -e "$DEST" ] && { echo "Path exists: $DEST — choose another name or remove it first."; exit 1; }

if git show-ref --verify --quiet "refs/heads/$BRANCH"; then
  # Branch already exists: confirm, then attach it (no -b, no new branch)
  git worktree add "$DEST" "$BRANCH"
else
  # New branch off the resolved local base tip
  git worktree add -b "$BRANCH" "$DEST" "$BASE"
fi

git worktree list
```

Rules:

- Use `-b` only when creating a new branch. If the branch exists, attach it and
  say so — never silently reset an existing branch.
- A branch can be checked out in only one worktree at a time. If `$BRANCH` is
  already checked out elsewhere, report where and stop.
- Never pass `--force`. If git refuses, surface the reason and let the user decide.

## Phase 6: Report and Hand Off

Report:

- Worktree path: `.worktrees/<name>`
- New branch and the base it forked from (plus why that base)
- Any freshness warning from Phase 3
- How to start work there: `cd .worktrees/<name>` and open a parallel session in
  that directory. Each worktree is an independent checkout sharing one `.git`.
- If the project needs dependencies, install them inside the worktree before
  r

Related in General