Экспорт диалогов Claude Code в PDF с помощью jsonl-to-pdf
Практическое руководство по превращению JSONL-файлов, которые Claude Code пишет в ~/.claude/projects/, в готовые к публикации PDF с помощью jsonl-to-pdf, с вложенностью субагентов, скрытием секретов, компактной и тёмной темами и рецептами для CI.
Каждый диалог с Claude Code хранится как файл .jsonl в глубине ~/.claude/projects/, по одной строке на ход, в полной точности, без отрисовки. jsonl-to-pdf — это небольшой CLI, который превращает эти файлы в PDF, удобные для чтения в просмотрщике, прикрепления к pull request, отправки в тред Slack или печати на бумаге. Самый быстрый способ попробовать его на последней сессии — npx jsonl-to-pdf. Команда открывает интерактивный селектор, спрашивает, включать ли диалоги субагентов, и пишет PDF с заголовком в текущий каталог.
В этой статье разбирается, откуда берутся JSONL-файлы, что в действительности оказывается в PDF (вложенные субагенты, блоки рассуждений, вызовы инструментов и их результаты, вложенные изображения), какие флаги стоит знать для внешней передачи (--compact, --redact, --no-thinking, --subagents-mode appendix, --dark), и несколько рецептов для CI и автоматизации. Версия — jsonl-to-pdf 0.1.0 в связке с Claude Code 2.1.x. Репозиторий — на GitHub, пакет — на npm.
Где Claude Code хранит ваши диалоги
Claude Code пишет один JSONL-файл на сессию по пути ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl. Сегмент <encoded-cwd> — это рабочий каталог, в котором запускалась сессия, с разделителями путей, заменёнными на -. Поэтому C:\S\my-app в Windows становится C--S-my-app, а /Users/marius/work в macOS или Linux — -Users-marius-work. Каждая строка — это JSON-объект: ход пользователя, ход ассистента, вызов инструмента, результат инструмента, блок рассуждений или метаданные сессии вроде cwd, gitBranch, aiTitle и permissionMode.
Диалоги субагентов (сессии, которые основной агент порождает через инструмент Task/Agent) лежат в соседнем каталоге: <session-id>/subagents/<sub-session-id>.jsonl. Это полноценные сессии со своими JSONL-потоками, привязанные по ID к вызову инструмента в основном файле. На практике эта вложенность рекурсивна: субагент, порождающий собственный субагент, оставляет третий файл рядом со вторым.
Эта раскладка важна, потому что в интерфейсе Claude Code она напрямую не отображается. Если после закрытия диалога нужно что-то с сессией сделать (заархивировать, поделиться, провести аудит), сначала вы находите её на диске. CLI делает поиск за вас командой jsonl-to-pdf list, но кодировку путей стоит знать на случай, если будете искать конкретную сессию вручную через grep. Недавнее изменение PR-from-URL в Claude Code 2.1.119 продолжает добавлять в эти файлы всё больше метаданных сессии, поэтому JSONL всё чаще оказывается каноническим логом того, что на самом деле сделал запуск агента.
Быстрый старт: npx jsonl-to-pdf
Путь без установки запускает jsonl-to-pdf напрямую из npm, не трогая ваш package.json:
# Node
npx jsonl-to-pdf
# Bun
bunx jsonl-to-pdf
# pnpm
pnpm dlx jsonl-to-pdf
Это открывает интерактивный селектор, который проходит по локальному каталогу проектов Claude Code, выводит каждую сессию в порядке от новой к старой с заголовком, возрастом и размером, и спрашивает, включать ли диалоги субагентов. Выберите сессию, ответьте на вопрос, и CLI запишет PDF с именем по заголовку сессии в ваш текущий рабочий каталог:
$ jsonl-to-pdf
◆ Project C:\S\my-app
◆ Session Refactor the billing module to use Stripe webhooks · 2h ago · 412KB
◆ Include sub-agent conversations? › Yes
✓ Wrote refactor-the-billing-module-to-use-stripe-webhooks.pdf
Если путь к файлу уже известен, convert принимает его как позиционный аргумент и пропускает селектор:
jsonl-to-pdf convert ~/.claude/projects/C--S-my-app/abc-123.jsonl
Обе формы принимают одни и те же флаги. Интерактивный селектор уместен, когда вы конвертируете разовую сессию; форма convert уместна, когда вы пишете скрипт против известного файла (загрузка артефакта в CI, hook автоматизации, пакетная архивация).
Для глобальной установки npm i -g jsonl-to-pdf или bun i -g jsonl-to-pdf кладут в ваш PATH и jsonl-to-pdf, и более короткий алиас j2pdf. Требуется Node 18 или новее.
Что попадает в PDF
По умолчанию PDF сохраняет полную точность сессии, а не только видимый чат:
- Каждый запрос пользователя и ответ ассистента, по порядку.
- Блоки рассуждений (внутренние рассуждения модели, когда включён расширенный режим мышления). Полезно, когда нужно разобрать, как агент решил, что делать.
- Каждый вызов инструмента с полным входом. Вызов
Bashпоказывает свою команду, вызовEdit— диф, вызов MCP — свои аргументы. - Каждый результат инструмента, включая полный stdout/stderr bash. Длинные выводы переносятся, а не обрезаются.
- Вложенные изображения, встроенные в той точке диалога, где они были прикреплены.
- Субагенты, отрисованные с вложенностью в нужном месте. Когда основной агент породил
TaskилиAgent, весь поддиалог появляется с отступом у того вызова инструмента, который его запустил. Субагенты, порождающие субагентов, отрисовываются так же, рекурсивно.
Блоки кода отрисовываются моноширинным шрифтом, с переносом строк, учитывающим синтаксис, и логикой переноса страниц, которая не рвёт строку посреди токена. Разделы содержат лёгкие навигационные элементы (номера страниц, заголовок сессии в шапке) без дизайна ради дизайна. Тема по умолчанию — светлая; --dark переключает на тёмную тему, которая лучше выглядит на экране и хуже на бумаге.
В этой точности и есть смысл. PDF сессий агента полезнее всего, когда читатель видит ровно то, что видела модель, ровно то, что она запустила, и ровно то, что вернулось. Сжатый экспорт читается как постмортем; полный экспорт читается как стенограмма.
Субагенты inline или в приложении
Отрисовка по умолчанию — inline: каждый диалог субагента появляется в позиции вызова инструмента, который его породил, с отступом и визуальной группировкой, чтобы родительский поток было легко читать. Это правильное значение по умолчанию для отладки, когда нужно видеть отступление в контексте.
--subagents-mode appendix переключает на другую раскладку: основной диалог читается сверху вниз без перерывов, а диалоги субагентов уходят в конец документа с якорями, ведущими обратно к вызову инструмента, который их породил. Это правильный режим для чтения в стиле code review, когда родительский диалог — это история, а потоки субагентов — подтверждающие свидетельства:
# inline (default)
jsonl-to-pdf convert session.jsonl
# appendix
jsonl-to-pdf convert session.jsonl --subagents-mode appendix
# omit sub-agents entirely
jsonl-to-pdf convert session.jsonl --no-subagents
Третий вариант, --no-subagents, нужен в случаях, когда диалоги субагентов — это шум (часто: длинные поиски в стиле Explore, не влияющие на итоговое изменение). Тогда в PDF попадает только поток основного агента.
Compact и redact: безопасно делиться сессией
Два флага закрывают сценарий «хочу поделиться этим вовне».
--compact обрезает сессию до самого нужного. Блоки рассуждений скрываются, а любой ввод/вывод инструмента длиннее примерно 30 строк урезается с явным маркером [N lines omitted]. Результат читается как обычный чат, без глубокой трассировки. Удобно, когда нужно отдать диалог коллеге, которому важен только итог.
--no-thinking — более тонкий разрез: скрывает только блоки рассуждений ассистента, оставляя вызовы инструментов и их результаты на месте. Полезно, когда трассировка важна, но внутренние рассуждения слишком многословны для печати.
--redact прогоняет каждую строку документа через набор регулярных выражений, которые матчат типовые форматы секретов: AWS access и secret keys, GitHub Personal Access Tokens (классические и fine-grained), API-ключи Anthropic и OpenAI, заголовки Bearer, токены Slack и приватные ключи в PEM-кодировке. Каждое совпадение заменяется на [redacted:<kind>], чтобы читатель понимал, какой именно секрет там был, не видя самого значения. Полный список паттернов лежит в src/utils/redact.ts на GitHub проекта.
# safe to email
jsonl-to-pdf convert session.jsonl --compact --redact
# safe to share, full fidelity
jsonl-to-pdf convert session.jsonl --redact
Используйте --redact всегда, когда получатель находится за пределами вашей зоны доверия. Даже если вы уверены, что в сессии не было ключа, цена флага практически нулевая, а цена ошибки — одна перевыпущенная боевая учётная запись.
Рецепты
Несколько паттернов, которые встречаются часто.
Пакетно конвертируйте последнюю неделю. Каждая сессия новее заданной даты, по одному PDF на каждую, рядом с местом, где вы запустили команду:
jsonl-to-pdf list --json |
jq -r '.[] | select(.modifiedAt > "2026-04-22") | .filePath' |
while read f; do jsonl-to-pdf convert "$f"; done
jsonl-to-pdf list --json печатает по одной записи на сессию с полями sessionId, projectPath, filePath, sizeBytes и modifiedAt, так что любой фильтр, который вы можете выразить в jq, работает.
Прикрепите активную сессию как артефакт CI. Полезно в любом пайплайне, где запуск Claude Code породил изменение, и вы хотите архивировать диалог рядом с выводом сборки:
- run: npx -y jsonl-to-pdf convert "$CLAUDE_SESSION_FILE" -o session.pdf --redact
- uses: actions/upload-artifact@v4
with:
name: claude-session
path: session.pdf
Пайпите в принтер или просмотрщик PDF. Форма -o - пишет PDF в stdout, что удобно для пайпа в lp, lpr или другой бинарник печати вашей платформы, либо в одноразовый просмотрщик PDF без оставления файла на диске:
jsonl-to-pdf convert session.jsonl -o - | lp
Выведите все сессии, которые видит CLI. Без PDF, только индекс:
jsonl-to-pdf list
Вывод по умолчанию читается человеком, с --json — машиной. Удобная точка для скриптов вокруг agent tooling; в статье про повторяющуюся триаж-задачу Claude Code есть более развёрнутый пример того же паттерна (расписанная задача, потребляющая list --json).
Автономные бинарники, когда вы не хотите устанавливать Node
Страница GitHub Releases поставляет однофайловые бинарники, собранные bun build --compile, по одному на ОС и архитектуру, без рантайма Node. Полезно на сборочных агентах, которым запрещено ставить toolchain Node, или на закрытых рабочих станциях, где глобальные npm-установки заблокированы:
# macOS / Linux
curl -fsSL https://github.com/marius-bughiu/jsonl-to-pdf/releases/latest/download/install.sh | sh
В Windows скачайте jsonl-to-pdf-win-x64.exe из последнего релиза и положите в свой PATH. Бинарник принимает те же флаги, что и установка через npm: convert, list, --compact, --redact, --dark и так далее.
Почему именно PDF, а не «открыть в браузере»
Несколько причин, по которым формат PDF оправдывает себя по сравнению с HTML-просмотром, который есть в roadmap.
- Архив. Локальные файлы сессий Claude Code ротируются, собираются сборщиком мусора или просто забываются. PDF — это замороженный самодостаточный snapshot, который можно положить в папку проекта, в issue или в бэкап.
- Поделиться. Большинство инструментов code review и чатов аккуратно принимают PDF-вложения. Вставлять JSONL на 400KB в тред Slack — опыт хуже, чем дропнуть PDF.
- Прочесть. Чтение работы агента так же, как вы читаете code review (за столом, в самолёте, на бумаге), — это другой режим внимания, чем скролл в чате. PDF переживает такой переход.
- Аудит. Подписанный, детерминированный экспорт — это запись того, что действительно было сказано и запущено. Внутренние команды compliance могут размечать PDF; они не могут размечать JSONL.
- Онбординг. Реальная сессия — куда лучший учебный материал для джуниора, чем универсальный туториал. PDF превращает такую передачу в задачу с одним вложением.
Roadmap, кратко
Релиз 0.1.0 покрывает только Claude Code. Roadmap на GitHub проекта обещает адаптеры для Aider, OpenAI Codex CLI, Cursor Compose и Gemini CLI — все они пишут какую-то разновидность JSONL- или JSON-Lines-стенограмм. Помимо покрытия форматов:
- HTML-вывод для встраиваемых веб-просмотров и небольшой статический viewer.
- Подсветка синтаксиса в блоках кода через токены Shiki.
- Оглавление с номерами страниц (текущие сборки используют PDF outlines/закладки).
- Флаги фильтрации:
--turns 5..15,--only assistant,--exclude-tool Bash, для случаев, когда полная стенограмма — это слишком.
Если вы пишете CLAUDE.md и hook, чтобы держать сессии в рамках (это разобрано в руководстве по CLAUDE.md), то jsonl-to-pdf — это подходящий артефакт: способ выйти из сессии с чем-то долговечным, на что можно сослаться. Репозиторий — github.com/marius-bughiu/jsonl-to-pdf.
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.