JJ + AI CLI 並行開発手法ガイドを考えてみた
なぜJujutsuなのか?
Git worktreeでも並行開発はできます。しかし、AIとの開発には決定的な違いがあります:
| 課題 | Git の場合 | Jujutsu の場合 |
|---|---|---|
| AI実験の失敗 |
git reset --hard で作業消失リスク |
jj op undo で瞬時に安全復旧 |
| 変更の記録 |
git add → git commit 手動作業 |
自動的に全変更が履歴に記録 |
| 実験ブランチ | ブランチ名を考える必要 | 名前なしで自然に変更を積み重ね |
| 複雑な履歴整理 |
git rebase -i で混乱 |
jj split jj squash で直感的 |
| 並行作業の競合 | マージ地獄のリスク | ロックフリーで安全に並行実行 |
つまり:AIとの実験的開発では「失敗を恐れない環境」が最重要。これがJujutsuの真価です。
🧠 Jujutsuの基本概念(Git経験者向け)
作業の流れの違い
Git の場合:
作業 → git add → git commit → push
↑ 手動でステージング ↑ 手動でコミット
Jujutsu の場合:
jj new → 作業 → 自動記録 → jj squash(必要時)
↑ 新作業開始 ↑ ファイル変更すると自動的に履歴に記録
核心的な違い
- Git: ファイル変更 → 手動でコミット作成
- Jujutsu: 常に「作業中のコミット」が存在し、変更は自動記録
📖 よく使うJujutsuコマンド早見表
| コマンド | 何をするか | Git相当 | 使う場面 |
|---|---|---|---|
jj new |
新しい作業を開始 | git checkout -b |
新機能開発、実験開始時 |
jj describe -m "メッセージ" |
現在の作業に説明をつける | git commit -m |
作業内容を記録したい時 |
jj log |
変更履歴を表示 | git log --graph |
進捗確認、履歴把握 |
jj status |
現在の状況を確認 | git status |
何が変更されたか確認 |
jj op undo |
直前の操作を取り消し | なし(Jujutsu独自) | 失敗を即座に元に戻す |
jj split |
1つの変更を2つに分割 |
git add --patch + commit |
AI生成コードを整理 |
jj squash |
複数の変更を1つにまとめる | git rebase -i squash |
完成した機能を統合 |
jj abandon |
変更を破棄する | git reset --hard |
失敗した実験を削除 |
🚀 Jujutsuによる革新的AI開発フロー
核心コンセプト:「失敗恐怖症の克服」
# Git: 実験が怖い(失敗したら面倒)
git checkout -b experimental-feature # ブランチ名を考える必要
# コード変更...
git add . # 手動でファイルを選択してステージング
git commit -m "実験..." # コミットメッセージを考えて手動コミット
# 失敗したら → git reset --hard で作業が完全消失
# Jujutsu: 実験が楽しい(失敗してもすぐ戻れる)
jj new -m "AI実験開始" # 新しい「作業スペース」を即座に作成
# コード変更 → 自動的に履歴に記録される(手動操作なし)
# 失敗したら → jj op undo で2秒で元の状態に戻る
🔍 何が起こっているか:
-
jj new: 「今から新しいことを始めます」とJujutsuに宣言 - 自動記録: ファイルを変更すると、Jujutsuが自動でスナップショットを作成
-
jj op undo: 「さっきの操作、なかったことにして」と時間を巻き戻し
🔬 実験駆動開発ワークフロー
1. 超高速プロトタイピング
# 現在の作業を「セーブポイント」として保存
jj new -m "AI提案: 新しいアーキテクチャ実験"
# 💡 これで「実験用の作業スペース」が作成される
# AI に複数の提案を同時実行させる
claude "このコードを3つの異なるアプローチで改善して"
# 💡 AIが大量のコードを生成 → 自動的にJujutsuが記録
# 結果を個別の「変更」に分割整理
jj split # diffエディタが開いて、分割する内容を編集できる
# 💡 右側のdiffを編集して「最初のコミットに含めたい部分」を残す
# 💡 エディタを閉じると、編集した内容→最初のコミット、残り→2番目のコミット
# 各アプローチを別々にテスト
jj new approach1 -m "アプローチ1のテスト" # approach1を起点に新作業開始
npm test # テスト実行
# 💡 テスト結果も自動的に履歴に記録される
jj new approach2 -m "アプローチ2のテスト" # approach2を起点に新作業開始
npm test
jj new approach3 -m "アプローチ3のテスト" # approach3を起点に新作業開始
npm test
# 最良のアプローチのみを採用
jj squash approach2 # approach2の内容をメインの履歴に統合
# 💡 「やっぱりアプローチ2が良かった」を1コマンドで反映
🎯 このワークフローの威力:
- 3つの実験を並行実行: Gitなら3つのブランチ作成+切り替えが必要
-
失敗コストゼロ: どの実験が失敗しても
jj op undoで瞬時復旧 - 手動作業なし: コミット作成、ファイル選択が全て自動
2. AIペアプログラミングでの瞬時フィードバック
# 新しい機能開発を開始
jj new -m "ユーザー認証機能開発開始"
# 💡 「認証機能専用の作業スペース」を作成
# 5分ごとにAIレビューを自動実行
while true; do
sleep 300 # 5分待機
jj new -m "5分経過 - AIレビュー要求" # 現在の進捗を「セーブ」
# 💡 5分間の作業内容が自動的に1つの「変更」として記録済み
claude "現在の変更をレビューして改善点を指摘"
# 💡 AIが現在のコードを見て改善提案
# AIの提案を即座に適用・テスト
if npm test; then # テストが通ったら
jj describe -m "AIレビュー反映 - テスト通過" # 成功をマーク
else # テストが失敗したら
jj op undo # 5分前の状態に瞬時に戻る
# 💡 失敗したAIの提案が完全に「なかったこと」になる
fi
done
🔍 何が素晴らしいか:
- 自動的な進捗セーブ: 5分間の作業が勝手に履歴に残る
- 安全な実験: AIの提案が失敗しても瞬時に元に戻る
-
手動操作ゼロ:
git addgit commitを考える必要なし
3. 複数AI順次実験と並行比較
# 共通の問題を設定
jj new -m "パフォーマンス問題: ダッシュボード読み込み遅延"
# 💡 「パフォーマンス改善プロジェクト」のベースを作成
# 複数のAIツールに順次依頼(実際は直列実行)
jj new -m "Claude提案" # 現在の状態から「Claude実験ブランチ」を作成
claude "ダッシュボードの読み込み速度を改善して"
# 💡 Claudeの改善案が自動記録される
jj new main -m "Aider提案" # 元の状態に戻って「Aider実験ブランチ」を作成
aider "ダッシュボードのパフォーマンス最適化"
# 💡 Aiderの改善案も別の履歴として記録
jj new main -m "手動実装" # エディターでの手動実装用
# Cursor、VS Code、その他のエディターで手動実装
# 💡 手動実装結果も自動的に履歴に記録
# 各提案の効果を客観的に測定(ここも順次実行)
jj new claude-solution -m "Claude解決案のベンチマーク"
npm run benchmark # パフォーマンス測定
# 💡 ベンチマーク結果も履歴に自動記録
jj new aider-solution -m "Aider解決案のベンチマーク"
npm run benchmark
jj new manual-solution -m "手動解決案のベンチマーク"
npm run benchmark
# 結果を視覚的に並行比較(ここが真の並行部分)
jj log --graph # 各実験の結果が樹形図で表示される
# 💡 「どの実験がいつ行われたか」が一目瞭然
# 最良の解決策を選択・統合
jj squash aider-solution -m "最良解決策: Aider提案を採用"
# 💡 「Aiderの提案が最も良かった」を1コマンドでメインに反映
🎯 この手法の革新性:
- 順次実験: 複数のAIツールに順番にタスクを依頼
- 並行比較: 全結果を同時に視覚化して客観的比較
- 簡単な選択: 最良の結果を1コマンドで採用
📝 実際に使用可能なCLI AIツール例:
-
Claude Code:
claude "プロンプト" -
Aider:
aider "プロンプト" -
GitHub Copilot CLI:
gh copilot suggest - 手動実装: CursorやVS Codeでエディター内AI機能を使用
📝 なぜ「順次」なのか:
- Claude Codeは一度に一つのセッションのみ
- 他のAIツールも基本的に順次利用
- 真の並行実行は複数ターミナル/開発者が必要
🚀 真の並行実験をするなら(注意:慎重な設計が必要):
⚠️ 重要な制限事項:
同じファイルへの同時編集は以下の問題を引き起こします:
- コンパイルエラー: 関数削除と呼び出し追加の競合
- テスト失敗: テストと実装の不整合
- Lintエラー: 異なるコーディングスタイルの競合
- 論理的矛盾: 技術的に統合できても動作しないコード
✅ 安全な並行実験の条件:
# 条件1: 異なるファイル/モジュールでの並行作業
# 開発者A: 認証機能(auth.js)
jj new main -m "Claude: 認証機能改善"
claude "src/auth.js のパフォーマンスを改善して"
# 開発者B: UI機能(dashboard.js)- 同時実行可能
jj new main -m "Aider: ダッシュボードUI改善"
aider "src/dashboard.js のレスポンシブ対応"
# 開発者C: テストファイル(tests/)- 同時実行可能
jj new main -m "手動: E2Eテスト追加"
# tests/ ディレクトリで新しいテストを手動作成
# 💡 異なるファイルなので安全に並行実行可能
🔍 並行実験結果の評価・選択プロセス:
ステップ1: 全実験結果の確認
# 全実験の状況を視覚的に確認
jj log --graph
# 💡 3つの並行実験ブランチが表示される
# 各実験の詳細確認
jj show claude-auth # Claude実験の内容確認
jj show aider-dashboard # Aider実験の内容確認
jj show manual-test # 手動実験の内容確認
# 各実験のテスト実行
jj new claude-auth -m "Claude実験のテスト"
npm test && npm run lint # 成功/失敗を記録
jj new aider-dashboard -m "Aider実験のテスト"
npm test && npm run lint
jj new manual-test -m "手動実験のテスト"
npm test && npm run lint
ステップ2: 採用・取り消しの決定パターン
🟢 パターン1: 全実験成功 → 最良を採用
# 最良の実験を選択(例:Claude実験が最高性能)
jj squash claude-auth -m "採用: Claude認証改善(性能+40%向上)"
# 他の成功実験も部分採用(必要に応じて)
jj squash aider-dashboard -m "採用: Aiderダッシュボード改善"
# 不要な実験を破棄
jj abandon manual-test
# 💡 手動実験が他より劣っていた場合の破棄
🟡 パターン2: 一部成功 → 成功分のみ採用
# 成功した実験のみ採用
jj squash claude-auth -m "採用: Claude認証改善(テスト通過)"
# 失敗した実験を破棄
jj abandon aider-dashboard # テスト失敗
jj abandon manual-test # Lintエラー
# 💡 失敗実験は履歴から除去されるが、必要時は復元可能
🔴 パターン3: 全実験失敗 → 全破棄して原点回帰
# 全実験を破棄
jj abandon claude-auth aider-dashboard manual-test
# または、実験開始前の状態に完全復帰
jj op log # 実験開始前のオペレーションIDを確認
jj op undo --to <実験開始前のoperation-id>
# 💡 「実験なんて最初からなかった」状態に戻る
🔵 パターン4: 部分統合 → 良い部分のみ抽出
# Claude実験から認証部分のみ抽出
jj new claude-auth -m "Claude実験から認証機能のみ抽出"
jj split src/auth.js # auth.jsの変更のみを分離
jj describe -m "採用: Claude認証改善(抽出版)"
# Aider実験からCSS部分のみ抽出
jj new aider-dashboard -m "AiderからCSS改善のみ抽出"
jj split src/styles/ # スタイル変更のみ分離
jj describe -m "採用: Aiderスタイル改善(抽出版)"
# 元の実験コミットは破棄
jj abandon claude-auth aider-dashboard manual-test
🔄 安全な取り消し・ロールバック手順
# レベル1: 個別実験の取り消し
jj abandon <実験コミット> # 特定実験のみ削除
# レベル2: 複数実験の一括取り消し
jj abandon experiment1 experiment2 experiment3
# レベル3: 時点指定での完全ロールバック
jj op log # 作業履歴を確認
jj op undo --to <安全な時点のID> # 指定時点まで巻き戻し
# レベル4: 緊急時の最終手段
jj git init --colocated # 最悪の場合、Jujutsuを再初期化
# ⚠️ これは全Jujutsu履歴を失うので最終手段
📊 採用基準の例
# 性能基準での評価
npm run benchmark # 各実験でベンチマーク実行
# Claude: 40%改善 → 採用
# Aider: 10%改善 → 条件付き採用
# 手動: 5%低下 → 破棄
# 品質基準での評価
npm test && npm run lint && npm run type-check
# 全てパス → 採用候補
# 一部失敗 → 修正または破棄
# 全て失敗 → 即座に破棄
✅ より現実的な並行パターン:
# パターン1: 機能別分担
# 開発者A: バックエンドAPI
# 開発者B: フロントエンドUI
# 開発者C: テスト&ドキュメント
# パターン2: 段階別分担
# 開発者A: プロトタイプ作成
# 開発者B: プロトタイプのリファクタリング(Aの完了後)
# 開発者C: プロトタイプのテスト追加(Bの完了後)
🔍 競合が発生した場合の対処:
# 競合検出
jj status # 競合状況を確認
jj log --conflicts # 競合の詳細を表示
# 競合解決
jj resolve # diffエディターで手動解決
# ↓ 解決後にビルド・テスト確認が必須
npm run build && npm test && npm run lint
# 解決不可能な場合
jj op undo # 競合前の状態に戻る
# 再度、異なるアプローチで並行実験を設計
🔍 現実的な並行実験の利点:
- 時間短縮: 異なる領域での同時作業(ファイル競合回避時のみ)
- 安全性: Jujutsuが技術的競合を自動検出(ただし論理的競合は要手動解決)
- 完全な記録: 並行作業も含めて全履歴を保持
- 段階的統合: 問題のある実験のみを破棄可能
💡 推奨される並行開発パターン:
- 小規模チーム: 機能別ファイル分担で並行実験
- 個人開発: 順次実験 + 結果の並行比較(元の手法)
- 大規模プロジェクト: モジュール別分担でリスク最小化
📋 並行実験前のチェックリスト:
- 編集対象ファイルが重複していないか
- 依存関係のあるコード変更ではないか
- ビルド・テスト環境が独立しているか
- 競合解決の責任者が決まっているか
🛡️ リスクゼロの大胆実験
4. 破壊的変更の安全実行
# 現在の状態を「復旧ポイント」として保護
jj new -m "破壊的リファクタリング実験"
# 💡 何があっても元に戻れる「安全な実験環境」を作成
# AIに大胆な変更を依頼
claude "このコードベース全体をTypeScriptに移行して。既存機能は全て保持"
# 💡 AIが大量のファイルを一気に変更 → 全て自動記録
# 移行の各段階を安全にチェック
jj new -m "TypeScript移行 - ビルド確認" # 移行結果を「セーブ」してからテスト
npm run build || jj op undo # ビルド失敗なら即座に移行前に戻る
# 💡 失敗したら「移行なんて最初からなかった」状態に戻る
jj new -m "TypeScript移行 - テスト確認" # ビルド成功なら次の段階
npm test || jj op undo # テスト失敗なら移行前に戻る
jj new -m "TypeScript移行 - 型チェック" # テスト成功なら型チェック
npx tsc --noEmit || jj op undo # 型エラーがあれば移行前に戻る
# 全段階成功なら統合
jj squash -m "TypeScript移行完了"
# 💡 「段階的な確認」を「1つの完成した移行」としてまとめる
# もし後で問題が発見されても...
jj op log # 全ての操作履歴を表示
# 💡 「いつ何をしたか」の完全な記録が残っている
jj op undo --to <移行前のoperation-id> # 特定の時点まで完全復旧
# 💡 「移行作業を全部なかったことにする」ワンコマンド復旧
🔍 安全性の仕組み:
- 段階的確認: 各チェックポイントで状態を保存
- 瞬時復旧: 失敗したら即座に前の状態に戻る
- 完全な履歴: いつでも任意の時点に戻れる
Git との恐ろしい対比
# Git版(高リスク・恐怖のリファクタリング)
git checkout -b typescript-migration # ブランチ作成
# 大量の変更をAIが実行...
git add . && git commit -m "TypeScript migration" # 全変更を1回でコミット
# 💀 問題発覚時の絶望:
git reset --hard HEAD~1 # 数時間の作業が完全消失
# または
git checkout main && git branch -D typescript-migration # ブランチごと削除
# 復旧不可能:細かい中間状態は記録されていない
📊 従来手法との具体的比較
シナリオ: 新機能開発での10回の実験
| 操作 | Git所要時間 | Jujutsu所要時間 | 何をしているか |
|---|---|---|---|
| ブランチ作成 | 10 × 10秒 = 100秒 | 0秒(不要) | 実験用環境の準備 |
| 変更のコミット | 10 × 30秒 = 300秒 | 0秒(自動) | 作業内容の記録 |
| 失敗時のリセット | 3 × 60秒 = 180秒 | 3 × 2秒 = 6秒 | 失敗実験の取り消し |
| ブランチ切り替え | 20 × 5秒 = 100秒 | 0秒(不要) | 実験間の移動 |
| 履歴の整理 | 120秒 | 20秒 | 完成版の作成 |
| 合計 | 700秒 | 26秒 |
結果:Jujutsuは96%の時間短縮を実現
🚀 今すぐ始める実践ガイド
最小構成(1分でスタート)
# 既存プロジェクトでJujutsuを有効化
cd existing-project
jj git init --colocated # GitとJujutsuを同時に使える設定
# 💡 既存のGitリポジトリにJujutsuを「追加」(Gitは残る)
# AI実験用の基本設定
jj config set --user ui.default-description "AI実験" # デフォルトのコミットメッセージ
jj config set --repo ui.auto-push false # 自動プッシュを無効化(実験中は手動管理)
# または設定ファイルを直接編集
jj config edit --user # ユーザー設定ファイルを開く
jj config edit --repo # リポジトリ固有の設定ファイルを開く
# 最初のAI実験を開始
jj new -m "Jujutsu + AI開発スタート" # 新しい作業開始
claude "今からJujutsuでAI並行開発を始めます。最初の実験として、このコードベースの改善点を提案してください"
# 💡 この時点で、AIとの会話もコード変更も全て自動記録される
実践的な1日のワークフロー
# 朝: 昨日の作業状況を確認
jj log --limit 5 # 昨日の作業履歴を表示
# 💡 「昨日何をしていたか」が一目瞭然
jj new main -m "新しい一日の開始" # 今日の作業用スペースを作成
# 💡 昨日の状態を保持しつつ、今日の新しい実験環境を準備
# 午前: 探索的開発(失敗を恐れない実験)
claude "このプロジェクトで最も改善すべき部分を特定して"
# AIの提案を次々と試す(すべて自動記録、失敗しても瞬時復旧)
# 午後: 有望なアイデアの深掘り
jj log --template 'description' | grep "有望" # 午前の実験で有望だった内容を検索
jj new <有望なコミット> -m "深掘り開発開始" # 有望な実験を起点に新しい開発開始
# 💡 「あの実験、もう少し深掘りしてみよう」を簡単に実現
# 夕方: 成果の統合と整理
jj squash -m "今日の成果統合" # 1日の実験結果をまとめて1つの「完成品」に
jj op log # 一日の全作業履歴を確認
# 💡 「今日1日で何を達成したか」の完全な記録
🎯 Jujutsu特有の高度技法
時間旅行デバッグ
# バグが発生したタイミングを特定
jj op log | claude "このoperationログからバグ混入タイミングを特定して"
# 💡 AIが作業履歴を分析して「この時点でバグが入った」を特定
# 特定の時点での状況を「時間旅行」して確認
jj --at-operation=<bug-free-operation> status # バグがなかった時点の状態
jj --at-operation=<bug-introduced-operation> status # バグが入った時点の状態
# 💡 「タイムマシンで過去に戻って状況確認」が可能
# バグ修正を「過去の時点」に適用
jj --at-operation=<target-operation> new -m "バグ修正"
# 💡 「過去に戻ってバグを修正し、その修正を現在に持ってくる」
AIによる履歴最適化
# AIに履歴整理を依頼
jj log --graph | claude "この履歴を最適化するためのsquash計画を立てて"
# 💡 複雑になった実験履歴を「AI コンサルタント」に整理してもらう
# 提案された計画を実行
# (AI提案: 「実験A、B、Cをまとめて、実験Dは削除、実験Eは独立させる」)
jj squash experimentA experimentB experimentC -m "統合実験結果"
jj abandon experimentD # 失敗実験を削除
# 💡 AIの提案に従って、履歴を「物語として読みやすく」整理
💡 まとめ:なぜJujutsuが必要なのか
AI開発の本質は「高速な試行錯誤」
問題: AIは素早くコードを生成するが、人間の「慎重なGitワークフロー」がボトルネックになる
解決: Jujutsuの「恐れない実験環境」でAIのペースに合わせる
具体的な違い
Git の現実:
AIが提案 → ブランチ名考える → git checkout -b → git add → git commit
→ テスト失敗 → git reset --hard → また最初から...
(心理的ハードル:「失敗したら面倒」)
Jujutsu の世界:
AIが提案 → jj new → 自動記録 → テスト失敗 → jj op undo → 即座に次の実験
(心理状態:「失敗しても2秒で戻れるから大胆に行こう」)
結論
AIとペアで開発するなら、AIのペースに合わせたツールが必要。
それがJujutsu—「失敗を恐れない開発環境」です。
📚 次のステップ
-
今すぐ試す: 既存プロジェクトで
jj git init --colocated -
小さな実験: AIに簡単な改善を依頼して
jj op undoの威力を体感 - 大胆な実験: 破壊的変更をAIに依頼して安全性を確認
- ワークフロー確立: 自分なりの「AI+Jujutsu」パターンを発見
覚えておくべき魔法のコマンド:
-
jj new -m "実験開始"- 新しい実験スペース作成 -
jj op undo- 失敗を2秒で取り消し -
jj log --graph- 実験履歴を視覚的に確認 -
jj squash- 成功した実験をまとめて完成品に
この4つだけで、AI開発の世界が変わります。
Discussion