はじめに
Codex使ってて、こんな状況になったことないですか?
AIに指示 → コード書いてもらう → 修正依頼 → また修正 → ...
(50回くらいやりとり)
→ 突然「コンテキスト制限に達しました」エラー
筆者も最初、「えっ、せっかくここまで進めたのに?」ってなりました。
そんな時に使うのが /compact
コマンド です。
この記事では、/compact
が何をするコマンドなのか、いつ使えばいいのかを、図を使ってわかりやすく解説します。
/compact
って何?
一言で言うと、「会話履歴を要約してコンパクトにするコマンド」 です。
問題: 会話が長くなるとAIが処理できなくなる
AIとの会話は、全て「履歴」として記録されています。
ユーザー: 「機能Aを実装して」
AI: 「実装しました」[コード表示]
ユーザー: 「ここにバグがあるから直して」
AI: 「修正しました」[修正コード]
...
(これが延々と続く)
この履歴が長くなると、AIが一度に処理できる量(コンテキストウィンドウ)を超えてしまいます。
イメージとしては:
- コンテキストウィンドウ = 本の1ページに書ける文字数
- 会話履歴 = 書かれた文字
- 文字が増えすぎると、1ページに収まらなくなる
解決策: /compact
で履歴を要約
/compact
を実行すると、こんな感じで履歴が圧縮される:
compact実行前:
履歴50個分のやりとり(ユーザーの指示、AIの応答、長いコード...)
トークン数: 50,000
で、実行すると:
compact実行後:
履歴1個(要約メッセージ):
「過去の会話内容の要約
完了: 機能Aの実装
未完了: テストが必要
TODO: エラーハンドリングを追加」
トークン数: 5,000
90%削減。重要な情報は残ってる。
/compact
を使うタイミング
タイミング1: トークン使用量が70-80%に達した時
Codexでは /status
コマンドで現在のトークン使用量を確認できます。
ユーザー: /status
Token usage: 45,000 / 100,000
まだ余裕あり
ユーザー: /status
Token usage: 85,000 / 100,000
そろそろ /compact を実行すべき
おすすめ: 80,000 / 100,000 くらいになったら実行する
タイミング2: 大きな機能が完了した時
会話の「区切り」で実行するのがベストです。
良いタイミング:
- 機能Aの実装が完了した後
- バグ修正が完了した後
- 次の機能に移る前
悪いタイミング:
- エラー解決の途中
- コードを書いてる最中
なぜかというと、要約時に「作業の途中」より「完了した状態」の方が綺麗にまとまるからです。
そういえば、筆者が一度エラー解決の真っ最中にcompact実行してしまって、「あれ、さっきのエラーメッセージ何だっけ?」ってなったことある。あれは失敗だった。
/compact
の実行方法
超簡単です。
ユーザー: /compact
これだけ。
実行すると、以下のメッセージが表示されます:
Compact task completed
これで完了です。次のメッセージから、要約された履歴を基に会話が続きます。
/compact
実行時に何が起こってるの?(詳細)
コマンド一発で完了するけど、裏では結構複雑なことやってる。
過去の会話を集める
まず、Codexは今までの会話履歴から「ユーザーが言ったこと」だけを集める。
元の履歴(50個のやりとり):
1. ユーザー「機能Aを実装して」
2. AI「実装しました」+ [長いコード]
3. ユーザー「バグ直して」
4. AI「修正しました」+ [長い修正コード]
...
ここからユーザーメッセージだけ抽出:
集めたメッセージ:
- 「機能Aを実装して」
- 「バグ直して」
- 「機能Bも追加して」
- 「テストを書いて」
AIの応答部分は含めない。ユーザーの「指示」だけあれば、何をしようとしてたかわかるから。
AIに「今までの作業を要約して」と頼む
ここが面白いんだけど、Codexは別のAIインスタンスを起動して、要約を作ってもらう。
このとき、AIには以下のような指示が送られます:
「次のエージェントへの引き継ぎメモを書いてください。
メモには以下を含めてください:
- 完了したことと、まだ必要なこと
- 未完了のTODOリスト(ファイルパスと行番号付き)
- テストが必要なコード
- 未解決のバグや問題点」
すると、AIが以下のような要約を作ってくれます:
完了したタスク:
- src/main.rs に機能Aを実装(45-120行目)
- データベース接続機能を追加(db.rs: 10-50行目)
未完了タスク:
- エラーハンドリングの強化が必要
- tests/integration_test.rs にテストを追加
TODO:
- src/main.rs:75 - タイムアウト処理を追加
- db.rs:30 - コネクションプールのサイズを調整可能にする
技術的注意:
- Tokio 1.x を使用、async/await パターン
- データベースは PostgreSQL を想定
この要約が、次の会話で使われる。
長すぎる部分を切り詰める
ユーザーメッセージを全部集めても、まだ長すぎる場合がある(20,000トークン以上)。
そういう時は、真ん中の部分を自動的に削除する:
元のメッセージ(長すぎる):
「機能A実装して」
「バグ直して」
「機能B追加して」
... [100個のメッセージ]
「機能Z追加して」
真ん中を削除すると:
切り詰め後:
「機能A実装して」
「バグ直して」
... [tokens truncated] ...
「機能Z追加して」
なぜ真ん中を削除するか?**最初の指示(何をしたいか)と最後の指示(今何してるか)**が一番重要だから。
この辺の実装、詳しくソース追ってないけど、たぶんtruncate_middle()みたいな関数で切り詰めてると思う。
「履歴ブリッジメッセージ」を作る
ここからが重要。集めたユーザーメッセージと、作った要約を組み合わせて、1つの特別なメッセージを作る。
【履歴ブリッジメッセージ】
あなたは元々、以下の指示を受けました:
- 機能Aを実装して
- バグ直して
- 機能Bも追加して
- テストを書いて
別のAIがこの問題の解決を開始して、作業状況をまとめました。
以下が要約です:
完了したタスク:
- src/main.rs に機能Aを実装
- データベース接続機能を追加
未完了タスク:
- エラーハンドリングの強化が必要
- tests/ にテストを追加
この情報を基に、作業を続けてください。
この「履歴ブリッジメッセージ」が、新しい履歴の中心になる。
古い履歴を新しい履歴に入れ替える
最後に、メモリ内の古い履歴を、新しい履歴に入れ替える。
入れ替え前:
メモリ内の履歴(50個のやりとり)
- ユーザー「機能Aを実装して」
- AI「実装しました」[長いコード]
- ユーザー「バグ直して」
- AI「修正しました」[長い修正コード]
- ... (50個、合計50,000トークン)
replace_history()を実行:
入れ替え後:
メモリ内の履歴(1個のメッセージ)
- 「履歴ブリッジメッセージ」
(ユーザーメッセージ + 要約、合計5,000トークン)
90%削減達成!
これで完了。次にあなたがメッセージを送ると、AIはこの「履歴ブリッジメッセージ」を読んで、過去の文脈を理解した上で作業を続けてくれる。
全体の流れをまとめると:ユーザーメッセージを集める → 別のAIに要約してもらう → 長すぎる部分を切り詰め → 履歴ブリッジメッセージを作る → メモリ内の履歴を入れ替え → 「Compact task completed」と表示。
所要時間は数秒〜十数秒くらい(要約生成にAI使うから、ちょっと時間かかる)。
そういえば、将来的には自動compactの機能とか追加されるかも?トークン使用量が一定以上になったら勝手にcompact実行してくれるみたいな。まだ確認してないけど、そうなると便利そう。
裏で保存されてるもの
ちなみに、メモリ内の履歴は入れ替わりますが、全ての履歴はディスクにも保存されています(Rolloutファイル)。
ディスク上のファイル:
~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl
内容:
- 古い50個のやりとり(全部残ってる)
- 「Compactを実行した」という記録
- 要約の内容
だから、セッションを再開した時に、完全に復元できます。メモリ内は消えても、ディスクには残ってるので安心です。
/compact
実行後の注意点
注意1: 詳細情報は失われる
要約されるので、細かい情報は消えます。
残る情報:
- 完了したタスク
- 未完了のタスク
- 重要なファイルパスや行番号
消える情報:
- 試行錯誤の過程
- エラーメッセージの詳細
- 中間的なやりとり
もし「あれ、さっきのエラーメッセージ何だったっけ?」と後で確認したい場合は、実行前にメモを取っておくのがおすすめです。
注意2: タスク実行中は使えない
AIがコードを書いてる最中や、ツールを実行してる最中は /compact
を使えません。
ユーザー: /compact
→ エラー: Task is running. Please wait.
タスクが完了してから実行してください。
注意3: 要約自体がトークンを消費する
/compact
を実行すると、AIが要約を生成するためにトークンを使います(500〜2,000トークンくらい)。
なので、「ちょっと会話しただけで毎回compact」はコスト的にもったいない。本当に必要な時だけ使いましょう。
/compact
vs /new
の違い
Codexには /new
というコマンドもある。似てるけど全然違う。
/compact
は履歴を要約して保持する。文脈は継続される。長い会話を続けたい時に使う。
/new
は履歴を完全にクリアする。文脈は新規開始。全く別の作業を始めたい時に使う。
使い分けとしては、同じプロジェクトで作業を続けたいなら/compact
、全く別の作業を始めたいなら/new
って感じ。
実際の使用例
例1: 長時間の実装作業
ユーザー: 「機能Aを実装して」
AI: [コード書く]
ユーザー: 「機能Bも追加して」
AI: [コード書く]
... (50ターン)
ユーザー: /status
Token usage: 85,000 / 100,000
ユーザー: /compact
Compact task completed
ユーザー: /status
Token usage: 6,500 / 100,000
ユーザー: 「じゃあ機能Cも実装して」
AI: [過去の文脈を基に、新しいコードを書く]
例2: 前日の作業を続ける
Codexは前回のセッションを再開(resume)できる。その時も/compact
の結果が保持される。
1日目: 機能A実装 → 長い会話 → /compact → セッション終了
2日目: Codexを起動 → 前回のセッションを再開 → compactの結果が保持されてる → 文脈を理解した状態で作業を続けられる
これ、めちゃくちゃ便利です。筆者も毎日使ってる。前日の夜に「明日ここから続けよう」ってcompact実行してから終わるのが習慣になってる。
よくある質問
Q1: いつ使えばいいかわからない
A: /status
を定期的に実行して、トークン使用量を確認しましょう。80%超えたら実行するのがおすすめです。
Q2: 要約が雑で重要な情報が消えた
A: 要約の品質はAIモデル次第です。GPT-4だと詳細に記録されますが、GPT-3.5だと省略気味。もし重要な情報が消えそうなら、実行前にメモを取っておくか、ユーザーメッセージとして「ここまでの重要ポイント」を書き込んでおくと良いです。
Q3: 何回でも実行できる?
A: はい。1つのセッションで何回でも実行できます。ただし、毎回トークンを消費するので、本当に必要な時だけ使いましょう。
Q4: 実行後に元に戻せる?
A: メモリ内の履歴は戻せません。ただし、Codexは全ての履歴を「Rolloutファイル」という形でディスクに保存してるので、セッションを再開すれば完全に復元できます(上級者向けの話)。
まとめ
/compact
は、長時間セッションの強い味方。
覚えておくポイント:
- 会話履歴を要約してトークン数を削減する
- トークン使用量が80%超えたら実行を検討
- 機能実装の区切りで実行するのがベスト
-
/status
で定期的に確認する
筆者も最初は「なんか難しそう」と思ってたけど、実際は「ただのコマンド一発」。使ってみると便利さがわかる。
長時間の作業を続けたい時、ぜひ試してみてください。
あ、そういえば、複数回compactした後のResumeってどうなるんだろう?理論上は完全に再現されるはずだけど、実際に試してないからわからない。そのうち試してみたい。
参考
- Codex公式ドキュメント(まだ充実してないけど、そのうち追加されるはず)
-
/help
コマンドでも簡単な説明が見られます