Claude Code пишет каждую сессию в ~/.claude/projects/<путь-проекта>/<uuid>.jsonl. Формат машинный: thinking, tool_use и результаты инструментов лежат разными типами блоков, связи между сообщениями идут через parentUuid, а tool_result формально приходит ролью user. Через jq это читается, но недолго.
Claude Code History Viewer (jhlee0409/claude-code-history-viewer, MIT, Rust + Tauri) собирает из этих файлов интерфейс: диалоги с тулколлами, глобальный поиск, статистику по токенам и стоимости. Кроме Claude Code он понимает историю ещё 27 клиентов — Codex CLI, Gemini CLI, Cursor, Cline, Copilot, Goose, Zed и прочих.
Транскрипты обрабатываются локально, телеметрии проект не заявляет (десктопная версия при этом ходит на GitHub за обновлениями). Режима два: обычное приложение (.dmg, .exe, .AppImage, .deb, .rpm, brew install --cask jhlee0409/tap/claude-code-history-viewer) и headless-сервер, который отдаёт тот же интерфейс в браузер. Дальше — про второй: история у меня живёт на Linux-сервере без иксов. Версия на момент проверки — 1.22.0.
Запуск в Docker
В репозитории есть свой docker-compose.yml, но он собирает бинарь из исходников: Rust, pnpm, webkit-заголовки. Возьмём готовый бинарь из релиза — для x86_64, под ARM64 в релизе лежит отдельный архив:
mkdir cchv && cd cchv curl -fsSLO https://github.com/jhlee0409/claude-code-history-viewer/releases/download/v1.22.0/cchv-server-linux-x64.tar.gz curl -fsSLO https://github.com/jhlee0409/claude-code-history-viewer/releases/download/v1.22.0/CHECKSUMS.sha256 sha256sum -c --ignore-missing CHECKSUMS.sha256
Рядом создаём файл Dockerfile. Распаковывать архив не нужно, ADD делает это сам:
FROM debian:bookworm-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates curl libgtk-3-0 libwebkit2gtk-4.1 libjavascriptcoregtk-4.1-0 \ && rm -rf /var/lib/apt/lists/* ADD cchv-server-linux-x64.tar.gz /usr/local/bin/ ENTRYPOINT ["cchv-server", "--serve", "--host", "0.0.0.0", "--port", "3727"]
Gtk и webkit нужны даже серверному бинарю: это compile-time зависимость Tauri, окно в режиме --serve не открывается. Сборка образа у меня заняла 2 минуты 27 секунд, почти всё — apt.
docker build -t cchv-server:1.22.0 . install -d -m 700 "$HOME/.claude-history-viewer" TOKEN="$(openssl rand -hex 24)" echo "http://127.0.0.1:3727/?token=$TOKEN" docker run -d --name cchv --restart unless-stopped \ --user "$(id -u):$(id -g)" -e HOME=/home/cchv \ -v "$HOME/.claude:/home/cchv/.claude:ro" \ -v "$HOME/.claude-history-viewer:/home/cchv/.claude-history-viewer" \ -p 127.0.0.1:3727:3727 --memory 1g \ cchv-server:1.22.0 --token "$TOKEN"
Второй том — не украшение: туда сервер кладёт токен и туда же складывает архивы (о них ниже). Читать историю остальных клиентов — монтируйте их каталоги отдельно, тоже read-only.
Про токен стоит сказать подробнее, потому что README тут отстал от кода. Он обещает, что при старте печатается полный токен и готовый URL с ?token=.... В 1.22.0 в лог уходят первые восемь символов, а сам токен сохраняется файлом:
🔑 Auth token enabled: 9547b40b... Generated token saved to: /home/cchv/.claude-history-viewer/webui-token.txt
Если домашний каталог смонтирован read-only, записать файл сервер не сможет и напишет Failed to persist generated token. Re-run with --token <value>. Тогда войти нельзя вообще: в логе только восемь символов. Отсюда и --token в примере выше.
Проверяем сервер и открываем напечатанный URL (снаружи — через ssh -L 3727:127.0.0.1:3727 user@host):
$ curl -s http://127.0.0.1:3727/health {"status":"ok"}
Что внутри
Слева дерево проектов и сессий со счётчиками, справа выбранный диалог: сообщения, тулколлы, thinking, дифы, вывод команд с ANSI-цветами. Сабагенты идут отдельными ветками, по правому клику копируются id сессии, путь к файлу и готовая команда claude --resume.
Ctrl+K — поиск сразу по всем провайдерам; в результатах видно, какой сессии принадлежит совпадение.
Отдельный пункт над списком проектов — Global Statistics.

22,5 млрд токенов, 414,8 тыс. сообщений, 9862 сессии, 54 дня чистого времени сессий. Оценка стоимости — 12 824 доллара, если бы это шло по прайсу API. Рядом плашки «Estimated» и «Pricing coverage: 35,4%»: посчитаны только те модели, для которых нашлась цена. Разбивка Billing показывает, что на диалог приходится 68,3% токенов, а 31,7% — на инструменты и системный трафик.
Ниже на той же странице — топ инструментов, топ моделей, heatmap активности по дням и разбивка по скилам и сабагентам с именами.

Дёргать по HTTP
Бэкенд не спрятан: те же команды доступны как POST /api/<имя> с Bearer-токеном. Без токена — честный 401.
curl -s -X POST -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' -d '{}' \ http://127.0.0.1:3727/api/scan_all_projects | jq -r '.[] | [.name, .path, .session_count] | @tsv'
Путь из второй колонки нужен для get_expiring_sessions — это список сессий, которые вот-вот попадут под автоочистку Claude Code (порог по умолчанию — 7 дней, меняется полем thresholdDays):
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \ -d '{"projectPath":"'"$HOME"'/.claude/projects/-home-user-myproject"}' \ http://127.0.0.1:3727/api/get_expiring_sessions | jq -r 'length, ([.[] | select(.daysRemaining <= 1)] | length)'
По одному моему проекту в списке 61 сессия, пять из них уходят в ближайшие сутки. Механика простая: cleanupPeriodDays по умолчанию 30, чистка идёт при старте клиента, и вьюер покажет ровно то, что осталось. Против этого в приложении есть Archive Manager с кнопкой Full Backup — сессии копируются в ~/.claude-history-viewer/archives, куда автоочистка не дотягивается.
Мелочи, на которые я наступил
Официальный
docker-compose.ymlставит лимит памяти 512 МиБ. На моих 8,4 ГБ истории контейнеру не зватает памяти, так что лимит лучше поднять сразу.Первый скан 8,4 ГБ занял около несколько минут, повторные запросы отдаются из кеша за 0,06 с.
30 дней retention по умолчанию — это меньше, чем кажется, рекомендую в настройках поменять на побольше, полезно для анализа и улучшения флоу работы.
Вкладка Recent Edits собирается из транскриптов и в контейнере с одним примонтированным
~/.claudeработает. Рабочие каталоги нужны git-функциям, и для них в образ придётся добавить пакетgit.В server mode интерфейс дёргает
get_startup_session_hintи получает 405 — красная строка в консоли браузера, работе не мешает.Наружу без токена не выставляйте: транскрипты лежат в открытом виде, и всё, что прочитал
Readили напечаталBash, читается в интерфейсе как есть. Для публичного хостинга в 1.14 добавили вход по аккаунту (Argon2id + серверные сессии), read-only-режим и работу за реверс-прокси на подпути.

