🙆‍♀️

JJ + AI CLI 並行開発手法ガイドを考えてみた

に公開

なぜJujutsuなのか?

Git worktreeでも並行開発はできます。しかし、AIとの開発には決定的な違いがあります:

課題 Git の場合 Jujutsu の場合
AI実験の失敗 git reset --hard で作業消失リスク jj op undo で瞬時に安全復旧
変更の記録 git addgit 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 add git 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—「失敗を恐れない開発環境」です。


📚 次のステップ

  1. 今すぐ試す: 既存プロジェクトで jj git init --colocated
  2. 小さな実験: AIに簡単な改善を依頼して jj op undo の威力を体感
  3. 大胆な実験: 破壊的変更をAIに依頼して安全性を確認
  4. ワークフロー確立: 自分なりの「AI+Jujutsu」パターンを発見

覚えておくべき魔法のコマンド:

  • jj new -m "実験開始" - 新しい実験スペース作成
  • jj op undo - 失敗を2秒で取り消し
  • jj log --graph - 実験履歴を視覚的に確認
  • jj squash - 成功した実験をまとめて完成品に

この4つだけで、AI開発の世界が変わります。

Discussion