dwgx@blog:~$dwgx
> cd ../posts

AgentScope: ローカルの Codex と Claude Code のセッション監視コンソール

// created

AgentScope は Windows デスクトップ向けのコンソールで、ローカルマシン上の Codex と Claude Code のセッションを見つけ出し、インデックスを作り、検索できるようにし、各プロセスとセッションの関連付けがどう導かれたのかまで説明する。チャット UI でもカンバンでもなく、ただこの一つのことだけをやる。

きっかけは、Windows で二つの作業を同時に走らせていたら、マシンにすぐ見えないものが溜まっていったことだ。大量の node プロセス、.claude\projects 配下の transcript、.codex にあるバージョン番号付きの SQLite と rollout の JSONL。どのプロセスがどのセッションに対応するのか、編集途中の session はどこに保存されたのか、消したいけど動作中のものを巻き添えにするのが怖い、ディレクトリを漁ってもまったく対応が取れない。

どう作ったか

TypeScript + Electron で、三つに分かれている。

apps/desktop        Electron + React のデスクトップシェル
packages/core       Windows のプロセス/セッションインデックスのコア
packages/shared     共有モデルと IPC の安全性型

メインプロセスがローカルの特権を握り、preload はごく狭い IPC を一本だけ公開し、レンダラー層の React/TS が画面を描く。プロセス側は Win32_Process で Codex、Claude、node、app-server を拾い上げ、さらに Get-Process で起動時刻とウィンドウタイトルを補う。セッション側は二系統ある。Claude は .claude\sessions の PID ファイルを解析してから .claude\projects で transcript を探す。Codex はもっと厄介で、state_*.sqlite のようなバージョン番号付きの SQLite を読み込み、さらに rollouts 内の JSONL をスキャンする必要がある。

証拠であって、推測ではない

プロセスとセッションの対応付けはスコアリングで行う。PID、cwd、transcript のパス、session id、ウィンドウタイトル、時刻、それぞれが一つの証拠だ。結果は exactindexedheuristicunknown の四段階でラベル付けする。時刻だけ一致して他が何もないものは、そのまま unknown に落とし込み、本物のマッチのように偽装することは絶対にしない。Codex には今なお信頼できる PID から thread へのマッピングがないので、正直にそう明示する。

削除まわりは非常に保守的に作った。ローカルのセッションを消すのは本当に取り返しがつかないことがあるからだ。削除の前にまず .agentscope\backups にバックアップを取り、触る対象を quarantine の隔離領域へ移し、全工程で journal.json に各ステップを記録するので、何かあってもログをたどって遡れる。まだ動作中のもの、高信頼度の候補を持つもの、サブセッションを抱えているものは、そのまま削除をブロックする。プロセスを kill することもなく、いかなるベンダーの状態も復号せず、触るのはローカルの平文だけ、JSONL の検索でもメタデータしか照会せず、transcript の本文は返さない。