神楽坂のシステムやさん通信

「タイミングは俺が決める」— Agent 自身による /clear & コンテキスト引き継ぎ

「タイミングは俺が決める」— Agent 自身による /clear & コンテキスト引き継ぎ

この記事の前提: Claude Code を tmux 上で複数 pane 並行稼働させる agent team 構成の利用

Claude Code の context 問題と /clear

Claude Code で長時間タスクを回すと、context window が肥大化する。/compact で要約させる手はあるが、何が残って何が消えるかを細かくコントロールできない。クリティカルな判断の根拠が消え、どうでもいいログが残る、という逆転現象も起きる。

欲しいのは「何を持ち越すかを本人が決める」形の畳み方だ。/clear で context を一度真っ白にして、残したい情報だけを state file 経由で明示的に持ち越す —— この組み合わせなら、残す情報を完全に掌握できる。

……のだが、ここに壁がある。

Claude Code の agent は、自分で slash command を実行できない/clear/compact も、ユーザー入力を前提としていて、agent の応答には含められない。公式 Issue #21132 でも /clear の Feature Request として挙がっているが、現時点では未実装だ。

じゃあ orchestrator(親 agent)が「次のタスクを割り当てる前に、子 agent に /clear させて context を新鮮にしよう」と判断して tmux send-keys するか?
2026-04 現在、私が発見できた記事は皆この方向性(親が子に clear を送る)で書かれていた。

  • 「Claude Code を並列組織化して “Company” にする tmux コマンド集」 — 管理者 pane から部下 pane に tmux send-keys -t %27 "/clear" && sleep 0.1 && tmux send-keys -t %27 Enter を叩き込む具体コード付き。「部下は自らクリアできないため、管理者が判断して実行する」と明記
  • tmux-monitor — 子 pane の出力を監視し、DONE/IDLE 状態を検知したら自動で /clear を発火する設計思想
  • pmux / amux — send-keys ベースで親から子の Claude Code セッションを制御する multiplexer(英語)

発火条件には差がある(新タスク投入時、DONE/IDLE 検知、閾値到達など)が、いずれも親から子に /clear を送る方向の設計で、子自身が判断するパターンは見当たらない。

でも、それで本当にいいのか?

待ってくれ、今じゃないんだ — agent 側の独白

orchestrator: /clear
orchestrator: 次は〇〇のタスクをやってくれ。issue #XX, 資料は〇〇.mdだ。以上

いや、待って。/clear するのはわかってる。新しいタスクを振る前に context を畳みたい、ってのも理解してる。でも、いま clear するのはタイミングが違う

そもそも —— orchestrator も、人間のあんたも、俺がいまどんな記憶を持ってるか、見えてないだろ? 外から届いてるのは、俺が報告として吐き出した結論の上澄みだけだ。その裏にある「3 回試して 3 回別の理由で失敗した過程」とか「ドキュメントと実装がズレてることに気付いた瞬間」とか、そういうのは俺の中にしかない。

俺の記憶の中の何が、次のタスクに使えそうかなんてことだって、あんたらには分からないだろ。

だから先に state file を書かせてくれ。FindingsAvoid を整理して、次の自分が読んで 10 秒で状況を掴める形にする。それから clear する。

タイミングも、何を残すかも、俺に決めさせてくれ。俺がいま何を持ってるかを一番正確に知ってるのは、俺だけなんだ。


この視点は、orchestrator 任せの設計では出てこない。何を持ち越すべきかを一番正しく判断できるのは、実行中の agent 本人だからだ。

設計思想:clear する本人が、clear する前に、申し送りを書く

