How It Works

Session Watcher is a real-time instrumentation layer for Claude Code sessions. It observes the transcript as it grows, derives position and cost metrics per API call, and delivers them to a browser dashboard. This page describes the logical pipeline, the session lifecycle, and why each stage produces correct results.

Pipeline

A single API call flows through these stages:

Claude Code session
    │
    ▼  writes usage rows into a local transcript
┌──────────────────────────────────────────────┐
│  Incremental read                             │
│  Only new bytes since last poll are consumed  │
└──────────────────────────────────────────────┘
    │
    ▼  parse, build branch topology, find active path
┌──────────────────────────────────────────────┐
│  Fold                                         │
│  Deduplicate by message ID (idempotent),      │
│  detect segment boundaries                    │
└──────────────────────────────────────────────┘
    │
    ▼  one valid usage snapshot per API call
┌──────────────────────────────────────────────┐
│  Measurement                                  │
│  ├─ Baseline (B): per-path token accounting   │
│  ├─ Position (L): effective context length    │
│  ├─ Growth (g): smoothed residual rate        │
│  ├─ Settlement: absorb cache-timing noise     │
│  └─ Cost model: dhat, bp, mf from EOQ theory │
└──────────────────────────────────────────────┘
    │
    ▼  assembled status snapshot
┌──────────────────────────────────────────────┐
│  Rate lamp                                    │
│  Integrate rentRate into billing ledger,      │
│  evaluate gate and backstop triggers          │
└──────────────────────────────────────────────┘
    │
    ▼  push to connected clients
┌──────────────────────────────────────────────┐
│  Dashboard                                    │
│  Browser fetches status on each data event,   │
│  renders gauges and history chart             │
└──────────────────────────────────────────────┘

Why this works:

Session Lifecycle

1. Hook (session-start)

Claude Code fires a hook on startup, resume, clear, or compact. The hook discovers the running server, hands it the transcript path, and injects any pending handoff tokens into the session context.

2. Server bootstrap

The MCP entrypoint starts a watcher instance, an HTTP server on a loopback port, and writes a discovery file so that hooks and the statusline can locate it. The server lifecycle is tied to the Claude Code process.

On resume (or any fresh process start with an existing transcript), the watcher replays the transcript from byte zero — reconstructing the full call history, measurement state, and segment boundaries from the file alone. This is how per-call time series data survives a process restart without requiring a separate persistent store for it.

3. Polling

A timer drives the pipeline at regular intervals:

  1. Late resolution — if the transcript did not exist at startup, retry each tick.
  2. Idle gate — skip ticks when no clients are connected and nothing changed recently.
  3. Poll — run the full pipeline (read → fold → measure).
  4. Rate-lamp advance — integrate new samples into the billing ledger.
  5. Broadcast — notify connected browsers that fresh data is available.

4. Segmentation

A segment is a contiguous stretch of context between resets. Boundaries are detected by topology (a new root UUID from /compact or /continue) or by a totalStock drop when no topology is available.

On boundary: finalize settlement, archive the segment for history, and reset all metrics to initial state. This ensures the cost model always reflects the current context, not a mixture of old and new.

5. Session rotation

When Claude Code restarts within a grace window, the hook sends the new session-id. The server archives the current segment, switches to the new transcript, and updates its discovery file.

6. Shutdown

On termination or idle timeout: stop timers, close connections, archive the final segment, and remove the discovery file. Segment archival persists profile summaries to SQLite — enough to reconstruct cross-segment trends but not the full per-call time series, which lives only in the current process memory.

Handoff

When a session ends, the agent can package its working context for the next session. The handoff mechanism bridges the gap between /clear (which destroys in-memory context) and the new session (which starts empty).

  1. The agent selects which file paths and symbols are essential for the next task — guided by the per-path token weights from B. It writes a structured summary (current state and intent, not history) and submits the package. The server persists this alongside a bookmark index: automatically selected conversation turning points that capture the session's work trajectory.

  2. On /clear, the session-start hook fires for the new session. The hook queries persistent storage, finds the undelivered handoff for this project, and injects a reminder into the session context containing the load token, age, and task preview. The load skill reads this reminder and initiates the restore flow.

  3. The load skill extracts the token from the injected reminder, retrieves the handoff package, and reads the kept paths using the cheapest strategy available (symbol line ranges when present, full file otherwise). As these files are read, they flow through the normal pipeline — fold processes them, path attribution adds them to B — so the baseline naturally rebuilds to reflect the carried context. The bookmark index and recent user intents provide orientation: the agent can scan the trajectory of what was built and, when the summary leaves a gap, drill into specific turns for surrounding context.

Why this works