Codex CLIで過去の会話が見えない?ログから完全復元する方法

この記事は、OpenAI Codex CLIのTUI(ターミナルUI)で長い会話の過去ログがスクロールできなくなる問題の解決策をまとめたものです。 Google検索では「resume」が履歴書の意味に引っ張られて情報が見つからないため、ここに記録します。

この記事で解決できること

  • Codex CLIで長時間作業していたら、過去の会話が画面から消えて見えなくなった
  • codex resumeでセッションを再開したが、最初の方のやり取りを確認したい
  • 過去のセッションからキーワードで会話を検索したい
  • 会話履歴をテキストファイルとして保存・共有したい

結論:TUIのスクロールに期待するのが負け

Codex CLIのTUIは見た目はチャットですが、表示できるスクロール量には限界があります。長期戦になると過去ログが「物理的に掘れない」状態になります。

解決策は2つ:

  1. ローカルに保存されたログファイルを直接読む
  2. 端末の設定でスクロール上限を増やす

この記事では主に1の方法を詳しく解説します。

Codexのログはどこに保存されているか

Codex CLIは会話ログをローカルに自動保存しています。

~/.codex/sessions/YYYY/MM/DD/rollout-XXXX.jsonl

例:

~/.codex/sessions/2025/12/14/rollout-2025-12-14T11-00-35-019b1a96-986b-7e20-865e-db1aff031855.jsonl

このファイルはcodex resumeでセッションを選ぶときの対象にもなっています。

ログファイルの確認

ls ~/.codex/sessions/
# 年/月/日のディレクトリ構造

ls ~/.codex/sessions/2025/12/14/
# rollout-*.jsonl ファイルが並ぶ

JSONLファイルの構造を理解する

.jsonl(JSON Lines)は1行が1つのJSONオブジェクトになっている形式です。そのまま開くと非常に見にくいです。

必要なツール:jq

JSONを整形・抽出するためのコマンドラインツールです。

# インストール(Ubuntu/Debian)
sudo apt update && sudo apt install -y jq

ログの構造を確認する

まず、ログファイルのキー構造を確認します:

cd ~/.codex/sessions/2025/12/14

# ファイルを1つ選ぶ
f=$(ls -1 rollout-*.jsonl | head -n 1)
echo "FILE=$f"

# トップレベルのキーを確認
head -n 1 "$f" | jq 'keys'

出力例:

[
  "payload",
  "timestamp",
  "type"
]

typeの種類を確認する

ログには複数の種類のイベントが混在しています:

jq -r '.type' "$f" | sort | uniq -c | sort -nr | head -n 30

出力例:

    142 response_item
     47 event_msg
     12 turn_context
      1 session_start

主要なtype:

  • event_msg: ユーザーの入力やシステムイベント
  • response_item: AIの応答
  • turn_context: コンテキスト情報
  • session_start: セッション開始時のメタデータ

会話を見やすく抽出する

ユーザーの入力だけを抽出

jq -r '
  select(.type=="event_msg" and .payload.type=="user_message")
  | "USER: " + .payload.message
' "$f" | less -R

AIの応答だけを抽出

