Agent skill
claude-session-logs
Search and analyze Claude Code session logs stored as JSONL files under ~/.claude/. Use when investigating why an agent didn't reply, reconstructing what happened in a past session, finding a specific message across all sessions, or diagnosing tool-call failures. Covers searching by text, timeline inspection, full transcript reconstruction, and tool-call auditing.
Install this agent skill to your Project
npx add-skill https://github.com/akaihola/skills-akaihola/tree/main/claude-session-logs
SKILL.md
Claude Session Logs
Claude Code records every session as a JSONL file. Each line is a JSON object representing one event: a user message, a streaming assistant token, a tool call, a tool result, or a queue operation. This skill provides two scripts for finding and dissecting those logs.
File locations
~/.claude/projects/<encoded-path>/<session-id>.jsonl # per-project sessions
~/.claude/transcripts/<session-id>.jsonl # other sessions
~/.claude/debug/<session-id>.txt # Claude's own debug log
The project directory name encodes the working directory path: leading / is
stripped and every / is replaced with -. For example the project at
/home/agent/coleaders/conversations/slack-C0AJ5JEJH3P becomes the directory
-home-agent-coleaders-conversations-slack-C0AJ5JEJH3P.
JSONL entry types
type |
What it is |
|---|---|
queue-operation |
Message batch queued/dequeued by a channel plugin. operation is "enqueue" or "dequeue". The content field holds the full prompt text. |
user |
A user turn — either a real message or a tool result. message.content is a string or a list of blocks. |
assistant |
An agent turn — text tokens and/or tool calls. During streaming, each token arrives as its own entry. |
Content block types (inside message.content lists)
Block type |
Key fields |
|---|---|
text |
text — the text chunk |
tool_use |
id, name, input |
tool_result |
tool_use_id, content |
Workflow A — find a message across all sessions
Use search-sessions.py when you have a phrase and need to locate which
session it belongs to.
cd ~/prg/skills-akaihola/claude-session-logs
uv run scripts/search-sessions.py "pystytkö nyt listaamaan"
Sample output:
========================================================================
Session : a01cdfa4-5944-48da-8b2d-15bffab0c923
File : /home/agent/.claude/projects/…/a01cdfa4-….jsonl
Project : /home/agent/coleaders/conversations/slack-C0AJ5JEJH3P
Matches : 2
========================================================================
[ 175] 2026-03-04T12:56 assistant/assistant Yritän uudelleen yksinkertaisemmin: …
[ 176] 2026-03-04T12:56 assistant/assistant QR-koodeista löytyi nämä videot: …
>>> [ 177] 2026-03-04T13:51 queue/enqueue New message batch … pystytkö nyt listaamaan …
[ 178] 2026-03-04T13:51 queue/dequeue
[ 179] 2026-03-04T13:51 user/user New message batch … pystytkö nyt …
Options:
uv run scripts/search-sessions.py "query" --context 5 # more surrounding entries
uv run scripts/search-sessions.py "query" --dir /extra/path
Workflow B — inspect a specific session
Use analyze-session.py once you have the session file path or ID.
Timeline mode (default) — one line per entry, streaming tokens merged
uv run scripts/analyze-session.py a01cdfa4-5944-48da-8b2d-15bffab0c923
# or with full path:
uv run scripts/analyze-session.py ~/.claude/projects/…/a01cdfa4-….jsonl
Consecutive single-token assistant entries are collapsed into one line with a token count suffix so the timeline stays readable.
Transcript mode — full reconstructed conversation
uv run scripts/analyze-session.py a01cdfa4 --mode transcript
Prints each turn as a block. Tool calls show the full input JSON; tool results show up to 500 characters of output.
Tools mode — only tool calls and results
uv run scripts/analyze-session.py a01cdfa4 --mode tools
Useful for quickly auditing what the agent tried to do (installs, file reads, bash commands) and what each tool returned.
Workflow C — read the Claude debug log
Claude writes a verbose debug log alongside every session:
cat ~/.claude/debug/<session-id>.txt | head -200
This log includes model-level details (token counts, stop reasons) not present in the JSONL.
Diagnostic patterns
Why didn't the agent reply?
- Run
search-sessions.pyto find the session. - Run
analyze-session.py --mode transcripton that session and look for<reply>tags in the assistant turns. - Common causes:
- No
<reply>tag at all — agent chose silence; the prompt said the message was not a direct address. - Unclosed
<reply>tag — agent opened<reply>before tool calls but never closed it; the reply extractor's regex found no complete pair. - Empty
full_text— session resumed stale; the hard-mention retry should have caught this (< 3 s elapsed, zero text). ProcessError— session was corrupt; dispatch retried fresh.- Session ends mid-stream — the subprocess crashed; check the debug log.
- No
Reconstructing full_text from multi-turn tool use
dispatch_to_agent concatenates text from all assistant turns.
sdk_consume.py inserts \n\n---\n\n between a text run and the following
text run whenever a tool call appeared in between.
So for a session with the pattern:
Turn 1: text + tool_use → "Opening text"
Turn 2: text + tool_use → "Intermediate text"
Turn 3: text only → "Final answer"
full_text will be:
Opening text
---
Intermediate text
---
Final answer
The <reply> extractor only sends what is inside <reply>…</reply> pairs
(or, after the 2026-03-04 fix, the tail after an unclosed <reply> tag).
Checking whether a reply was actually sent
Search for the agent's name or a unique phrase from the expected response
in the session file of the channel plugin (Slack/Matrix/WhatsApp), not the
Claude session. The channel plugin session records the outgoing send_message
tool call when a reply is dispatched.
Alternatively check the channel plugin's systemd log:
journalctl --user -u pykoclaw-slack -n 100
Look for Agent response sent (reply dispatched) or Agent chose silence
(reply suppressed because _extract_reply returned None).
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
youtube-to-markdown
Convert a YouTube video into clean, readable Markdown using its free auto-generated captions (no paid API needed). Use when the user asks to "convert YouTube video to markdown", "get transcript from YouTube URL", "summarise this video", or wants to turn YouTube subtitles/captions into readable text. Prefer this over youtube-transcription when the video already has auto-generated subtitles — it's free and faster. Accepts YouTube URLs.
brave-search
Search the web using Brave Search API. Use when the user asks to "search the web", "look up current information", "find news about", "research a topic online", "check prices online", or needs up-to-date facts that may not be in the model's training data. Requires BRAVE_SEARCH_API_KEY. Supports structured web results (pages, FAQs, news, videos) and an optional AI summarizer.
verkkokauppa
Search products on the Verkkokauppa.com Finnish webshop. This skill uses the Verkkokauppa search API directly, requiring no browser. Use when the user asks to "search Verkkokauppa", "find products on verkkokauppa.com", "verkkokauppa product search", "check Verkkokauppa prices", or mentions searching the Verkkokauppa store.
clasohlson
Search products on the Clas Ohlson Finland webshop (clasohlson.com/fi/). This skill uses the Voyado Elevate (Apptus eSales) search API directly, requiring no browser. Use when the user asks to "search Clas Ohlson", "find products on clasohlson.com", "clas ohlson product search", "check Clas Ohlson prices", or mentions searching the Finnish Clas Ohlson store.
bauhaus
Search products on the Bauhaus webshop (bauhaus.fi). This skill uses the Algolia search API with automatic key refresh. Use when the user asks to "search Bauhaus", "find products on bauhaus.fi", "bauhaus product search", "check Bauhaus prices", or mentions searching the Bauhaus store.
library
Didn't find tool you were looking for?