🧑‍🧑‍🧒‍🧒

Processing Issues in Parallel Without Polluting Your Main Environment, Using Claude Code × git worktree

This article was automatically translated from theJapanese original by AI. It may contain translation errors.

Introduction

While letting Claude Code handle issues in VSCode, I found myself wanting to do the following:

  • Work on another issue locally in parallel while Claude works on one issue
  • Keep the dev server running in my main VSCode while I do other work, without being interrupted
  • As soon as Claude finishes, quickly verify the result in my local browser. If it looks good, have it create the PR right away
  • There are cloud-based AIs that handle everything on their own, but I want to review the diff and verify things using the VSCode I’m used to

As a solution, I used git’s worktree feature together with a custom slash command. With git worktree, you can create multiple independent working directories from a single repository (file edits don’t conflict with each other, and the git history is shared). I automated this with Claude Code’s custom slash commands.

How it works

Here’s what it looks like in action.

  1. Specify the issue you want worked on with /issue <GitHub Issue number> (manual)
  2. A git worktree is created automatically (automatic)
  3. A new VSCode window opens (automatic)
  4. A terminal opens automatically in the new VSCode, /issue-work runs, and work begins (automatic) work-image

Setup

Let’s put the /issue and /issue-work commands I created into a form that Claude Code can read as custom slash commands. If you place them under ~/.claude/commands/, they can be used across all repositories.

Adding the custom slash commands

Copy the text below and use it.

/issue (VSCode launcher)
---
description: Create a worktree from an issue number and automatically launch a Claude work session in a new VSCode window (launcher)
argument-hint: <issue number>
---

Set up the work environment for GitHub Issue #$ARGUMENTS.
Your role is that of a **launcher**. Implementation is not done in this session (the `/issue-work` on the new window side handles implementation).

## Ground rules (most important)

- **The current checkout is being used by the user for other work. Never touch it.**
  Editing files, `git checkout` / `git switch` / `git stash` in the current directory are prohibited.
- Running this command itself may be treated as "permission to create a branch for the worktree."

## Steps

1. Get the issue title with `gh issue view $ARGUMENTS --json title -q .title` and create a **slug**:
   - Convert to alphanumeric kebab-case (e.g., "Fix login form validation" → `fix-login-form-validation`)
   - For Japanese titles, translate loosely into short English that captures the content (e.g., "ログイン画面のバリデーション修正" → `fix-login-validation`)
   - Up to 3–5 words / about 30 characters. Remove symbols
   - From here on, the worktree name is `issue-$ARGUMENTS-<slug>` and the branch name is `issue/$ARGUMENTS-<slug>`
2. Run `git fetch origin` and create the worktree:
   `git worktree add .claude/worktrees/issue-$ARGUMENTS-<slug> -b issue/$ARGUMENTS-<slug> origin/HEAD`
   (If a branch with the same name already exists, drop `-b` and create it on the existing branch)
3. Copy files that are gitignored but required to run (such as `.env`) from the main checkout into the worktree.
4. Create `.vscode/tasks.json` inside the worktree. This is a **throwaway file** for auto-launching Claude in the new window (the `/issue-work` side deletes it right after startup):

   ```json
   {
     "version": "2.0.0",
     "tasks": [
       {
         "label": "claude-issue-worker",
         "type": "shell",
         "command": "claude \"/issue-work $ARGUMENTS\"",
         "runOptions": { "runOn": "folderOpen" },
         "presentation": { "focus": true, "panel": "dedicated" },
         "problemMatcher": []
       }
     ]
   }
   ```

5. Open a new VSCode window with `code <absolute path of worktree>`.
6. Report the following and finish:
   - The worktree path and that `/issue-work $ARGUMENTS` will auto-launch in the new window
   - If it doesn't auto-launch (e.g., the auto task isn't allowed), that running `claude "/issue-work $ARGUMENTS"` manually in the new window's terminal is fine

This session can continue to accept another `/issue <number>` (it can be reused as a dispatcher).
/issue-work (worker)
---
description: Inside a worktree, proceed from implementing the issue through waiting for verification to creating the PR (the worker auto-launched by /issue)
argument-hint: <issue number>
---

Handle GitHub Issue #$ARGUMENTS.
You are a **work session** launched inside a worktree. The current directory is that worktree.

## Ground rules

- Complete all work within this worktree. Do not touch anything outside the worktree (the main checkout).
- **Pushing and creating a PR are prohibited until the user says "OK".**

## Steps

1. First, delete `.vscode/tasks.json` (the throwaway file for auto-launch. Keep it out of the PR).
2. Check the issue's content and acceptance criteria with `gh issue view $ARGUMENTS`.
3. Install dependencies (e.g., `npm install`. The worktree is a fresh checkout, so `node_modules` doesn't exist).
4. Implement. If there are existing tests / lint, run them and make them pass.
5. Commit (do not push).
6. To prepare for verification, start the dev server **in the background**.
   Use a free port so it doesn't conflict with the server on the main checkout
   (e.g., `npm run dev -- --port 3001`. If 3001 is taken, try 3002, 3003, and so on).
7. When done, report the following and **stop, waiting for the user's confirmation**:
   - The verification URL (e.g., http://localhost:3001) and the screen / API / operations to check
   - A summary of the changes (what was changed and how)
8. When the user says "OK":
   - Stop the dev server.
   - Push and create a PR with `gh pr create` (include a change summary, verification details, and `closes #$ARGUMENTS` in the body).
9. If there is feedback to fix, fix it → re-commit → go back to step 7
   (if the server supports hot reload, you can leave it running).
10. After creating the PR, give cleanup instructions and finish:
    - That this window can be closed
    - That the worktree can be removed on the main checkout side by running
      `git worktree remove <absolute path of this worktree>`
      (Check the actual path with `pwd` and provide it. You can also ask the launcher-side Claude
      to "remove the worktree for issue #$ARGUMENTS".)

How it actually works

Here’s how it actually works under the hood. Feel free to skip this.

/issue (launcher): Only sets up the environment. Strictly instructed never to touch the main checkout. Can dispatch issues one after another in the same session.

/issue-work (worker): Auto-launched on the new window side, handles everything from implementation to waiting for verification.

Main terminal (dispatcher)
─────────────────────────────
1. Launch claude and accept the /issue 17 command
2. Get the issue title and content with gh
3. Create the worktree (the worktree name is auto-generated from the issue content)
4. Copy .env from main
5. Plant the throwaway tasks.json
6. Launch a new window with code <worktree path>


New VSCode window (opens automatically)
─────────────────────────────
The part that auto-launches Claude in the new VSCode window uses VSCode's auto task feature ("runOn": "folderOpen" in tasks.json).

1. The moment the folder opens, the auto task immediately deletes tasks.json (to prevent it leaking into the PR)
2. npm install (the worktree is a fresh checkout)
3. Implement → test → commit
4. If needed, start the dev server on a free port

Future outlook

  • It might be worth automating everything through push, PR creation, and worktree removal once work is done. I didn’t want the AI to push on its own, so I left that out this time.
  • As an aside, having Claude play a sound when it finishes work makes things go more smoothly.

References

Recent Articles

Network(beta)

Drag to move / Ctrl+wheel to zoom