jq -r '
  select(.type=="response_item")
  | (.payload.role // "assistant") + ": " + ((.payload.content // []) | map(.text? // empty) | join(""))
' "$f" | less -R

会話全体をテキストファイルに変換

jq -r '
  if .type=="event_msg" and .payload.type=="user_message" then
    "USER: " + (.payload.message // "")
  elif .type=="response_item" then
    "ASSISTANT: " + ((.payload.content // []) | map(.text? // empty) | join(""))
  else empty end
' "$f" > convo.txt

less -R convo.txt

タイムスタンプ付きで出力

jq -r '
  select(.type=="event_msg")
  | "[" + (.timestamp|tostring) + "] "
  + (.payload.type // "event") + ": "
  + (.payload.message // "")
' "$f" > convo_with_timestamp.txt

キーワードで過去の会話を検索する

複数のログファイルからキーワードを検索するにはripgreprg)が便利です。

# インストール
sudo apt install -y ripgrep

# 検索
cd ~/.codex/sessions
rg -n "Next\.js|マルウェア|脆弱性" --include "*.jsonl"

特定のディレクトリ内で検索:

cd ~/.codex/sessions/2025/12/14
rg -n "検索したいキーワード" rollout-*.jsonl

便利コマンドを作成する(道具化)

毎回jqのコマンドを打つのは面倒なので、スクリプト化しておくと便利です。

codexlogコマンドの作成

mkdir -p ~/bin

cat > ~/bin/codexlog <<'SH'
#!/usr/bin/env bash
set -euo pipefail

f="${1:-}"
if [[ -z "$f" ]]; then
  f="$(ls -1t rollout-*.jsonl 2>/dev/null | head -n 1)"
fi

if [[ ! -f "$f" ]]; then
  echo "Error: File not found: $f" >&2
  exit 1
fi

jq -r '
  if .type=="event_msg" and .payload.type=="user_message" then
    "USER: " + (.payload.message // "")
  elif .type=="event_msg" then
    ((.payload.type // "event") + ": " + (.payload.message // ""))
  elif .type=="response_item" then
    ((.payload.role // "unknown") + ": " + ((.payload.content // []) | map(.text? // empty) | join("")))
  else empty end
' "$f"
SH

chmod +x ~/bin/codexlog

使い方

# PATHに~/binを追加(.bashrcに書いておく)
export PATH="$HOME/bin:$PATH"

# 最新のログを表示
cd ~/.codex/sessions/2025/12/14
codexlog | less -R

# 特定のファイルを指定
codexlog rollout-2025-12-14T11-00-35-XXXXX.jsonl | less -R

端末側の設定(補助的対策)

TUIのスクロール上限は端末の設定に依存します。

tmuxの場合

~/.tmux.confに追加:

set -g history-limit 100000

Windows Terminalの場合

Settings → Profiles → 該当プロファイル → Scrollback lines を増やす(例:100000)

scriptコマンドで丸ごと録画

端末の出力をそのままファイルに保存する方法:

script -f codex.tui.log
codex
# 作業後
exit

これでcodex.tui.logにTUIの出力がすべて記録されます。

Codex CLIの便利なスラッシュコマンド

長い会話でコンテキストが溢れそうなときに使えるコマンド:

コマンド説明
/compact現在の会話を要約してコンテキストを節約
/new同じCLI内で会話をリセット(セッションは維持)
/status現在のセッション情報を表示

トラブルシューティング

jqでパースエラーが出る

jq: parse error: Invalid numeric literal at line 1, column 4

原因head -n 1 rollout-*.jsonlで複数ファイルにマッチすると、headが見出し行(==> filename <==)を出力するため。

解決策: ファイルを1つだけ指定する

f=$(ls -1 rollout-*.jsonl | head -n 1)
head -n 1 "$f" | jq 'keys'

変数$fが古いファイルを指している

シェル変数はディレクトリを移動しても値が残ります。

解決策: 作業ディレクトリで変数を再設定する

cd ~/.codex/sessions/2025/12/14
f=$(ls -1 rollout-*.jsonl | head -n 1)
echo "FILE=$f"

または、フルパスで指定する:

f="$HOME/.codex/sessions/2025/12/14/rollout-2025-12-14T11-00-35-XXXXX.jsonl"

No such file or directory

確認方法:

pwd
echo "$f"
ls -l "$f"

現在のディレクトリと$fの値が一致しているか確認してください。

この方法が有効な理由

Codex CLIのログシステムは、UIが壊れても後から復元できるように設計されています:

  • 会話をイベント列(JSONL)として全て記録
  • 役割別(user/assistant/system)に分けて保存
  • 日付+UUIDでファイルを整理

これは「見やすさ」より「壊れない記録」を優先した設計です。

jqでログを解析できるようになると:

  • TUIの表示限界に縛られない
  • 過去のセッションを自由に検索できる
  • 会話をテキストとして保存・共有できる
  • ツールが壊れても自力で復旧できる

まとめ

やりたいことコマンド
ログの場所を確認ls ~/.codex/sessions/
最新のログを開くf=$(ls -1t rollout-*.jsonl | head -n 1)
構造を確認head -n 1 "$f" | jq 'keys'
ユーザー入力を抽出jq -r 'select(.type=="event_msg")...' "$f"
キーワード検索rg "キーワード" rollout-*.jsonl
会話をテキスト化codexlog > convo.txt

Google検索では見つからない情報ですが、知っておくと確実に役立ちます。

参考リンク

この記事が誰かの「見えない!」を解決できれば幸いです。

CodexのTUIで見えなくなった会話をログから復元する方法

CodexのTUI(Terminal User Interface)で長時間作業していると、過去の会話が見えなくなることがあります。これは会話が「消えた」わけではなく、TUIの表示限界で「見えなくなっている」だけです。

本記事では、ローカルに保存されているログ(JSONL形式)から会話を復元・検索する方法を解説します。

TUIとは

TUI(Terminal User Interface)は、ターミナル上で動作するユーザーインターフェースのことです。マウスで操作するGUIとは異なり、キーボード中心で操作します。Codexの画面もTUIの一種です。

ログの保存場所

Codex

~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl

Claude Code

~/.claude/projects/<project>/

どちらも考え方は同じで、「混ざっているログから必要な行だけ抜く」という発想で会話を復元できます。

ログを確認する準備

VSCodeで開く方法(推奨)

ログディレクトリは階層が深いため、コマンドで辿るよりVSCodeで.codexフォルダを開いて視覚的に確認するのが効率的です。

cd ~
ls -la .codex

ログは日付ごとに整理されています。日によってはファイルが複数あるため、まず「どれを読むか」を絞る必要があります。基本的には一番新しいrollout-*.jsonlから見ればOKです。

ログの構造を理解する

ログには主に2種類の重要なタイプがあります。

event_msg

ユーザーが入力した内容が記録されています。

jq -c 'select(.type=="event_msg") | .payload' "$f" | head -n 1 | jq .

出力例:

{
  "type": "user_message",
  "message": "こんにちは。\n最近、next.jsの脆弱性をつかれマルウェアに感染したんだ。",
  "images": []
}

messageフィールドにユーザーが打った文章がそのまま入っています。

response_item

AIの応答やシステム情報が記録されています。

jq -c 'select(.type=="response_item") | .payload' "$f" | head -n 1 | jq .

出力例:

{
  "type": "message",
  "role": "user",
  "content": [
    {
      "type": "input_text",
      "text": "<environment_context>..."
    }
  ]
}

role(user/assistant)とcontentの中に本文が入っています。環境情報も混ざるため、会話本文とは別枠で扱う必要があります。

構造の確認

jq -c 'select(.type=="response_item") | .payload' "$f" | head -n 1 | jq 'keys'

出力:

["content", "role", "type"]

type / role / contentがあれば、roleでユーザーとアシスタントを分けて、contentのtextだけ抜くことで会話を復元できます。

会話を抽出するjqコマンド

event_msgresponse_itemから会話だけを抽出できます。抽出後はマウスホイールやキーボードの上下キー、PageUp/PageDownでスクロールできます。終了するときはアルファベットの「q」を押します。

特定のキーワードで検索する

rg(ripgrep)を使えば、特定のキーワードを含むログを素早く検索できます。

# nginx関連のログを検索
rg nginx "$f"

# プロキシ関連のログを検索
rg proxy "$f"

# ファイル名っぽいものを検索
rg -n "(/etc/nginx|nginx\.conf|sites-available|.conf|Dockerfile|next\.config|package\.json)" "$f"

# 編集・変更に関するログを検索
rg -n "edit|modify|change|update|patch|diff|ファイル|修正|変更" "$f"

ログで見えるもの・見えにくいもの

見える可能性が高いもの

  • 「○○ファイルを編集した」「設定を変えた」などの説明文
  • 実行したコマンド
  • 作業ディレクトリ(cwd)や環境情報

見えにくい・保証できないもの

  • パッチ全文(どの行をどう変えたかのdiff)
  • 実際に書き換えられたファイルの中身そのもの

ログは「痕跡を拾う」用途には便利ですが、差分の真実を知るにはGitが最強です。

まとめ

  • codex resumeで再開はできるが、TUIでは過去の経緯が全部見えないことがある
  • ログを直接読むと、作業中に流れていた情報ややり取りが残っていて後から追える
  • 会話はログから復元できるが、ファイルの変更内容を100%確実に残すならgit diffが一番
タイトルとURLをコピーしました