ai newsFr., 16. Okt.
EilmeldungHow to track your brand in Google AI Mode

# Reading the undocumented session logs of Claude Code, Codex and Mistral Vibe

Oct 16, 2026 · @arthur Why read the logs at all Claude Code, Codex and Mistral Vibe all write everything they do to disk, as they do it, and none of them documents the format. If you run a few sessions that spawn sub-agents, those files are the only place that knows which agent is still working, wh

dev.toFreitag 14:50 · 16.10.5 Min. Lesezeit
Bild: dev.to

Claude Code, Codex and Mistral Vibe all write everything they do to disk, as they do it, and none of them documents the format. If you run a few sessions that spawn sub-agents, those files are the only place that knows which agent is still working, which one is waiting on another, and which session is sitting on a prompt for you.

I build Agent Standup, an open-source tool that reads those files and plays each session back as a live call. This article is what I learned reading them: where each tool keeps its sessions, which records matter, how sub-agents show up, and how to keep a reader correct when a format you don't control changes under you. Everything here is read-only: the reader never writes in these folders and never calls a model.

The formats below were checked against real sessions in October 2026: Claude Code 2.1, Codex (desktop app and CLI), and Mistral Vibe 2.26.1. They are undocumented, so treat every field name as something that can change.

Claude Code keeps each session in ~/.claude/projects/<folder>/<session-id>.jsonl. The folder is the project's path with every character that isn't a letter or a digit turned into -, so /Users/me/shop-api becomes -Users-me-shop-api.

Each line is one JSON record, and its type says what it is. user and assistant records carry the conversation. Others you'll meet: custom-title and ai-title (the session's name), system, attachment, queue-operation, pr-link and result.

An assistant message holds a list of content blocks: text, thinking and tool_use (a tool name, an id and its input). A trimmed example:

{ "type": "assistant", "timestamp": "2026-10-15T09:12:03.120Z", "message":{ "id": "msg_01…", "model": "…", "stop_reason": "tool_use", "usage":{ "input_tokens": 12, "output_tokens": 340, "cache_read_input_tokens": 20480, "cache_creation_input_tokens": 512 }, "content":[{ "type": "tool_use", "id": "toolu_01…", "name": "Bash", "input":{ "command": "npm test" }}]}} Enter fullscreen mode Exit fullscreen mode The tool's answer comes back in a later user record, as a tool_result block with the same tool_use_id. Claude Code often writes a structured toolUseResult beside it too, which holds what the text doesn't: a published artifact's link and id, for example.

Codex, both the desktop app and the codex CLI, writes one "rollout" file per thread in ~/.codex/sessions/YYYY/MM/DD/rollout-<time>-<thread-id>.jsonl (or under $CODEX_HOME ). Thread names live separately, in session_index.jsonl. You don't need anything else from the Codex folder.

The first line of every rollout is a session_meta record, and it carries the fields that tell you what the thread is: id, cwd, cli_version, originator, source and, for a child thread, parent_thread_id.

{ "type": "session_meta", "payload":{ "id": "01a1…", "cwd": "/Users/me/shop-api", "cli_version": "…", "source":{ "subagent":{ "other": "guardian" }}, "parent_thread_id": "01a0…" }} Enter fullscreen mode Exit fullscreen mode What I learned:

Vibe keeps its sessions in ~/.vibe/logs/session (or under $VIBE_HOME ), and since version 2.26 it writes them in two different ways depending on the engine. A reader has to handle both, because people still run the old one.

The current engine (the default in 2.26) writes logs/session/unified/<id>/, and it works like an event-sourced store:

So reading a session means loading the snapshot's chunks, then replaying the journal in order. An entry is a message (yours or the agent's), a piece of reasoning, or an "effect": a tool call with its input, its state, its result, and the times it started and ended. Every event has its time, so a replay is exact.

Sub-agents leave no history of their own in this engine. All you know about one is what the lead did with it: subagent.spawn,.send_message,.wait (with the answer it got back) and.stop. You can show who was asked what and what they answered, but not each of their commands.

The earlier engine ( vibe --legacy-harness, and older versions) writes <prefix>_<date>_<time>_<id>/ with a messages.jsonl (one message per line) and a meta.json. Each sub-agent is a session of its own in an agents/ folder inside it, so here you do see a sub-agent's commands. The catch: no message has a timestamp, and the file is saved at the end of each step. Followed live, times are right to within a step; read afterwards, you have to spread the events between the session's start and end.

[embedded content: How Agent Standup reads three tools: three formats, three adapters, one event list, four views]

Each adapter has a small job: turn its tool's records into the same handful of events (something said, something typed, tool calls, their results, token usage, the end of a turn, a compaction). Everything after that is shared: the live call, the board of sessions, the sub-agent tree and the replay. Supporting a fourth tool means writing one adapter, not four features.

The reader is incremental. Each file is parsed once, then only the bytes appended since the last read: the reader keeps an offset per file, plus the last bytes it read. If those bytes are no longer where they were, the file was rewritten rather than appended to, and it's read again from the start. A session is the merge of its main file and one file per sub-agent, each cached on its own, so following a busy session costs a few small reads every couple of seconds, not a full parse.

Three tools, no documentation, and each ships often. What kept the reader honest:

Agent Standup is free and MIT licensed. It's plain Node with no runtime dependencies, and it runs as a VS Code extension (also on Open VSX for Cursor and VSCodium), a terminal command, a desktop app or a Claude Code plugin. To try it with a built-in demo, no install needed (Node 18 or later):

npx @double_geste/agent-standup --open Enter fullscreen mode Exit fullscreen mode The adapters are in the repo ( codex.js, vibe.js, and the Claude Code reader in server.js ), if you want to reuse the parsing for something else.

Three gaps where real sample files would help, with ids and paths redacted:

Issues and samples are welcome at github.com/Atoll92/agent-standup.

Not affiliated with Anthropic, OpenAI or Mistral AI.

Quelle: dev.to (dev.to). Original öffnen