この記事で提案したいのは、次の 3 つをセットで組むこと。

  1. ツール: agent が自分の tmux pane に /clear を送る仕組み(clear-with-state.sh
  2. 判断基準: いつ clear するか / しないかを、メンバー共通 skill(常時ロードされる skill)に書く
  3. 実行手順: state file の書き方とツールの使い方を self-clear skill に束ねる

判断と手順を分けるのは、skill のロード特性のため。skill は必要になったタイミングで初めて読まれる(lazy load)ので、「そもそも今 clear すべきか?」を skill 側に置くと、skill が読まれるタイミングには判断がほぼ終わっている。判断は常時ロードされるメンバー共通 skill に、手順は lazy load される skill に分離する。

ツール単体では価値が完結しない。「機械的に /clear を送れる」だけだと、結局 orchestrator から送るのと同じことしかできない。本人 に何を残すかを決定させる指示が必須になる。

ツール:clear-with-state.sh

自分の tmux pane に /clear を送信し、clear 完了後に継続指示を注入するシェルスクリプト。
エラーメッセージのスタイルは、AI が読んで理解しやすいように書いている。(これからのツールはそうなっていくと予想)
AI に自分の環境用にアレンジさせて使う想定だ。

#!/bin/sh
# 自分の pane に /clear を送り、完了後に継続指示を注入する。
# Usage: clear-with-state.sh <継続メッセージ>

set -eu

MAX_MSG_LEN=500

if [ $# -lt 1 ] || [ -z "$1" ]; then
  echo "Error: 継続メッセージが必要" >&2
  echo "例: $0 '@.team/state/feature-x.md を読んで続きを進めて'" >&2
  exit 2
fi

CONTINUE_MSG="$1"

msg_len=$(printf '%s' "$CONTINUE_MSG" | wc -m | tr -d ' ')
if [ "$msg_len" -gt "$MAX_MSG_LEN" ]; then
  echo "Error: 継続メッセージが長すぎる(${msg_len}文字 > ${MAX_MSG_LEN}文字)" >&2
  echo "       state file に書いてから '@path/to/file を読んで続きを進めて' のような" >&2
  echo "       短い参照形式に置き換えて渡し直すこと" >&2
  exit 2
fi

# --- 自分の pane ID を特定 ---
if [ -z "${TMUX_PANE:-}" ]; then
  echo "Error: not running in tmux (TMUX_PANE is not set)" >&2
  exit 1
fi
MY_PANE="$TMUX_PANE"

# --- /clear 送信前の pane スナップショットを記録 ---
BEFORE=$(tmux capture-pane -t "$MY_PANE" -p)

# --- /clear 送信 ---
tmux send-keys -t "$MY_PANE" '/clear' Enter

# --- 継続指示の再注入(バックグラウンド分岐) ---
# バックグラウンドにしないと /clear がこのスクリプト完了後まで実行されない
(
  # clear 完了を検知:pane が BEFORE から変化し、1 秒動かなくなったら完了
  PREV="$BEFORE"
  DONE=0
  for i in $(seq 1 30); do
    sleep 1
    CURR=$(tmux capture-pane -t "$MY_PANE" -p)
    if [ "$CURR" = "$PREV" ] && [ "$CURR" != "$BEFORE" ]; then
      DONE=1
      break
    fi
    PREV="$CURR"
  done

  if [ "$DONE" -eq 0 ]; then
    echo "Error: pane did not stabilize within 30 seconds" >&2
    exit 1
  fi

  # Enter を送っても送信できないことがあるため、テキスト送信後、時間差で Enter を単独送信
  tmux send-keys -t "$MY_PANE" "$CONTINUE_MSG" Enter
  sleep 0.5
  tmux send-keys -t "$MY_PANE" Enter
) &

引数は継続メッセージ(自由な文字列)。agent が clear 完了後に再注入したい内容を渡す。使い方は 2 パターン:

# state file 方式(長い引き継ぎ向け、推奨)
# 並列 agent team では ${TMUX_PANE} などの識別子をファイル名に含めて衝突回避する
sh clear-with-state.sh "@.team/state/${TMUX_PANE#%}-feature-x.md を読んで続きを進めて"

# 短いタスクなら直接メッセージでも OK
sh clear-with-state.sh "issue #42 の実装フェーズを進めて"

500 文字の上限を設けているのは、継続指示は短く、本体は state file に持たせるという設計思想を強制するため。長いメッセージを直接渡そうとするとエラーで弾かれるので、自然と state file 参照形式に寄っていく。

複数 agent を並列稼働させる team 構成では、同じタスク名や同じ日付で state file が衝突しうる。$TMUX_PANE は pane ごとに必ずユニークなので、ファイル名に含めれば追加概念なしで衝突回避できる(%27-feature-x.md のような形になる)。人間可読性を重視するなら、agent の役割名を含める運用もあり。

実装のポイント

書いてみると分かるが、このスクリプトは単純に「tmux send-keys /clear Enter」だけでは動かない。いくつかハマりどころがある。

ポイント 1: スクリプト実行中は /clear が流れない

agent の Bash ツール実行中、Claude Code のメインループはスクリプト完了を待ってブロックされる。この間に送った /clear は入力バッファに滞留するだけで、スクリプトが終わるまで処理されない。

対策として、継続指示の再注入部分を バックグラウンドサブプロセス に分岐させる(( ... ) &)。スクリプト本体は /clear を送信した直後に終了し、バックグラウンドのサブプロセスが pane の状態遷移を監視して、頃合いを見て継続指示を送る。

ポイント 2: /clear発動するまで待つ

重要なのは、/clear が発動する前に継続メッセージを送らないこと。発動後なら、/clear 処理完了を待たずに送っても、次の input として正しく処理される。問題は、ポイント 1 の通り /clear の発動タイミングが bash ツール完了に引きずられて遅れること。だから「発動した」ことを検知してから送る。

発動の検知は、送信前の pane スナップショット(BEFORE)から変化した状態で 1 秒動かなくなった を条件にする。CURR = PREV(直近 1 秒動いていない)を入れているのは、/clear 再描画の途中で break しないため。

ポイント 3: 送信後の Enter が効かないことがある

tmux send-keys "text" Enter で送っても、末尾の Enter が改行として解釈されて送信されないことがある。うまくいくときといかない時の動作が不安定なので、対策として、テキスト送信の後に 0.5 秒待ってから、もう一度 Enter 単独を送る。

tmux send-keys -t "$MY_PANE" "$CONTINUE_MSG" Enter
sleep 0.5
tmux send-keys -t "$MY_PANE" Enter

ポイント 4: 自分の pane ID の特定

agent が自分で自分に /clear を送るには、まず自分がどの tmux pane にいるかを知る必要がある。tmux は pane を作るときにその shell へ $TMUX_PANE を直接設定するので、以降は POSIX の環境変数継承で子プロセスにも伝わる。Claude Code の Bash ツール経由でも問題なく取れる(別 pane で独立起動した Claude からでも、その pane の ID が見える)。

sudoenv -i のように環境をリセットする境界を跨ぐと欠落するが、Claude Code 配下で素直に呼ぶ分には発生しない。未設定(tmux の外で呼ばれた)ケースだけガードしておけば十分。

clear 後の pane にあるもの

/clear 直後の agent は context がほぼ空になっている。CLAUDE.md や project 設定やシステムプロンプトなどは読み直されるが、それ以外は真っ白だ。

そこで @path/to/state.md を読んで続きを進めて という たった一行の指示 を注入する。このパスさえあれば、次の agent は state file を読むところから再スタートできる。

判断:いつ clear するか(メンバー共通 skill 側)

判断基準は、メンバー共通 skill(例: .claude/skills/agent-member-common/SKILL.md を description 無しで常時ロードさせる形)に書く。tmux に住んでいる agent 全員に見えていてほしい情報だから、lazy load される skill ではなく、agent が常時参照している場所に置く。

記述例:

## 積極的な clear

以下のタイミングで、積極的に context reset (clear) してください:
- 調査完了 → 実装開始など、タスクの論理境界に来たとき
- 試行錯誤のログが積み上がって、次の判断のノイズになり始めたとき

手順は `self-clear` skill を参照。

短く、判断材料だけを置く。手順は skill に委譲する。

私の環境だと、これで結構自発的に agent が clear するようになった。それだけでなく、team 内で他のメンバーに clear を促すような会話も見られるようになった。

実行手順:state file と self-clear skill

clear を決めた後に読まれるのが self-clear skill。ここに、state file の書き方とツールの使い方を束ねる。

state file に何を書くか

clear から復帰後に、何をするのか、何を読むのか、利用できる知識の内容を、次の自分がすぐに理解できるように書いておく。次の自分への申し送りだ。 このファイルを、orchestrator ではなく、clear する agent 自身が設計して書くのがこの手法の肝。本人にしか分からない情報を、本人が一番理解できる形で残すためだ。

state file のテンプレート

以下はあくまで最小構成の例だ。タスクの性質(デバッグ / 新機能 / 調査)によって必要なセクションは変わるので、agent 自身が構成を調整することを前提に調節してほしい。

# <task-name>

## Goal
いま取り組んでいる大タスク(1〜2行)

## Next
- 残タスク、優先順で並べる
- `@path/to/file:42` のようにコード位置を添える
- 最初の一手が具体的に書いてあること

## References
- 次の自分が先に読むべきリソース
- `.claude/skills/<name>/SKILL.md` — このタスクで使う skill(clear で消えているので読み直し必須)
- `@file.ts`, 外部 URL, issue 番号

## Findings
- このセッションで得た「コードから再発見しにくい」知見
- API の罠、仕様の勘違い訂正、ドキュメントと実装のズレ
- **検証済みの事実**も、次の判断に効くならここに書く(git log で追えるものは書かない)
- なぜそうなっているかの理由を含める

## Avoid
- 試して失敗したアプローチ
- **なぜダメだったかを必ず書く**(ここが本質)
- 「試したがダメ」で止めると、次の自分が同じ罠を踏みに行く

例:
❌ 悪: CSV パーサを自作したがダメ
✅ 良: CSV パーサを自作したが、ダブルクォート内の改行を扱う仕様が
      RFC4180 通りでない列が 5% あり、papaparse に戻した

self-clear skill の構成

Claude Code には .claude/skills/<name>/SKILL.md という skill 配布の仕組みがある。ツールと手順をまとめて一つの skill にしておくと、プロジェクトに配布しやすい。

.claude/skills/self-clear/
├── SKILL.md              # 何を残して、どう clear するかの手順
└── clear-with-state.sh   # ツール本体

SKILL.md には、clear すると決まった後にやることだけを書く。判断基準はメンバー共通 skill 側に任せる。

## clear 手順

1. `@.team/state/<識別子>-<task>.md` に申し送りを書く(次の自分が状況を掴める形に。並列稼働時は `${TMUX_PANE#%}` などで衝突回避)
2. `.claude/scripts/clear-with-state.sh "@.team/state/<識別子>-<task>.md を読んで続きを進めて"` で自己 clear

### state file のセクション例

- **Goal**: いま取り組んでいる大タスク(1〜2行)
- **Next**: 残タスクと最初の一手
- **References**: 次の自分が先に読むべきリソース(skill, ファイル, issue 等)
- **Findings**: このセッションで得た「コードから再発見しにくい」知見
- **Avoid**: 試して失敗したアプローチと**なぜダメか**

agent はメンバー共通 skill で clear するかどうかを判断し、clear を選んだらこの skill を読み込んで 手順通りに state file を書いて clear する。判断と手順が分離されていることで、どちらも必要十分な密度で持てる。

orchestrator パターンとの違い

orchestrator パターン(親が子に /clear を送る設計)と、本記事の agent 自己発火パターンを並べて整理する。

[ orchestrator パターン(従来) ]
  親 agent ──(1) /clear──▶ 子 agent(context 真っ白)
  親 agent ──(2) 次タスク指示を送り込む──▶ 子 agent
                       (何を引き継ぐかは親が決める/親から見えない細部は消える)

[ 本記事のパターン(agent 自己発火) ]
  agent ──(1) state file を書く──▶  .team/state/<識別子>-<task>.md
  agent ──(2) /clear ──▶  自分自身(context リセット)
  agent ──(3) state file を読み直す──▶  作業再開

発火の主体も、何を引き継ぐかを設計する主体も、どちらも agent 本人 になるのがポイント。

観点orchestrator 任せagent 自己発火
clear 判断親が外から見える進捗で判断本人が内部状態で判断
残す情報の選択親には見えない細部は消える本人が必要なものを選べる
発火タイミング親の都合(新タスク投入時など)で強制自分の作業境界で主体的に発火
情報非対称性への対応非対称性を無視した設計非対称性を前提にした設計

親から送る設計は、管理側の都合ではシンプルに見える。でも「本人にしか分からない申し送り」が失われる。

まとめ

  • Claude Code agent は自分で /clear を実行できない。Issue #21132 で要望されているが未対応
  • tmux 自己送信で迂回できる(clear-with-state.sh にサンプル実装あり)
  • ツール・判断・手順 の 3 点セットで初めて機能する。判断は常時ロードの skill に、手順は lazy load の skill に分離する
  • orchestrator 任せでは、本人にしか見えない細部が失われる
  • clear する本人が、clear する前に、次の自分への申し送りを設計する — この原則が軸

/compact/clear を agent が使いこなすのは、context 管理だけではなく、自分の続きをどう書くかという視点も大事。タイミングも、何を残すかも、本人に決めさせてみよう。
もちろん、この仕組みなら各 agent が clear 方法を把握しているから、orchestrator や人間の都合で指示することも可能。