Skip to content

Watching a session as it runs

Two commands keep generated output current while Claude Code is still writing to a transcript.

Markdown (or HTML) on disk

claude-code-log watch

With no arguments this watches the project for the current directory — which is what you want when running it alongside a live session. It converts once up front, then re-converts whenever a transcript changes. Anything that reloads files picks the changes up: an editor, Obsidian, a browser refresh.

For an Obsidian vault:

claude-code-log watch -f md -o ~/vault/claude

A tick regenerates only the session that changed, so a vault indexer sees one file move, not the whole projection.

Obsidian auto-updates, but doesn't auto-scroll, so expect something like this:

The served page, updating itself

claude-code-log serve --watch

Open a session page and it grows as messages arrive — roughly a second behind the CLI, without a reload. Your scroll position, folded sections and open disclosures all survive, and new messages fade in.

A follow button (⏬) joins the buttons down the right-hand edge once the page is being served. Click it to keep the page pinned to the newest message; while you are not following, it shows a count of how many have arrived since you last looked.

It is the session pages that track a live session. Watch ticks leave the combined pages alone, for the same reason watch defaults to --combined no: regenerating them is what forces a tick to reload the whole project rather than just the session that grew. The combined pages written at startup stay on disk and keep serving — they simply stop tracking the live session until you restart. Their "View All Sessions" back-link keeps working throughout — it points at a page that exists and is still served, just one that stopped growing.

Sub-agents update while they run, not only when they finish: a synchronous agent's transcript grows in its own file while the session waits for it, and each tick picks that up. With --theme minimal (see Themes) the branch layout follows along — lanes you interleaved or put in a column stay that way across updates, a sub-agent that has not returned yet is drawn as running (its lane carries on to the newest message with an open end and a pulsing running label) and turns into an ordinary merge when its result arrives, and a rewind adds its fork lane without moving the main line. An agent waiting on something slow — a background process, a watcher — keeps reading as running however long it takes; once it has been silent for a minute its label says for how long (running · quiet 42m). "Running" needs a live page: a page opened from file:// (or a session nothing has moved in for over a week) shows such an agent as having ended without a result instead, and so does one the session stopped with TaskStop.

In either theme, a message-type filter or a search you have set also applies to messages as they arrive, without moving you to the newest match.

To follow the combined page live as well, run claude-code-log watch --combined yes (with the same --theme) beside serve: the server serves whatever is on disk, and that watch keeps the combined page current.

This works only over the server. A page opened from file:// cannot fetch anything at all — not even itself — so it stays static, exactly as before. Nothing about the generated HTML changes.

This is how following a session looks like:

What "real-time" can and cannot mean here

It cannot show tokens arriving. Claude Code writes a transcript entry exactly once, when the message is complete — it never rewrites a line, so there is no partial message on disk to display. The finest granularity available anywhere in this tool is one whole message, appearing promptly after it finishes. The fade-in is there to make that arrival legible, not to imitate streaming.

Everything else follows from that. A message typically appears within a second or so of completing: the watcher waits briefly for the burst of entries in a turn to settle (a turn writes several), converts, and the page notices on its next poll.

Tuning

Flag Default What it does
--interval 0.25 Seconds between filesystem polls
--quiet-period 0.3 Wait for changes to settle before converting
--max-latency 2.0 Convert anyway after this long, so a long unbroken stream still surfaces
--all-projects off Watch the whole archive instead of one project
--combined no no keeps ticks cheap: only the changed session is regenerated
--theme $CLAUDE_CODE_LOG_THEME, else default HTML theme: classic (current look), minimal, or default (the built-in default, currently classic). Also on serve

Raise --quiet-period if conversions feel too frequent on a large project; lower --interval if you want changes noticed sooner.

Switching --theme rewrites every page in the new theme on the first tick — including a combined page that --combined no would otherwise leave alone, so its session pages never link back into a page of the other theme. Later ticks are cheap again.

Cost

A tick re-converts only what changed. On a 319 MB, 217-file archive a tick is about a second; on a small project it is hundredths of a second. While nothing is changing, the browser's poll is a HEAD for the page's own metadata — about a millisecond, and no body — and the watcher is a stat of the project directory. The page is re-fetched in full only once that metadata says it moved.