Skill v1.0.1
currentAutomated scan100/1004 files
version: "1.0.1" name: ai-conversation-extractor description: "Convert AI conversation transcripts (Claude Code, Codex CLI, ChatGPT JSONL; Cursor IDE SQLite) to readable Markdown. Use when the user wants to: (1) convert .jsonl conversation transcripts to .md, (2) strip binary/base64 data from AI conversation logs, (3) make AI conversation history human-readable, (4) process session exports from ~/.claude/ or ~/.codex/, (5) batch-convert a folder of conversation JSONL files, or (6) list, search, or export Cursor IDE chat/composer conversations. Triggers on mentions of JSONL conversations, transcript conversion, conversation export, readable conversation logs, or Cursor chat history."
ai-conversation-extractor
Convert AI conversation transcripts (Claude Code, Codex CLI, ChatGPT/Gemini JSONL; Cursor IDE SQLite storage) to clean, readable Markdown files. Strips binary blobs (base64 images, PDFs — typically 95%+ of file size) while preserving all human-readable content: user messages, assistant text, thinking, tool calls, and tool results.
See scripts/README.md for full JSONL format documentation.
Supported Formats
Auto-detected from file content — no flags needed:
| Format | Source | Typical location | |
|---|---|---|---|
| Claude Code | Claude Code CLI sessions | ~/.claude/projects/*/*.jsonl | |
| Codex CLI | OpenAI Codex CLI sessions (event stream with timestamp/type/payload) | ~/.codex/sessions/*.jsonl | |
| Codex history | Codex CLI prompt history (session_id/ts/text) — user prompts only | ~/.codex/history.jsonl | |
| Simple | ChatGPT / Gemini exports (role/message) | varies | |
| Cursor | Cursor IDE chat/composer conversations (SQLite, via cursor_extract.py) | ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb |
Usage
Run the script at scripts/extract.py (within this skill's directory):
# Single file — outputs .md alongside the .jsonlpython3 <skill-dir>/scripts/extract.py <file.jsonl># Single file with custom output pathpython3 <skill-dir>/scripts/extract.py <file.jsonl> -o output.md# All .jsonl in a directorypython3 <skill-dir>/scripts/extract.py <directory># Recursive (includes subdirectories)python3 <skill-dir>/scripts/extract.py <directory> --recursive# Messages-only view (user + final assistant response per turn, no tools/thinking)python3 <skill-dir>/scripts/extract.py <file.jsonl> --ua-final-only# Batch convert to a specific output directorypython3 <skill-dir>/scripts/extract.py <directory> --out-dir ./converted/# Keep Codex environment context and boilerplate in messages-only modepython3 <skill-dir>/scripts/extract.py <file.jsonl> --ua-final-only --keep-env-context --keep-agent-boilerplate
No external dependencies — uses only Python 3.12+ stdlib (json, re, pathlib, argparse, sqlite3).
Cursor IDE conversations
Cursor stores conversations in a global SQLite DB (cursorDiskKV table: composerData:<id> metadata rows + bubbleId:<composerId>:<bubbleId> message rows; old versions inline the conversation in composerData). Use scripts/cursor_extract.py (opens the DB read-only, safe with Cursor running):
# List all conversations (newest first): composerId, last-updated, message count, titlepython3 <skill-dir>/scripts/cursor_extract.py --list [--limit 50]# Find conversations whose content matches a regex (full DB scan — can take minutes on multi-GB DBs)python3 <skill-dir>/scripts/cursor_extract.py --grep "AccessManager|rate.?limit"# Extract specific conversations to Markdown (named <title-slug>-<id8>.md)python3 <skill-dir>/scripts/cursor_extract.py <composerId> [<composerId>...] --out-dir ./converted/# Extract everything / use a custom DB path (e.g. Linux/Windows)python3 <skill-dir>/scripts/cursor_extract.py --all --out-dir ./converted/ --db <path/to/state.vscdb>
Output uses the same Markdown conventions as extract.py. Notes: per-message timestamps are not stored by Cursor (only conversation-level created/updated times, used for frontmatter and file mtime); tool results in very recent Cursor versions may live in encrypted blobs and show as tool calls without results.
CLI Flags
| Flag | Description | |
|---|---|---|
-o, --output | Custom output path (single-file mode only) | |
-r, --recursive | Recurse into subdirectories | |
--ua-final-only | Messages-only view: keeps user messages and final assistant response per turn, drops tool calls/results/thinking | |
--out-dir | Output directory for batch mode (writes <stem>.md into this folder) | |
--keep-env-context | With --ua-final-only: retain Codex <environment_context> user messages (dropped by default) | |
--keep-agent-boilerplate | With --ua-final-only: retain Codex AGENTS.md/skills boilerplate messages (dropped by default) |
What Gets Stripped
- Base64-encoded images and documents (biggest savings)
<system-reminder>tags injected by the toolfile-history-snapshotrecords (editor state backups)progressrecords (hook events)systemrecords (turn durations, metadata)- Meta messages (
isMeta: true, like/initinjections) - Line-number prefixes from file reads (
123→)
What Gets Preserved
- User text messages (full)
- Assistant text responses (full)
- Assistant thinking blocks (truncated at 3000 chars, in
<details>tags) - Tool calls (name + JSON input, truncated at 4000 chars)
- Tool results (text content, full; no truncation)
- Image/document placeholders (e.g.,
*[attached document: application/pdf]*) - Error results from rejected tool uses
- Per-message timestamps (Claude Code format only)
- Source file metadata (YAML frontmatter) and filesystem mtime (output .md matches source .jsonl mtime for natural sort-by-date)
Output Format
- YAML frontmatter:
source,modified(ISO 8601) for parseable metadata - Filesystem: Output .md file's modification time is set to match the source .jsonl, so
ls -tor Finder sort-by-date preserves conversation order - Markdown with
## User/## Assistantheadings separated by---. Per-message timestamps shown as*2026-02-09T23:51:07Z*when available (Claude Code format). Tool calls formatted as**Tool: \Name\**with JSON code blocks. Tool results as**Result** (\id\):with code blocks.