Claude Code + Git worktree + Raycastで並列作業を快適にする
はじめに
今更ながらgit worktreeを使い始めたのですが、Claude CodeとRaycastのスニペットを組み合わせたら、並列作業の立ち上げが一瞬でできるようになったので、その方法を共有します。
モノレポや複数リポジトリを束ねたプロジェクトにも対応できるスクリプト付きです。
こんな人に読んでほしい
- Claude Codeを日常的に使っている人
- 複数タスクを並行して進めたい人
- モノレポ / マルチリポジトリ構成のプロジェクトで作業している人
本記事の要約はこちら💡

困っていたこと
Claude Codeはターミナル上で動くAIエージェントです。基本的には1つのセッションで1つのタスクを進めていくわけですが、こういう場面で困ります。
- 機能開発の真っ最中に急ぎで直したいタスクが発生する
- バックエンドとフロントエンド、別々に並行して進めたい
- 時間のかかるタスクを走らせつつ、別の作業も片付けたい
じゃあ別のターミナルでもう1つClaude Codeを起動すればいいかというと、同じファイルを同時に編集して片方の変更が吹き飛ぶリスクがあるんですよね。これが地味に怖い。
解決策の比較
Claude Codeで並列作業する方法をざっくり3つ比較してみます。
| 方法 | ファイル競合 | コスト | セットアップ | 適したケース |
|---|---|---|---|---|
| Git worktree | なし | 低い | 中 | 全く異なるタスクの並列(推奨) |
| 複数セッション(同一ディレクトリ) | あり | 低い | 低 | 担当ディレクトリが明確に分かれている場合 |
| Agent Teams(swarm) | あり | 高い | 高 | エージェント間の連携が必要な場合 |
結論から言うと、独立した別タスクを並行するならGit worktree が一番適していて、Claudeも推奨している手法です。この記事ではこの方法を詳しく解説します。
Git worktreeとは
知ってる方は読み飛ばしてください。
Git worktreeは、1つのリポジトリから複数の作業ディレクトリを作れるGitの標準機能です。存在は知っていたけど使ったことがなかった、という人も多いのではないでしょうか(自分がそうでした)。
何がうれしいかというと:
-
.gitは共有なのでディスク容量をほとんど食わない - 各worktreeは独立したファイルシステムなので、ファイル競合がゼロ
- それぞれ異なるブランチで自由に作業できる
基本的な使い方
シンプルなリポジトリの場合
1つのリポジトリだけなら、こんな感じで始められます。
# worktreeを作成(新しいブランチも同時に作成)
git worktree add ../my-project-task-b -b feat/task-b main
# worktree先でClaude Codeを起動
cd ../my-project-task-b
claude
# 作業が終わったら片付け
git worktree remove ../my-project-task-b
複数ターミナルでの運用イメージ
ターミナル1(元のタスク) ターミナル2(新しいタスク)
/projects/my-app /projects/my-app-task-b
ブランチ: feat/task-a ブランチ: feat/task-b
│ │
├─ claude(セッション継続) ├─ claude(新しいセッション)
│ 元のタスクをそのまま続行 │ 別タスクを独立して進行
それぞれのClaude Codeは完全に独立しています。元のセッションの文脈は引き継がれないので、新しいセッションでは普通にやりたいことを伝えればOKです。
実践:マルチリポジトリ構成での一括worktree管理
これが面倒だった
例えば複数リポジトリを1つの親ディレクトリにまとめて管理していたとする
my-project/
├── CLAUDE.md
├── backend/ ← default: main
├── frontend/ ← default: develop
├── infra/ ← default: master
├── api/ ← default: main
└── scripts/ ← default: master
この場合、リポジトリごとにworktreeを作る必要があります。しかもデフォルトブランチがバラバラ。手動でやるのはしんどいので、一括管理スクリプトを書きました。
一括管理スクリプト
#!/bin/zsh
#
# worktree 一括管理スクリプト
#
# 使い方:
# ./worktree-manager.sh create <task-name> # worktree を作成
# ./worktree-manager.sh remove <task-name> # worktree を削除
# ./worktree-manager.sh list # 一覧表示
#
# ===== ここより下の===までをプロジェクトに合わせて変更 =====
PROJECT_DIR="/path/to/your/project"
WORKTREE_BASE="/path/to/worktrees"
# 各リポジトリとデフォルトブランチ(repo:branch の形式)
REPOS=(
"backend:main"
"frontend:develop"
"infra:master"
"api:main"
"scripts:master"
)
# worktree 先にシンボリックリンクするファイル/ディレクトリ
# ⚠ .claude はディレクトリごとリンクすると会話履歴が混ざる可能性あり(後述)
SYMLINK_ITEMS=("CLAUDE.md" "AGENTS.md" "docs" ".claude")
# ===============================================
create_worktree() {
local task_name="$1"
local target_dir="$WORKTREE_BASE/$task_name"
if [ -d "$target_dir" ]; then
echo "エラー: $target_dir は既に存在します"
exit 1
fi
mkdir -p "$target_dir"
# 各リポジトリの worktree を作成
for entry in "${REPOS[@]}"; do
local repo="${entry%%:*}"
local default_branch="${entry##*:}"
local branch_name="feat/$task_name"
local repo_dir="$PROJECT_DIR/$repo"
local worktree_dir="$target_dir/$repo"
if [ -d "$repo_dir/.git" ]; then
echo "[$repo] fetch 中..."
git -C "$repo_dir" fetch origin "$default_branch" --quiet 2>/dev/null
echo "[$repo] worktree 作成中 (origin/$default_branch → $branch_name)..."
git -C "$repo_dir" worktree add "$worktree_dir" -b "$branch_name" "origin/$default_branch" 2>&1
if [ $? -ne 0 ]; then
echo " ⚠ $repo の worktree 作成に失敗しました。スキップします。"
fi
fi
done
# 共有ファイルをシンボリックリンク
for item in "${SYMLINK_ITEMS[@]}"; do
if [ -e "$PROJECT_DIR/$item" ]; then
ln -s "$PROJECT_DIR/$item" "$target_dir/$item"
echo "[symlink] $item"
fi
done
echo ""
echo "====================================="
echo "worktree を作成しました: $target_dir"
echo ""
echo "Claude Code を起動:"
echo " cd $target_dir && claude"
echo "====================================="
}
remove_worktree() {
local task_name="$1"
local target_dir="$WORKTREE_BASE/$task_name"
if [ ! -d "$target_dir" ]; then
echo "エラー: $target_dir が見つかりません"
exit 1
fi
for entry in "${REPOS[@]}"; do
local repo="${entry%%:*}"
local worktree_dir="$target_dir/$repo"
local repo_dir="$PROJECT_DIR/$repo"
if [ -d "$worktree_dir" ]; then
echo "[$repo] worktree を削除中..."
git -C "$repo_dir" worktree remove "$worktree_dir" 2>/dev/null
if [ $? -ne 0 ]; then
echo " ⚠ 強制削除します..."
git -C "$repo_dir" worktree remove --force "$worktree_dir" 2>/dev/null
fi
fi
done
rm -rf "$target_dir"
echo ""
echo "worktree を削除しました: $target_dir"
}
list_worktrees() {
if [ ! -d "$WORKTREE_BASE" ] || [ -z "$(ls -A "$WORKTREE_BASE" 2>/dev/null)" ]; then
echo "アクティブな worktree はありません"
return
fi
echo "アクティブな worktree:"
echo ""
for dir in "$WORKTREE_BASE"/*/; do
if [ -d "$dir" ]; then
local name
name=$(basename "$dir")
echo " $name"
echo " パス: $dir"
echo " 起動: cd $dir && claude"
echo ""
fi
done
}
case "$1" in
create)
if [ -z "$2" ]; then
echo "使い方: $0 create <task-name>"
echo "例: $0 create urgent-hotfix"
exit 1
fi
create_worktree "$2"
;;
remove)
if [ -z "$2" ]; then
echo "使い方: $0 remove <task-name>"
exit 1
fi
remove_worktree "$2"
;;
list)
list_worktrees
;;
*)
echo "worktree 一括管理スクリプト"
echo ""
echo "使い方: $0 {create|remove|list} [task-name]"
echo ""
echo "コマンド:"
echo " create <task-name> 全リポジトリの worktree を作成"
echo " remove <task-name> worktree を削除して片付け"
echo " list アクティブな worktree を一覧表示"
exit 1
;;
esac
やっていること
スクリプトの中身はシンプルで、以下を自動でやっているだけです。
- 各リポジトリのリモートをfetch - 最新のデフォルトブランチを取得
-
worktreeを作成 -
origin/デフォルトブランチからfeat/タスク名ブランチを切る - 共有ファイルをシンボリックリンク - CLAUDE.mdなどを元のディレクトリと共有
実際のワークフロー
並列タスクが発生したとき
やることは3ステップだけ。
# ① 別のターミナルを開いてworktreeを作成
cd /path/to/your/project
./worktree-manager.sh create urgent-hotfix
# ② worktree先でClaude Codeを起動
cd /path/to/worktrees/urgent-hotfix
claude
# ③ 普通にタスクを指示する
# 「web/の〇〇コントローラーでバグを修正して」
元のターミナルに戻れば、元のタスクをそのまま続行できます。何も失われていません。
作業が終わったら
# ① worktree側のClaude Codeを終了
/exit
# ② 必要に応じてブランチをpush(Claude Codeのセッション内で済ませてもOK)
# ③ worktreeを片付け
cd /path/to/your/project
./worktree-manager.sh remove urgent-hotfix
Raycastスニペットで一発起動
ここまでの手順、毎回手で打つのは面倒なので、自分はRaycastのスニペット機能に登録して、一発で起動できるようにしています。
スニペットの登録手順
- Raycastを開き、
Create Snippetを検索して選択 - 以下の内容でスニペットを作成
| 項目 | 設定例 |
|---|---|
| Name | Claude Code Worktree |
| Keyword |
ccwt など任意 |
スニペット内容:
cd /path/to/your/project && ./worktree-manager.sh create {cursor}
cd /path/to/worktrees/{cursor}
claude
使い方
- 別のターミナルを開く
-
ccwtと入力してスニペットを展開 - タスク名(英語)を2箇所書き換える
- エンターで実行
# 展開後のイメージ(タスク名を書き換え)
cd /path/to/your/project && ./worktree-manager.sh create fix-payment-bug
cd /path/to/worktrees/fix-payment-bug
claude
これだけで、worktreeの作成からClaude Codeの起動まで一気に完了します。慣れると10秒くらいで並列作業を始められます。
片付け用スニペットも登録しておくと便利
cd /path/to/your/project && ./worktree-manager.sh remove {cursor}
| 項目 | 設定例 |
|---|---|
| Name | Claude Code Worktree Remove |
| Keyword |
ccwtr など任意 |
注意点とTips
worktreeは使い終わったら消す
放置すると地味に困ります。
- 同じブランチ名で新しいworktreeが作れない(1ブランチ1worktreeの制約)
-
git branch -dでブランチが消せない(worktreeで使用中と判定される)
PRのマージ後やレビュー待ちの段階で remove してしまってOKです。溜めると後で面倒なので、こまめに片付けるのがおすすめ。
.claude のシンボリックリンクに注意
スクリプトでは .claude ディレクトリをまるごとシンボリックリンクしていますが、Claude Codeは .claude/sessions/ 配下に会話履歴を保存します。ディレクトリごとリンクすると、異なるworktreeのセッション履歴が同じ場所に混在してしまう可能性があります。
対策としては:
-
設定ファイルだけリンクする:
.claude/settings.jsonなど必要なファイルだけ個別にリンク - 割り切って使う: 履歴が混ざっても実害がないなら気にしない(自分はこっち派)
# 設定ファイルだけ個別にリンクする場合の例
mkdir -p "$target_dir/.claude"
ln -s "$PROJECT_DIR/.claude/settings.json" "$target_dir/.claude/settings.json"
worktreeごとにセッションを明確に分けたい場合は、SYMLINK_ITEMS から .claude を外して、必要なファイルだけ個別にリンクするのが安全です。
環境ファイルに注意
worktree先は独立したファイルシステムなので、.env.local などのgit管理外のファイルは含まれません。ビルドやテストで必要になったらコピーしてください。
cp /path/to/original/.env.local /path/to/worktree/.env.local
node_modulesなどの依存パッケージ
worktree先では node_modules/ や vendor/ が空の状態です。Claude Codeにビルドやテストを頼む場合は、先に依存パッケージのインストールが必要になります。
Claude Codeの起動順序だけ気をつけて
worktreeの作成 → Claude Codeの起動 の順番を守ってください。Claude Codeは起動時のディレクトリを作業ディレクトリとして使うので、先にClaude Codeを起動してからworktreeを作っても、そのセッションは元のディレクトリで動き続けます。
まとめ
git worktree 自体はClaude Code専用の機能でもなんでもなく、Gitの標準機能です。今まで使っていなかったのがもったいなかったなと思います。Claude Codeに限らず、複数ブランチを同時に扱いたい場面でぜひ試してみてください。
Discussion