Convert Codex and Claude Code session logs to HTML transcripts
Project description
ai-code-sessions
Transform ephemeral AI coding sessions into permanent, browsable artifacts.
Table of Contents
- Standing on Simon's Shoulders
- The Problem Worth Solving
- What You Get
- Quick Start
- The
ais ctxWorkflow - The Changelog System
- CLI Reference
- Configuration
- How Source Matching Works
- Architecture
- Documentation
Standing on Simon's Shoulders
This project is a fork of Simon Willison's claude-code-transcripts (Apache-2.0). The core of what makes this tool useful—the parsing logic, the paginated HTML rendering, the thoughtful presentation of tool calls and their outputs, the collapsible sections, the clean typography—that's all Simon's work.
I discovered his project through his blog post and immediately recognized it as the solution to something I'd been wanting: a way to preserve AI coding sessions as readable artifacts. His code does the hard work of transforming messy JSONL logs into something you'd actually want to read.
What I've added on top:
- Codex CLI support (in addition to Claude Code)
- Automatic source matching for finding the right log file when running concurrent sessions
- An
ais ctxworkflow for naming sessions and organizing exports by project - An append-only changelog system for generating structured summaries
- An interactive setup wizard for easy configuration
But the rendering engine—the part that makes the HTML output look good—that's Simon's contribution. If you find the transcripts beautiful and readable, credit goes to him. My additions are plumbing around the edges.
The original project: github.com/simonw/claude-code-transcripts
The Problem Worth Solving
Every time you pair-program with an AI, a complete record of problem-solving unfolds—hypotheses formed, dead ends explored, solutions discovered. But when the terminal closes, that knowledge evaporates.
AI coding tools generate verbose, machine-formatted logs:
- Codex:
~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl - Claude Code:
~/.claude/projects/<encoded-path>/<session-id>.jsonl
These files are technically readable, but practically useless for humans. Thousands of lines of JSON. Tool calls nested in content blocks nested in messages. Simon's project transforms that chaos into something you'd actually want to read.
This fork extends his work to support both Codex and Claude, with some workflow conveniences for people who use both.
What You Get
Each export produces a self-contained directory:
.codex/sessions/2026-01-02-1435_fix-auth-race-condition/
├── index.html # Timeline of prompts with statistics
├── page-001.html # First 5 conversations
├── page-002.html # Next 5 conversations
├── source_match.json # How the source file was identified
└── session.jsonl # Original log (archived)
Simon's rendering engine produces clean, readable HTML:
- User prompts appear cleanly, with markdown formatting preserved
- Assistant responses show text, tool calls, and reasoning blocks
- Tool results are syntax-highlighted and collapsible
- File edits display as side-by-side diffs
- Long content truncates gracefully with expand buttons
- Git commits auto-link to GitHub (detected from session metadata or git push output)
The index page shows a timeline of every prompt in the session, with statistics: which tools were called, how many commits were made, whether tests passed. All of this presentation logic comes from the original claude-code-transcripts.
Quick Start
1. Install
# Install the CLI globally
pipx install ai-code-sessions
pipx ensurepath
# Verify it works
ais --help
2. Run the Setup Wizard (Recommended)
ais setup
The wizard will:
- Ask for your GitHub username (for changelog attribution)
- Set your preferred timezone for session folder names
- Configure changelog generation preferences
- Optionally update your
.gitignore
3. Start Your First Session
# With Codex
ais ctx "Fix the login race condition" --codex
# With Claude Code
ais ctx "Add unit tests for auth module" --claude
When you exit the AI tool (Ctrl+D or /exit), your session is automatically exported to:
.codex/sessions/YYYY-MM-DD-HHMM_Your_Label/(for Codex).claude/sessions/YYYY-MM-DD-HHMM_Your_Label/(for Claude)
4. View Your Transcript
# macOS
open .codex/sessions/*/index.html
# Linux
xdg-open .codex/sessions/*/index.html
The ais ctx Workflow
ais ctx is the recommended way to use this tool. It wraps the Codex or Claude CLI, preserving all terminal colors and interactivity, and automatically exports a transcript when you're done.
Basic Usage
# Start a new Codex session with a descriptive label
ais ctx "Refactor database connection pool" --codex
# Start a new Claude session
ais ctx "Debug memory leak in worker process" --claude
Resuming Sessions
Sessions can be resumed, and ais ctx will update the existing transcript:
# Resume the most recent Codex session
ais ctx "Continue database refactor" --codex resume
# Resume a specific Codex session by ID
ais ctx "Continue database refactor" --codex resume abc123
# Resume a specific Claude session
ais ctx "Continue memory debugging" --claude --resume abc123
# Or pick from a list
ais resume codex
ais resume claude
What Gets Generated
After each session, you'll find:
| File | Description |
|---|---|
index.html |
Timeline of all prompts with tool call statistics |
page-001.html, page-002.html, ... |
Paginated conversation pages (5 conversations each) |
source_match.json |
Metadata about which native log file was selected |
rollout-*.jsonl or *.jsonl |
Copy of the original session log |
export_runs.jsonl |
Export metadata (for resumable backfills) |
Tips
- Labels are important: They become part of the directory name and appear in transcripts
- Use descriptive labels: "Fix login bug" is better than "debug"
- Sessions are per-repo: Transcripts are stored in your project directory, making them easy to find
The Changelog System
Beyond transcripts, ai-code-sessions can generate structured changelog entries after each session. These aren't commit messages—they're higher-level summaries of what an AI-assisted coding session actually accomplished.
What Gets Captured
Each entry includes:
| Field | Description |
|---|---|
summary |
One-line description of the session's purpose |
bullets |
3-5 specific changes or accomplishments |
tags |
Classification (feat, fix, refactor, docs, etc.) |
touched_files |
Created/modified/deleted/moved files (best-effort) |
tests |
Test commands + results (pass/fail/unknown) |
commits |
Git commits made during the session |
Where Changelogs Live
.changelog/
└── your-username/
├── entries.jsonl # Successful changelog entries (append-only)
└── failures.jsonl # Failed generation attempts (for debugging)
Enabling Changelog Generation
Option 1: Environment Variables
export CTX_ACTOR="your-github-username"
export CTX_CHANGELOG=1
Option 2: Setup Wizard
ais setup
Option 3: Per-Repo Config
Create .ai-code-sessions.toml in your project root:
[changelog]
enabled = true
actor = "your-github-username"
Choosing an Evaluator
Changelog entries are generated by an AI evaluator. You can choose:
| Evaluator | Model | Strengths |
|---|---|---|
codex (default) |
Default: gpt-5.2 with xhigh reasoning |
Fast, good at summarization |
claude |
Default: opus with 8192 thinking tokens |
More detailed analysis |
Model names must be supported by the selected CLI. Codex CLI documents its model list (for example, gpt-5.2-codex and gpt-5.1-codex-mini) and accepts --model/-m overrides.
Configure via environment:
export CTX_CHANGELOG_EVALUATOR="claude"
export CTX_CHANGELOG_MODEL="opus"
Or in config:
[changelog]
evaluator = "claude"
model = "opus"
claude_thinking_tokens = 8192
Backfilling Existing Sessions
Generate changelog entries for sessions that were exported before you enabled changelogs:
# Backfill all sessions in current repo
ais changelog backfill --project-root "$(git rev-parse --show-toplevel)"
# Backfill a specific sessions directory
ais changelog backfill --sessions-dir ./.codex/sessions
# Use Claude as the evaluator with custom concurrency
ais changelog backfill --evaluator claude --max-concurrency 5
Privacy Note
Consider adding .changelog/ to your .gitignore if you don't want to commit these entries (recommended for public repos).
CLI Reference
All commands are available via ais (short) or ai-code-sessions (full).
ais setup
Interactive wizard to configure global and per-repo settings.
ais setup
ais setup --no-global # Skip global config
ais setup --no-repo # Skip per-repo config
ais setup --force # Overwrite existing configs
ais ctx
Start a labeled AI coding session with automatic transcript export.
ais ctx "My session label" --codex
ais ctx "My session label" --claude
ais ctx "My session label" --codex resume
ais ctx "My session label" --claude --resume <session-id>
ais resume codex
ais json
Convert a specific JSON/JSONL file to HTML transcript.
# Basic conversion
ais json /path/to/session.jsonl -o ./out
# With options
ais json /path/to/session.jsonl \
-o ./out \
--label "My Session Name" \
--json \
--open \
--repo owner/name
| Option | Description |
|---|---|
-o, --output |
Output directory (required) |
--label |
Label shown in transcript header |
--json |
Copy input file to output directory |
--repo |
Enable GitHub commit links (owner/repo) |
--open |
Open index.html after generating |
--gist |
Upload to GitHub Gist |
ais find-source
Find the native log file matching a time window (used internally by ais ctx).
ais find-source \
--tool codex \
--cwd "$PWD" \
--project-root "$(git rev-parse --show-toplevel)" \
--start 2026-01-02T07:25:55.212Z \
--end 2026-01-02T09:16:57.576Z
ais export-latest
Export the most recent session matching a time window (used internally by ais ctx).
ais export-latest \
--tool codex \
--cwd "$PWD" \
--project-root "$(git rev-parse --show-toplevel)" \
--start 2026-01-02T07:25:55.212Z \
--end 2026-01-02T09:16:57.576Z \
-o ./.codex/sessions/2026-01-02-0000_My_Session \
--label "My Session" \
--json \
--changelog
ais changelog backfill
Generate changelog entries for existing session directories.
ais changelog backfill --project-root "$(git rev-parse --show-toplevel)"
ais changelog backfill --sessions-dir ./.codex/sessions --actor "username"
ais changelog backfill --evaluator claude --max-concurrency 5
| Option | Description |
|---|---|
--project-root |
Git repo containing session outputs |
--sessions-dir |
Specific sessions directory to process |
--actor |
Override changelog actor |
--evaluator |
codex or claude (default: codex) |
--model |
Model override for evaluator |
--max-concurrency |
Max concurrent evaluations (Claude only, default: 5) |
ais changelog since
Query changelog entries by date or git commit.
ais changelog since 2026-01-06 # Since a specific date
ais changelog since yesterday # Since yesterday
ais changelog since "3 days ago" # Relative date
ais changelog since HEAD~5 # Since a git commit
ais changelog since main --format json # Output as JSON
ais changelog since yesterday --tool codex # Filter by tool
| Option | Description |
|---|---|
--format |
Output format: summary, json, bullets, table |
--project-root |
Git repo root |
--actor |
Filter by actor |
--tool |
Filter by tool (codex or claude) |
--tag |
Filter by tag (repeatable) |
ais changelog lint
Validate existing changelog entries for quality issues.
ais changelog lint # Scan all entries
ais changelog lint --actor myusername # Filter by actor
ais changelog lint --fix # Re-evaluate and fix issues
ais changelog lint --fix --dry-run # Preview what would be fixed
| Option | Description |
|---|---|
--project-root |
Git repo root |
--actor |
Filter by actor |
--fix |
Re-evaluate entries with validation errors |
--evaluator |
Evaluator for --fix: codex (default) or claude |
--dry-run |
Preview fixes without making changes |
ais changelog refresh-metadata
Recompute entry metadata (touched_files, tests, commits) from stored transcripts without re-running the evaluator.
This is useful if a parser bug was fixed (e.g., file touches weren’t detected correctly) and you want to update historical entries without spending evaluator tokens.
ais changelog refresh-metadata --project-root "$(git rev-parse --show-toplevel)" --dry-run
ais changelog refresh-metadata --project-root "$(git rev-parse --show-toplevel)" --actor myusername
ais changelog refresh-metadata --project-root "$(git rev-parse --show-toplevel)" --actor myusername --all
| Option | Description |
|---|---|
--project-root |
Git repo root |
--actor |
Filter by actor |
--only-empty/--all |
Refresh only entries with empty touched_files (default) or all entries |
--dry-run |
Preview changes without writing |
Claude-Specific Commands (Inherited)
These commands are inherited from Simon's original tool:
ais local— Interactive picker from~/.claude/projectsais web— Fetch sessions via the Claude APIais all— Build browsable archive for all local Claude sessions
Configuration
Config File Locations
| Type | Location |
|---|---|
| Global (macOS) | ~/Library/Application Support/ai-code-sessions/config.toml |
| Global (Linux) | ~/.config/ai-code-sessions/config.toml |
| Global (Windows) | %APPDATA%\ai-code-sessions\config.toml |
| Per-repo | .ai-code-sessions.toml or .ais.toml in project root |
Precedence (Highest to Lowest)
- CLI flags
- Environment variables
- Per-repo config
- Global config
Example Config
[ctx]
tz = "America/Los_Angeles" # Timezone for session folder names
[changelog]
enabled = true # Enable changelog generation
actor = "your-github-username" # Who gets credited in changelogs
evaluator = "codex" # "codex" or "claude"
model = "" # Blank uses tool defaults
claude_thinking_tokens = 8192 # Claude-specific setting
Environment Variables
| Variable | Description |
|---|---|
CTX_TZ |
Timezone for session folder names |
CTX_CODEX_CMD |
Override Codex executable path |
CTX_CLAUDE_CMD |
Override Claude executable path |
CTX_CHANGELOG |
Enable changelog (1/true) |
CTX_ACTOR |
Changelog actor (username) |
CTX_CHANGELOG_EVALUATOR |
codex or claude |
CTX_CHANGELOG_MODEL |
Model for evaluator |
CTX_CHANGELOG_CLAUDE_THINKING_TOKENS |
Claude thinking tokens |
How Source Matching Works
When you run concurrent AI sessions, identifying which log file belongs to which session becomes non-trivial. This project solves it with intelligent matching:
- Date search: Scans session directories for the date range ±1 day
- Modification time filter: Considers files modified within the session window
- Timestamp extraction: Reads first/last entries to get actual session bounds
- Working directory matching: Verifies the session was started in the expected directory
- Scoring: Minimizes timestamp delta to find the best match
The result is saved to source_match.json with the selected file and up to 25 candidates—so you can verify or manually override if needed.
Debugging Source Matching
If a transcript picks the wrong session:
# Check what was selected
cat .codex/sessions/*/source_match.json | jq .best
# Re-export with the correct file
ais json /path/to/correct-file.jsonl -o .codex/sessions/my-session --json
Architecture
The implementation lives in a single focused module (src/ai_code_sessions/__init__.py, ~5,000 lines) with Jinja2 templates for HTML rendering. Key patterns:
- Format normalization: Both Codex and Claude logs are parsed into a common "loglines" format
- Content block handling: Modern multi-block messages (text + images + tool calls) are rendered correctly
- Graceful degradation: Export succeeds even if changelog generation fails
- Content-addressed deduplication: Changelog entries have content-based IDs to prevent duplicates
- Parallel backfill: Claude changelog backfill runs up to 5 evaluations concurrently
Documentation
Detailed documentation is available in the docs/ directory:
| Document | Description |
|---|---|
| docs/README.md | Documentation overview |
| docs/cli.md | Complete CLI reference |
| docs/ctx.md | The ais ctx workflow |
| docs/config.md | Configuration options |
| docs/changelog.md | Changelog generation |
| docs/source-matching.md | How source file matching works |
| docs/troubleshooting.md | Common issues and fixes |
| docs/privacy.md | Privacy and safety considerations |
| docs/development.md | Contributing and development |
| docs/pypi.md | Publishing to PyPI |
Because every debugging session teaches something worth remembering.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ai_code_sessions-0.1.7.tar.gz.
File metadata
- Download URL: ai_code_sessions-0.1.7.tar.gz
- Upload date:
- Size: 80.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33e84a21c526c034f92698f0ec68f929fdc5aaf16277bfd02a9b9dafea05076f
|
|
| MD5 |
1c1c3b44d13623a4d1a18e4daeb3bd53
|
|
| BLAKE2b-256 |
e8ccccddfbc3302ac01b4eb35de9b1d9b6d0f0c2cb71205142aaaabf1e54000c
|
File details
Details for the file ai_code_sessions-0.1.7-py3-none-any.whl.
File metadata
- Download URL: ai_code_sessions-0.1.7-py3-none-any.whl
- Upload date:
- Size: 85.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
708c869c93c5e76d906e0bfae2f4b7d5d06b74790fde3fd78844669eb978b5a5
|
|
| MD5 |
28a12cc50a79fb0be9ed70164d11c5c4
|
|
| BLAKE2b-256 |
2242666b5d7e00cfa263ee4775487ef998eb42a28b99ee9ab472746aff9e2193
|