Small CLI to help browse Codex CLI session logs and extract user/assistant messages from JSONL files for later summarization.
Current version: 0.4.0 (see CHANGELOG.md for details).
- List recent sessions under
~/.codex/sessions(or a custom dir) with a fixed header that labels age, size, cwd, and cached summary counts. - Show each session's working directory (parsed from the log) directly in the list output.
- Track how many cached summaries exist per session and reuse that information in both the
listoutput and the interactive browser. - Extract only lines where
"type":"message"into a new JSONL. - Stream to stdout or write to a file.
- Default output path is the current working directory (not the script location).
- Accept either a full path or just the filename present under the sessions dir.
- Jump straight from
listtoextractby passing the numeric row shown in the listing. - Optional interactive browser (
browsesubcommand) that now supports summary viewing/regeneration alongside message extraction.
There is no PyPI package yet—install directly from this repository.
git clone [email protected]:QLiMBer/codex-summarize-session.gitcd codex-summarize-session- Pick your install style:
- pip (current environment)
- Standard CLI:
pip install . - With interactive browser:
pip install .[browser] - Editable: add
-e, e.g.pip install -e .[browser]
- Standard CLI:
- pipx (isolated venv)
- Standard CLI:
pipx install . - With interactive browser:
pipx install .[browser] - Editable:
pipx install --editable .[browser](use--forcewhen refreshing an existing install)
- Standard CLI:
- pip (current environment)
Either approach drops the codex-summarize-session entrypoint on your PATH (often ~/.local/bin or the active virtualenv).
- Export an API key via
OPENROUTER_API_KEY=<token>before running summary commands; we read it on every invocation so you can scope it per shell. - Optionally store the key at
~/.config/openrouter/key(one line, no quotes). The CLI checksOPENROUTER_API_KEYfirst, then this file, so you can keep the variable unset in scripts. - Set
OPENROUTER_API_BASEif you need to target a self-hosted proxy; otherwise the default public endpoint is used. - Keep tokens out of version control—
codex-summarize-sessiononly reads the key and never writes back to that file. - When the key is missing we will gate the upcoming
summariescommands/browse shortcuts with a clear error so it’s safe to install ahead of configuration.
- pipx:
pipx uninstall codex-summarize-session - pip:
pip uninstall codex-summarize-session- prompt_toolkit: it is not automatically uninstalled
- you can manually uninstall it using
pip uninstall prompt_toolkit
- Editable installation
pip install -e .[browser]pipx install --editable .[browser]
- Run directly without install:
python codex_summarize_session/cli.py listpython -m codex_summarize_session.cli extract <session.jsonl>
- Ad-hoc run (no permanent install):
pipx run --spec . codex-summarize-session list
-
List latest sessions (most recent first):
codex-summarize-session listcodex-summarize-session list --limit 50
-
Browse interactively (requires the optional
[browser]extra):codex-summarize-session browsecodex-summarize-session browse --limit 50codex-summarize-session browse --summary-model mistral/mistral-large --summary-temperature 0.5
Key bindings:
- Arrow keys/PageUp/PageDown/Home/End: navigate the session table.
Enter: prompt for message extraction path (same as before).s: view the cached summary for the highlighted session usingpydoc.pager(if present).g: generate a summary when none exists, or view the cached copy when one is already available.G: regenerate the summary, bypassing cache.qorEsc: quit the browser.
Summary configuration flags:
--summaries-dir: override the cache root (defaults to~/.codex/summaries).--prompt: select the prompt variant or point to an absolute file path.--summary-model,--summary-temperature,--summary-max-tokens,--summary-reasoning-effort: mirror thesummaries generateCLI options for fast iteration inside the browser.
-
Customize summary prompts:
codex-summarize-session summaries generate 1 --prompt concisecodex-summarize-session summaries generate 1 --prompt /tmp/my-prompt.mdcodex-summarize-session browse --prompt concisecodex-summarize-session browse --prompt ~/prompts/session-review.md
-
Generate AI summaries (requires OpenRouter API access):
codex-summarize-session summaries generate 1codex-summarize-session summaries generate ~/.codex/sessions/example.jsonl --model x-ai/grok-4-fast:freecodex-summarize-session summaries generate 1 --stdout --strip-metadata
-
Extract by filepath:
codex-summarize-session extract /home/user/.codex/sessions/2025/09/07/rollout-2025-09-07T23-41-39-...jsonl
-
Extract by filename (searched under the sessions dir):
codex-summarize-session extract rollout-2025-09-07T23-41-39-...jsonl
-
Extract by list index (uses the same ordering as
list):codex-summarize-session extract 3
-
Stream extracted lines to stdout:
codex-summarize-session extract --stdout <session.jsonl>
-
Choose a specific output directory (filename is auto-chosen as
<input-basename>.messages.jsonl):codex-summarize-session extract --output-dir ~/notes/summaries <session.jsonl>
-
Choose an exact output file path:
codex-summarize-session extract --output ~/notes/summaries/my-session.messages.jsonl <session.jsonl>
-
Choose a different sessions dir:
codex-summarize-session --sessions-dir ~/.codex/sessions extract <session.jsonl>
- Default output location is your current working directory at runtime, not the directory where the script is installed (e.g., not
~/.local/bin). - If you pass
--output-dir, the file is written there using the default filename<input-basename>.messages.jsonl. - If you pass
--output, that exact file path is used. - Use
--forceto overwrite an existing output file. - Malformed JSON lines are skipped instead of aborting the extraction.
- The
summaries generatecommand caches Markdown output under~/.codex/summaries/<session>/<variant>/summary.mdand the cleaned transcript alongside it assummary.messages.jsonl, so repeat runs avoid additional API spend. - The
listoutput and TUI browser share the same cache scanner, so the "Summaries" column reflects the number of cached variants on disk in both modes. - Prompt variants live under
codex_summarize_session/summaries/prompts/. Reference a file by stem name—or pass an absolute path—with the shared--promptflag used by both CLI and TUI. Cache folders are keyed by that variant name, so different prompts keep independent summaries. - Extraction normalizes entries where messages are wrapped in
response_itempayloads and preserves timestamps when present. - The
browsecommand will prompt for a destination path (pre-filled with a sensible default). PressCtrl+Cto cancel. - When summary key bindings are used without an API key configured, the browser reports the issue inline and stays responsive.
- When
prompt_toolkitis missing, the CLI suggests installing the optional[browser]extra before launching the interactive mode.
-
Prompt files are plain text/Markdown—no templating required. Whatever you write becomes the system prompt.
-
When we call OpenRouter the conversation looks like this:
System: <your prompt> User: <session start> """ <messages-only transcript> """ </session end> -
The default template (
summaries/prompts/default.md) already explains that the transcript is wrapped between<session start>/<session end>markers. Feel free to create additional prompts in that directory or point to any file with--prompt.
- Test both dependency setups when iterating on the browser: run once with
prompt_toolkitinstalled (python -m pip install .[browser]orpipx inject codex-summarize-session prompt_toolkit) and again after uninstalling it (python -m pip uninstall prompt_toolkit) to ensure the CLI’s guidance for missing extras stays accurate. - If you keep both a pip and pipx install, whichever
codex-summarize-sessionappears first onPATHwins. Runwhich codex-summarize-sessionto confirm, or uninstall one copy before testing changes. - After changing installs, run
hash -r(or open a new shell) so Bash forgets cached command locations; otherwise it might still call a removed shim.