🧑‍🧑‍🧒‍🧒

Claude Code × git worktree で、メイン環境を汚さず Issue を並行処理する

はじめに

VSCodeでClaude CodeにIssue対応を任せていると、以下のようなことをしたいなと思いました。

  • Claudeが1つのIssueを作業している間、ローカル環境で別のIssueも並行で進めたい
  • メインのVSCodeでは devサーバーを起動したまま別作業をしており、邪魔されたくない
  • Claudeの作業が終わったら、すぐローカルのブラウザで動作確認したい。OKならそのままPRを作ってほしい
  • クラウドで完結するAIもあるが、使い慣れているVSCodeを使って差分の閲覧と検証もしたい。

解決アプローチとして、gitのworktreeという機能とカスタムスラッシュコマンドを用いた。 git worktreeを使うと、1つのリポジトリから複数の独立した作業ディレクトリを作れる(ファイル編集が互いに衝突せず、git履歴は共有)。これをClaude Codeのカスタムスラッシュコマンドで自動化した。

動作イメージ

動作イメージは以下のようになります。

  1. /issue <GitHub Issue番号>で作業してほしいissueを指定(手動)
  2. git worktreeの自動作成(自動)
  3. VSCodeが別ウィンドウで立ち上がる(自動)
  4. 新規VSCodeのターミナルが自動で立ち上がり、/issue-workが実行され作業を開始する(自動) work-image

導入方法

今回作成した、/issue/issue-workをカスタムスラッシュコマンドとしてClaude Codeが読み込める形にします。 ~/.claude/commands/に置けば、全リポジトリ共通で使えます。

カスタムスラッシュコマンドの導入

以下のテキストをコピーして使用します。

/issue(VSCodeランチャー)
---
description: Issue番号からworktreeを作成し、新しいVSCodeウィンドウでClaude作業セッションを自動起動する(ランチャー)
argument-hint: <issue番号>
---

GitHub Issue #$ARGUMENTS の作業環境をセットアップしてください。
あなたの役割は**ランチャー**です。実装はこのセッションでは行いません(実装は新ウィンドウ側の `/issue-work` が担当)。

## 大前提(最重要)

- **現在のチェックアウトはユーザーが別作業中。絶対に触らない。**
  現在のディレクトリでのファイル編集・`git checkout` / `git switch` / `git stash` は禁止。
- このコマンドの実行自体が「worktree 用ブランチ作成の許可」とみなしてよい。

## 手順

