Claude Code 始めました
Claude Codeの"続きから"を実装するのに、自動検知を諦めた話

前の記事でThroughlineを公開した。コンテキストの大半を占めてるツールI/Oを退避するやつ。

あの時点では"動いてた"。自分の環境では。

でも記事を出した直後から、おかしな挙動に気づき始めてた。

並行で別のウィンドウを開くと、新しいセッションが前のセッションの記憶を勝手に拾う。VSCodeを再起動すると、毎回「前回のセッションから続き」扱いになる。一度も /clear してないのに。

原因: /clear を検知できない

Claude Codeのhookには SessionStart ってイベントがあって、source っていうフィールドで startup(新規起動)と clear(/clear後)を区別できる、はずだった。

ところがVSCode拡張だと、/clear しても sourcestartup に潰される。GitHub issue #49937 に上がってる既知の問題。CLI単体なら動くけど、拡張だと識別できない。

自分はVSCode拡張で使ってる。つまり「startupとclearを区別する」前提の設計が、根本から崩れてた。

ヒューリスティックで補おうとした

じゃあ時間差で判定するか。前のセッションの最終活動から10秒以内ならclear、それ以上ならstartup、みたいな。

これも壊れた。

  • 並行でウィンドウを2つ開いてると、両方が"最近活動してた"ので両方が継承先候補になる
  • VSCode再起動でもtranscriptは残ってるので"最近"に見える
  • プロセスツリーを追いかけようとしたけど、CLIとextensionでプロセス構造が違う

“そもそも検知できる条件が無い"と気づいた。

発想を変えた

検知しようとするから失敗する。ユーザーが宣言すれば、検知はいらない。

作ったのが /tl ってスラッシュコマンド。ユーザーが次のセッションに記憶を引き継ぎたい時だけ打つ。打つと handoff_batons ってテーブルにそのセッションIDが書き込まれる。バトンを置くイメージ。

次のセッション開始時、バトンが1時間以内に置かれてたら、そのセッションの記憶を引き継ぐ。なければ、何もしない。新規セッションとして始まる。

並行ウィンドウもVSCode再起動も、「バトンが置かれてない限り誤爆しない」が原理的に保証される。

明示的なのは一見面倒だけど、「勝手に引き継いで迷惑」の方が遥かに困る。誤爆ゼロの方が価値があった。

でも、これだけじゃ物足りなかった

バトンができて、次のセッションが前のセッションの会話ログを読めるようになった。でも実際に使ってみて思ったのが、「ただログを読んでるだけ」感。

過去ログを読むAIと、中断地点から続けるAIは、体感が違う。

前者は「よし、状況を把握した。じゃあ今から何をしましょうか?」って聞いてくる。後者は「さっきの続きだと、あと◯◯を確認すればいいよね」って進める。

ここで2つ足した。

in-flight memo. /tl を打った瞬間、今動いてるClaude自身に「次の一手、今の仮説、未解決の問題、進行中のTODO」をMarkdownで書いてもらう。それをバトンに添付する。

thinkingの保存. Claudeのextended thinking(内部推論)ブロックもL3として保存しておく。次のセッションの注入時、最終ターンのthinkingを頭に出す。前のClaudeが何を考えてたかが、次のClaudeに渡る。

結果、次のセッションの注入テキストはこういう形になる。

あなたは中断されたタスクを再開します。

[前のClaudeが書いた in-flight memo]
次やること: X のテストを書く。仮説: Y が原因だと思う。未解決: Z。

[前のClaudeが最後に考えてたこと]
Z の挙動が気になる。もしかしたら...

[直近20ターンの会話]
...

“読む"じゃなく"続ける”

これで手応えが変わった。

/clearして/tlして新セッションを始めると、次のClaudeがいきなり「じゃあさっきのXのテスト、書き始めるね」から始まる。読んでない。続けてる。

人間同士でも、誰かに仕事を引き継ぐ時、ログを全部読ませるより「次にやること。理由。気になってること一つだけ」ってメモ渡す方が速い。同じだった。

本当は自動がよかった

誤解してほしくないんだけど、自分は「裏で勝手に動く」のが理想だと思ってる。ユーザーが明示的に何かを打たなきゃいけないのは、本当は妥協。

今回は「検知できないから宣言に逃げた」。VSCode拡張の source 問題が直れば自動検知に戻したいし、戻す。それまでの間、明示バトンで代替してるだけ。

ただ、妥協とはいっても実害はほぼない。自動検知でも /clear は結局打つわけで、それが /tl に置き換わるだけ。キーストロークは変わらず、誤爆だけゼロにできてる。

「明示のほうが正しい」ではなく、「検知できなかったから宣言で済ませた」。それが正直なところ。


Throughline は v0.3.2 でnpmに公開してる。Node.js 22.5+、依存ゼロ、MIT。

Throughline — GitHub

npm install -g throughline
throughline install

興味ある人は覗いてみてください。