Note : このIssueは 2026-04-14 にStage 3(影響範囲)レビュー結果を反映して更新されました。
詳細: dev-reports/issue/649/issue-review/
概要
Home 画面にアシスタントチャット UI を追加し、特定の worktree に紐づかない汎用的な CLI セッション(インストール済みの全CLIツール)を利用可能にする。登録済みリポジトリの中から作業ディレクトリを選択し、リポジトリ横断の開発指示を行える。
デフォルトで CommandMate CLI の使い方と登録済みリポジトリの情報をコンテキストとして付与する。
背景・課題
現在の CLI セッションはすべて worktree 単位で紐づいており、複数 worktree にまたがる操作(一括指示・状況確認・リポジトリ横断の質問)を行う場所がない
commandmatedev CLI の使い方を対話的に聞ける窓口がなく、ドキュメントを別途参照する必要がある
リポジトリ全体の俯瞰的な開発相談(設計判断・Issue 整理等)を行うための汎用的なセッションが存在しない
提案する解決策
1. グローバルセッション概念の追加
worktree に紐づかない「グローバルセッション」を新設する:
tmux セッション名 : mcbd-{cli_tool_id}-__global__ 形式(例: mcbd-claude-__global__, mcbd-codex-__global__)
既存の BaseCLITool.getSessionName(worktreeId) をそのまま再利用し、worktreeId に __global__ を渡す
getSessionName('__global__') は mcbd-{tool}-__global__ を返す(既存コードの変更不要)
CLIツール毎に独立したセッションを持つ(CLIツール切替時に既存セッションを破棄する必要がない)
cli-tools/validation.ts の SESSION_NAME_PATTERN は mcbd-claude-__global__ を許容済み(確認済み)
security/path-validator.ts の WORKTREE_ID_PATTERN も __global__ を許容(アンダースコア許可、確認済み)
作業ディレクトリ : 登録リポジトリの一覧から選択(ドロップダウン)
セッション実行中にリポジトリを変更した場合は確認ダイアログを表示し、既存セッションを停止して再作成する
CLI ツール : CLIToolManager.getInstalledTools() で取得したインストール済みツール全種を選択肢として表示する(claude / codex / gemini / vibe-local / opencode / copilot)
既存の CLI_TOOL_IDS 定数(src/lib/cli-tools/types.ts)の全6種類と整合
2. Home 画面への埋め込み
現在の Home 画面(セッションサマリー + ショートカットカード)の上部にチャット UI を配置:
グローバルセッション専用の簡略版コンポーネント AssistantMessageInput を新規作成する
既存の MessageInput は worktreeId を必須Propsとして受け取り、内部で worktreeApi.sendMessage() / useSlashCommands() / useImageAttachment() / InterruptButton 等が全て worktreeId に依存しているため、そのまま拡張すると50箇所以上の影響がある
AssistantMessageInput はメッセージ送信のみに特化し、スラッシュコマンド・画像添付・割り込みボタン等のworktree固有機能は含めない
グローバルセッション用APIルート(/api/assistant/*)を直接呼び出す設計とする
リポジトリ選択ドロップダウン + CLI ツール選択
ターミナル出力表示 : 既存の capturePane API と同等のキャプチャ機構を利用してリアルタイム表示する
レイアウト考慮 :
チャットUI部分は折りたたみ可能(Collapse/Expand)とし、非アクティブ時は最小化表示にする
高さは最大 50vh を上限とし、スクロール可能にする
モバイルレイアウトではタブ切替方式(チャット / セッションサマリー)で表示する
3. チャット履歴の保存方針
セッション内のみ(Phase 1) : ターミナル出力のキャプチャ(capturePane)のみで表示し、DBマイグレーションは不要とする。
tmuxセッション終了時に履歴は失われる
Phase 1 では DB 操作を一切行わない : chat-db.ts の createMessage() や session-db.ts の updateSessionState() は呼び出さない
chat_messages テーブルの FOREIGN KEY (worktree_id) REFERENCES worktrees(id) ON DELETE CASCADE 制約により、__global__ での INSERT は失敗する(init-db.ts:46)
session_states テーブルも同様の FOREIGN KEY 制約を持つ(init-db.ts:79-88)
DBスキーマ変更(chat_messages.worktree_id の NOT NULL 制約変更等)を回避し、影響範囲を最小化する
DB保存が必要になった場合は follow-up Issue で対応する(仮想worktreeレコード挿入方式 or FOREIGN KEY 制約の見直しを検討)
Phase 1 では会話ログファイル出力もスコープ外 : conversation-logger.ts の recordClaudeConversation() は worktreeId で DB 問合せするため、DB 非保存方針では常に null を返しログが記録されない
4. レスポンスポーリング設計
グローバルセッション専用のポーリング関数を新規実装する(既存 response-checker.ts の再利用を廃止) :
既存の response-checker.ts の checkForResponse() は冒頭で getWorktreeById(db, worktreeId) を呼び出し、結果が null の場合に stopPolling() して return する(response-checker.ts:408-415)。仮想 worktreeID __global__ は worktrees テーブルに存在しないため、ポーリング開始直後に停止される
対応方針 : グローバルセッション専用のポーリング関数 pollGlobalSession(cliToolId) を新規作成する
DB チェック(getWorktreeById)をスキップ
DB 保存(createMessage, updateSessionState)をスキップ
tmux キャプチャ出力のみを返す軽量なポーリングループ
activePollers Map のキーには __global__:{cliToolId} を使用して既存ポーラーとの重複を防止
startPolling('__global__', cliToolId) / stopPolling('__global__', cliToolId) は使用しない(既存関数内部の DB 依存ロジックとの衝突を回避)
5. デフォルトコンテキスト
セッション開始時に以下をコンテキストとして付与する:
CommandMate CLI コマンド一覧・使い方
登録済みリポジトリ一覧(名前・パス・別名・worktree 数)
現在アクティブな worktree セッションのステータス(セッション開始時のスナップショット。都度更新はしない)
CLIツール毎のコンテキスト付与方式 :
CLIツール
付与方法
Claude Code
CLAUDE.md 自動読み込み(CLI 標準動作) + 初回メッセージにリポジトリ情報付与
Codex
--system-prompt 引数でコンテキスト全体を渡す
Gemini
初回メッセージとしてコンテキスト情報を送信
Copilot
初回メッセージとしてコンテキスト情報を送信
OpenCode
初回メッセージとしてコンテキスト情報を送信
Vibe Local
初回メッセージとしてコンテキスト情報を送信
6. セッションのライフサイクル管理
セッション停止 : UI 上にセッション停止ボタンを配置し、ユーザーが明示的に停止できるようにする
サーバー再起動時 : session-cleanup.ts に cleanupGlobalSessions() 関数を新規追加し、以下を行う:
mcbd-{cli_tool_id}-__global__ パターン(全 CLI_TOOL_IDS をループ)の孤立 tmux セッションを検出・停止
syncWorktreesAndCleanup() から呼び出す(DB ベースの削除 ID ループとは別の独立した処理として実装)
サーバー起動時にも既存グローバルセッションを検出してクリーンアップ
ページ遷移時 : グローバルセッションは維持する(Home画面に戻った際にセッション状態を復元表示する)
CLIツール切替時 : 各CLIツールが独立セッションを持つため、切替時に既存セッションの停止は不要。ただし前のツールのセッションが残り続けるため、UIに「全セッション停止」ボタンも提供する
サイドバー表示の除外 : worktree-status-helper.ts の detectWorktreeSessionStatus() でグローバルセッション(__global__)をサイドバーの worktree 一覧から除外するフィルタを追加する。worktrees API のレスポンスにグローバルセッションが含まれないようにする
7. API 追加
POST /api/assistant/start — グローバルセッション開始(ディレクトリ・CLI ツール指定)
POST /api/assistant/terminal — グローバルセッションへのメッセージ送信
GET /api/assistant/current-output — グローバルセッションの出力取得
DELETE /api/assistant/session — グローバルセッション停止
認証 : /api/assistant/* は middleware.ts の認証マッチャーで自動的にカバーされる(AUTH_EXCLUDED_PATHS に追加しないこと)。実装時に認証テストを追加して確認する
8. スコープ定義(Phase 1)
Phase 1 では基本的なメッセージ送受信のみをサポートする。以下の高度な機能はスコープ外とし、必要に応じて follow-up Issue で対応する:
Auto-Yes 機能のグローバルセッション対応
スケジューラー連携
CLI コマンド(commandmate ls, send, wait 等)からのグローバルセッション操作
チャット履歴の DB 永続化
スラッシュコマンド / 画像添付
会話ログファイル出力(conversation-logger.ts)
Phase 1 スコープ外機能一覧
機能
スコープ外理由
Phase 2 引き継ぎ要否
Auto-Yes
auto-yes-manager.ts の Map キーが worktreeId 依存。resource-cleanup.ts の cleanupOrphanedMapEntries() が __global__ を孤立と判定して削除する
要: cleanupOrphanedMapEntries() に予約 ID スキップロジック追加
スケジューラー連携
schedule-manager.ts が worktree 単位のジョブ管理。グローバルセッション用のジョブ定義が未設計
要: グローバルセッション用スケジュール設計
CLI コマンド統合
commandmate ls/send/wait 等が worktreeId を必須引数として受け取る設計
要: --global フラグ追加等の設計
DB 永続化
chat_messages / session_states の FOREIGN KEY 制約が __global__ を拒否
要: 仮想レコード挿入 or FK 制約見直し
スラッシュコマンド
useSlashCommands() が worktreeId ベースのコマンドファイル探索
要: グローバルスコープのコマンド探索設計
画像添付
useImageAttachment() が worktreeId ベースのアップロード先管理
要: グローバルセッション用アップロードパス設計
会話ログ出力
conversation-logger.ts が worktreeId で DB 問合せ。DB 非保存方針では機能しない
要: DB 保存対応後に連携
resource-cleanup.ts 予約ID対応
cleanupOrphanedMapEntries() が __global__ エントリを孤立判定
要: 予約 ID スキップロジック追加
実装タスク
受入条件
影響範囲
変更対象ファイル(想定)
ファイル
変更内容
src/app/page.tsx
アシスタントチャット UI の組み込み
src/app/api/assistant/ (新規)
グローバルセッション用 API ルート(start, terminal, current-output, session)。DB 操作は行わない
src/lib/session/
グローバルセッション管理ロジック追加
src/lib/polling/ (新規)
グローバルセッション専用ポーリング関数 pollGlobalSession()
src/lib/session-cleanup.ts
cleanupGlobalSessions() 関数追加(mcbd-{cli_tool_id}-__global__ パターン対応)
src/lib/session/worktree-status-helper.ts
グローバルセッション除外フィルタ追加
src/lib/tmux/tmux.ts
グローバルセッション用の tmux 操作対応
src/components/home/ (新規)
AssistantMessageInput, AssistantChatPanel 等のコンポーネント
src/middleware.ts
/api/assistant/* への認証ミドルウェア適用確認(変更不要、テストのみ)
影響を受けるが変更しないファイル(Phase 1)
ファイル
影響内容
対応方針
src/lib/polling/response-checker.ts
checkForResponse() の getWorktreeById() が __global__ で null を返す
専用ポーリング関数で回避(既存コード変更なし)
src/lib/db/chat-db.ts
createMessage() の FOREIGN KEY 制約
Phase 1 では呼び出さない
src/lib/db/session-db.ts
updateSessionState() の FOREIGN KEY 制約
Phase 1 では呼び出さない
src/lib/conversation-logger.ts
recordClaudeConversation() が null を返す
Phase 1 ではスコープ外
src/lib/resource-cleanup.ts
cleanupOrphanedMapEntries() が __global__ を孤立判定
Phase 2 で予約 ID スキップ対応
関連コンポーネント
MessageInput — メッセージ入力 UI(参考設計。直接流用ではなく AssistantMessageInput を新規作成)
CLIToolManager — CLI ツール管理(getInstalledTools() でインストール済みツール一覧取得)
HomeSessionSummary — 既存 Home コンポーネント(レイアウト調整、モバイル時タブ切替対応)
repositoryApi.list() — リポジトリ一覧取得(Issue feat(repositories): リポジトリ一覧表示と別名編集UI #644 で追加済み)
session-cleanup.ts — セッションクリーンアップ(cleanupGlobalSessions() 新規追加)
BaseCLITool.getSessionName() — セッション名生成(__global__ を引数として既存関数を再利用)
レビュー履歴
Stage 1 (2026-04-14)
S1-001: CLIツール選択範囲をインストール済み全ツール(6種)に拡張
S1-002: MessageInput拡張方針を明確化(グローバルセッション専用 AssistantMessageInput 新規作成)
S1-003: レスポンスポーリング設計方針追記(仮想worktreeID __global__ 使用)
S1-004: セッションのライフサイクル管理追記(停止UI、クリーンアップ、ページ遷移時の方針)
S1-005: tmuxセッション名を mcbd-global-{cli_tool_id} 形式に変更(CLIツール毎に独立セッション)
S1-006: チャット履歴保存方針をセッション内のみ(Phase 1)に確定
S1-007: デフォルトコンテキスト付与方法をCLIツール毎に具体化
S1-008: 作業ディレクトリ変更時の処理方針追記(確認ダイアログ + セッション再作成)
S1-009: 受入条件にターミナル出力表示の検証項目追加
S1-010: セッション停止API(DELETE /api/assistant/session)追加
S1-011: Home画面レイアウト変更への配慮追記(折りたたみ、高さ上限、モバイル対応)
Stage 3 - 影響範囲レビュー (2026-04-14)
S3-MF-001: ポーリング設計を「専用関数方式」に変更(response-checker.ts の getWorktreeById() チェック回避)
S3-MF-002: Phase 1 で DB 操作を一切行わないことを明記(FOREIGN KEY 制約対策)
S3-MF-003: cleanupGlobalSessions() 関数の実装タスク追加(tmux セッションリーク防止)
S3-SF-001: Phase 1 で会話ログファイル出力がスコープ外であることを明記
S3-SF-002: resource-cleanup.ts の予約 ID スキップ対応を Phase 2 タスクとして明記
S3-SF-003: セッション命名を mcbd-{cli_tool_id}-__global__ に統一(既存 getSessionName() 再利用)
S3-SF-004: 回帰テスト・グローバルセッション用テストのタスクを詳細化
S3-SF-005: サイドバーからグローバルセッションを除外するフィルタ実装タスク追加
S3-SF-006: /api/assistant/* の認証テスト追加を実装タスクに明記
S3-SF-007: session_states の FOREIGN KEY 制約対策を S3-MF-002 に統合
S3-NTH-001: CLAUDE.md モジュール一覧更新タスク追加
S3-NTH-002: Phase 1 スコープ外機能一覧テーブル追加
概要
Home 画面にアシスタントチャット UI を追加し、特定の worktree に紐づかない汎用的な CLI セッション(インストール済みの全CLIツール)を利用可能にする。登録済みリポジトリの中から作業ディレクトリを選択し、リポジトリ横断の開発指示を行える。
デフォルトで CommandMate CLI の使い方と登録済みリポジトリの情報をコンテキストとして付与する。
背景・課題
提案する解決策
1. グローバルセッション概念の追加
worktree に紐づかない「グローバルセッション」を新設する:
mcbd-{cli_tool_id}-__global__形式(例:mcbd-claude-__global__,mcbd-codex-__global__)BaseCLITool.getSessionName(worktreeId)をそのまま再利用し、worktreeIdに__global__を渡すgetSessionName('__global__')はmcbd-{tool}-__global__を返す(既存コードの変更不要)cli-tools/validation.tsのSESSION_NAME_PATTERNはmcbd-claude-__global__を許容済み(確認済み)security/path-validator.tsのWORKTREE_ID_PATTERNも__global__を許容(アンダースコア許可、確認済み)CLIToolManager.getInstalledTools()で取得したインストール済みツール全種を選択肢として表示する(claude / codex / gemini / vibe-local / opencode / copilot)CLI_TOOL_IDS定数(src/lib/cli-tools/types.ts)の全6種類と整合2. Home 画面への埋め込み
現在の Home 画面(セッションサマリー + ショートカットカード)の上部にチャット UI を配置:
AssistantMessageInputを新規作成するMessageInputはworktreeIdを必須Propsとして受け取り、内部でworktreeApi.sendMessage()/useSlashCommands()/useImageAttachment()/InterruptButton等が全てworktreeIdに依存しているため、そのまま拡張すると50箇所以上の影響があるAssistantMessageInputはメッセージ送信のみに特化し、スラッシュコマンド・画像添付・割り込みボタン等のworktree固有機能は含めない/api/assistant/*)を直接呼び出す設計とするcapturePaneAPI と同等のキャプチャ機構を利用してリアルタイム表示する3. チャット履歴の保存方針
セッション内のみ(Phase 1): ターミナル出力のキャプチャ(
capturePane)のみで表示し、DBマイグレーションは不要とする。chat-db.tsのcreateMessage()やsession-db.tsのupdateSessionState()は呼び出さないchat_messagesテーブルのFOREIGN KEY (worktree_id) REFERENCES worktrees(id) ON DELETE CASCADE制約により、__global__での INSERT は失敗する(init-db.ts:46)session_statesテーブルも同様の FOREIGN KEY 制約を持つ(init-db.ts:79-88)chat_messages.worktree_idの NOT NULL 制約変更等)を回避し、影響範囲を最小化するconversation-logger.tsのrecordClaudeConversation()はworktreeIdで DB 問合せするため、DB 非保存方針では常に null を返しログが記録されない4. レスポンスポーリング設計
グローバルセッション専用のポーリング関数を新規実装する(既存
response-checker.tsの再利用を廃止):response-checker.tsのcheckForResponse()は冒頭でgetWorktreeById(db, worktreeId)を呼び出し、結果が null の場合にstopPolling()して return する(response-checker.ts:408-415)。仮想 worktreeID__global__はworktreesテーブルに存在しないため、ポーリング開始直後に停止されるpollGlobalSession(cliToolId)を新規作成するgetWorktreeById)をスキップcreateMessage,updateSessionState)をスキップactivePollersMap のキーには__global__:{cliToolId}を使用して既存ポーラーとの重複を防止startPolling('__global__', cliToolId)/stopPolling('__global__', cliToolId)は使用しない(既存関数内部の DB 依存ロジックとの衝突を回避)5. デフォルトコンテキスト
セッション開始時に以下をコンテキストとして付与する:
CLIツール毎のコンテキスト付与方式:
--system-prompt引数でコンテキスト全体を渡す6. セッションのライフサイクル管理
session-cleanup.tsにcleanupGlobalSessions()関数を新規追加し、以下を行う:mcbd-{cli_tool_id}-__global__パターン(全CLI_TOOL_IDSをループ)の孤立 tmux セッションを検出・停止syncWorktreesAndCleanup()から呼び出す(DB ベースの削除 ID ループとは別の独立した処理として実装)worktree-status-helper.tsのdetectWorktreeSessionStatus()でグローバルセッション(__global__)をサイドバーの worktree 一覧から除外するフィルタを追加する。worktrees API のレスポンスにグローバルセッションが含まれないようにする7. API 追加
POST /api/assistant/start— グローバルセッション開始(ディレクトリ・CLI ツール指定)POST /api/assistant/terminal— グローバルセッションへのメッセージ送信GET /api/assistant/current-output— グローバルセッションの出力取得DELETE /api/assistant/session— グローバルセッション停止/api/assistant/*はmiddleware.tsの認証マッチャーで自動的にカバーされる(AUTH_EXCLUDED_PATHSに追加しないこと)。実装時に認証テストを追加して確認する8. スコープ定義(Phase 1)
Phase 1 では基本的なメッセージ送受信のみをサポートする。以下の高度な機能はスコープ外とし、必要に応じて follow-up Issue で対応する:
commandmate ls,send,wait等)からのグローバルセッション操作conversation-logger.ts)Phase 1 スコープ外機能一覧
auto-yes-manager.tsの Map キーが worktreeId 依存。resource-cleanup.tsのcleanupOrphanedMapEntries()が__global__を孤立と判定して削除するcleanupOrphanedMapEntries()に予約 ID スキップロジック追加schedule-manager.tsが worktree 単位のジョブ管理。グローバルセッション用のジョブ定義が未設計commandmate ls/send/wait等が worktreeId を必須引数として受け取る設計--globalフラグ追加等の設計chat_messages/session_statesの FOREIGN KEY 制約が__global__を拒否useSlashCommands()が worktreeId ベースのコマンドファイル探索useImageAttachment()が worktreeId ベースのアップロード先管理conversation-logger.tsが worktreeId で DB 問合せ。DB 非保存方針では機能しないresource-cleanup.ts予約ID対応cleanupOrphanedMapEntries()が__global__エントリを孤立判定実装タスク
mcbd-{cli_tool_id}-__global__形式(既存のgetSessionName('__global__')を再利用)POST/GET/DELETE /api/assistant/*API ルート追加(start, terminal, current-output, session)createMessage,updateSessionState)は一切行わない/api/assistant/*への認証ミドルウェア適用確認テスト追加AUTH_EXCLUDED_PATHSに/api/assistantを追加しないことを確認するテストAssistantMessageInput新規作成)CLIToolManager.getInstalledTools()を使用)pollGlobalSession(cliToolId)の新規実装getWorktreeById)をスキップcreateMessage,updateSessionState)をスキップsession-cleanup.tsへのcleanupGlobalSessions()関数追加CLI_TOOL_IDSをループしてmcbd-{cli_tool_id}-__global__パターンのセッションを検出・停止syncWorktreesAndCleanup()から呼び出しworktree-status-helper.tsにグローバルセッション除外フィルタ追加detectWorktreeSessionStatus()で__global__セッションをサイドバー表示から除外session-cleanupテストの回帰確認pollGlobalSessionの正常系・異常系テスト/api/assistant/*の認証テスト受入条件
mcbd-{cli_tool_id}-__global__セッションがクリーンアップされる/api/assistant/*が認証ミドルウェアで保護されているnpm run lint/npx tsc --noEmit/npm run test:unitがパスする影響範囲
変更対象ファイル(想定)
src/app/page.tsxsrc/app/api/assistant/(新規)src/lib/session/src/lib/polling/(新規)pollGlobalSession()src/lib/session-cleanup.tscleanupGlobalSessions()関数追加(mcbd-{cli_tool_id}-__global__パターン対応)src/lib/session/worktree-status-helper.tssrc/lib/tmux/tmux.tssrc/components/home/(新規)AssistantMessageInput,AssistantChatPanel等のコンポーネントsrc/middleware.ts/api/assistant/*への認証ミドルウェア適用確認(変更不要、テストのみ)影響を受けるが変更しないファイル(Phase 1)
src/lib/polling/response-checker.tscheckForResponse()のgetWorktreeById()が__global__で null を返すsrc/lib/db/chat-db.tscreateMessage()の FOREIGN KEY 制約src/lib/db/session-db.tsupdateSessionState()の FOREIGN KEY 制約src/lib/conversation-logger.tsrecordClaudeConversation()が null を返すsrc/lib/resource-cleanup.tscleanupOrphanedMapEntries()が__global__を孤立判定関連コンポーネント
MessageInput— メッセージ入力 UI(参考設計。直接流用ではなくAssistantMessageInputを新規作成)CLIToolManager— CLI ツール管理(getInstalledTools()でインストール済みツール一覧取得)HomeSessionSummary— 既存 Home コンポーネント(レイアウト調整、モバイル時タブ切替対応)repositoryApi.list()— リポジトリ一覧取得(Issue feat(repositories): リポジトリ一覧表示と別名編集UI #644 で追加済み)session-cleanup.ts— セッションクリーンアップ(cleanupGlobalSessions()新規追加)BaseCLITool.getSessionName()— セッション名生成(__global__を引数として既存関数を再利用)レビュー履歴
Stage 1 (2026-04-14)
AssistantMessageInput新規作成)__global__使用)mcbd-global-{cli_tool_id}形式に変更(CLIツール毎に独立セッション)Stage 3 - 影響範囲レビュー (2026-04-14)
response-checker.tsのgetWorktreeById()チェック回避)cleanupGlobalSessions()関数の実装タスク追加(tmux セッションリーク防止)resource-cleanup.tsの予約 ID スキップ対応を Phase 2 タスクとして明記mcbd-{cli_tool_id}-__global__に統一(既存getSessionName()再利用)/api/assistant/*の認証テスト追加を実装タスクに明記session_statesの FOREIGN KEY 制約対策を S3-MF-002 に統合