1. `gh issue view $ARGUMENTS --json title -q .title` で issue タイトルを取得し、**スラッグ**を作る:
   - 英数の kebab-case に変換する(例: "Fix login form validation" → `fix-login-form-validation`
   - 日本語タイトルは内容を表す短い英語に意訳する(例: "ログイン画面のバリデーション修正" → `fix-login-validation`
   - 3〜5語・30文字程度まで。記号は除去する
   - 以降、worktree 名は `issue-$ARGUMENTS-<スラッグ>`、ブランチ名は `issue/$ARGUMENTS-<スラッグ>` とする
2. `git fetch origin` を実行し、worktree を作成する:
   `git worktree add .claude/worktrees/issue-$ARGUMENTS-<スラッグ> -b issue/$ARGUMENTS-<スラッグ> origin/HEAD`
   (同名ブランチが既に存在する場合は `-b` を外して既存ブランチで作る)
3. `.env` など gitignore されていて実行に必要なファイルを、メインのチェックアウトから worktree にコピーする。
4. worktree 内に `.vscode/tasks.json` を作成する。これは新ウィンドウで Claude を自動起動するための**使い捨てファイル**`/issue-work` 側が起動後すぐ削除する):

   ```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. `code <worktreeの絶対パス>` で新しい VSCode ウィンドウを開く。
6. 以下を報告して終了する:
   - worktree のパスと、新ウィンドウで `/issue-work $ARGUMENTS` が自動起動すること
   - もし自動起動しない場合(自動タスクが未許可など)は、新ウィンドウのターミナルで
     `claude "/issue-work $ARGUMENTS"` を手動実行すればよいこと

このセッションは引き続き別の `/issue <番号>` を受け付けられる(ディスパッチャーとして使い回せる)。
/issue-work(作業役)
---
description: worktree内でIssueの実装〜動作確認待ち〜PR作成まで進める(/issueから自動起動される作業役)
argument-hint: <issue番号>
---

GitHub Issue #$ARGUMENTS に対応してください。
あなたは worktree 内で起動された**作業セッション**です。カレントディレクトリがその worktree です。

## 大前提

- 作業はすべてこの worktree 内で完結させる。worktree の外(メインのチェックアウト)には触らない。
- **push と PR 作成はユーザーの「OK」が出るまで禁止**

## 手順

1. まず `.vscode/tasks.json` を削除する(自動起動用の使い捨てファイル。PR に混入させない)。
2. `gh issue view $ARGUMENTS` で issue の内容・受け入れ条件を確認する。
3. 依存関係をインストールする(例: `npm install`。worktree は新規チェックアウトなので `node_modules` が存在しない)。
4. 実装する。既存のテスト・lint があれば実行して通す。
5. コミットする(push はしない)。
6. 動作確認の準備として、dev サーバーを**バックグラウンド起動**する。
   メインのチェックアウトのサーバーと衝突しないよう、空いているポートを使うこと
   (例: `npm run dev -- --port 3001`。3001 が埋まっていれば 3002, 3003…と探す)。
7. 完了したら以下を報告し、**ユーザーの確認待ちで止まる**:
   - 確認用 URL(例: http://localhost:3001)と、確認すべき画面・API・操作手順
   - 変更内容の要約(何をどう変えたか)
8. ユーザーが「OK」と言ったら:
   - dev サーバーを停止する。
   - push し、`gh pr create` で PR を作成する(本文に変更概要・動作確認内容・`closes #$ARGUMENTS` を含める)。
9. 修正指摘があった場合は、修正→再コミット→手順7に戻る
   (サーバーがホットリロード対応なら起動したままでよい)。
10. PR 作成後、後片付けの案内をして終了する:
    - このウィンドウは閉じてよいこと
    - worktree の削除はメインのチェックアウト側で
      `git worktree remove <この worktree の絶対パス>` を実行すればよいこと
      (実際のパスを `pwd` で確認して案内する。ランチャー側の Claude に
      「issue #$ARGUMENTS の worktree を消して」と頼んでもよい)

実際の動作

実際の動作原理です。読み飛ばしても問題ありません。

/issue(ランチャー): 環境構築だけ。メインのチェックアウトには一切触らないことを厳命。同じセッションで次々と Issue をディスパッチできる

/issue-work(作業役): 新ウィンドウ側で自動起動され、実装〜確認待ちまでを担当

メインのターミナル(ディスパッチャー)         
─────────────────────────────
1. claudeを起動して /issue 17 コマンドを受理
2. ghでIssueタイトル・内容取得
3. worktree 作成(worktree名はIssueの内容から自動命名)
4. .env をメインからコピー
5. 使い捨て tasks.json を仕込む
6. code <worktreeパス> で新ウィンドウ起動 


新しいVSCodeウィンドウ(自動で開く)
─────────────────────────────
新しいVSCodeウィンドウでClaudeを自動起動する部分は、VSCodeの自動タスク機能(tasks.json の "runOn": "folderOpen")を利用。

1. フォルダを開いた瞬間、自動タスクでtasks.json を即削除(PR混入防止)
2. npm install(worktreeは新規チェックアウト)
3. 実装 → テスト → コミット
4. 必要があれば、空きポートで dev サーバー起動

今後の展望

  • 作業が終わったらpushとPR作成を自動で行ってworktreeも削除して完了するまでを自動化しても良いかもしれないです。AIにpushして欲しくなかったので、今回は含めていません。
  • 余談ですが、Claudeが作業完了したときに音を鳴らすようにすると、捗ります。

参考文献

https://tech.findy.co.jp/entry/2026/03/23/070000

新着記事

関連ネットワーク(beta)

ドラッグで移動 / Ctrl+ホイールでズーム