app_sessions table, summarised on-device, classified against your tickets, and folded into the same per-task totals you see on the dashboard. The result is that “an agent shipped this while you were at lunch” is visible, attributed to a ticket, and quoted in your worklog draft — without you doing anything.
When this applies
This pipeline is dormant unless a supported coding agent is present on the machine. Meridian probes for each agent’s on-disk store and CLI at daemon startup. If none of those exist, the indexer and summariser stay idle and log “dormant” — installing Meridian on a machine without any of these agents has no effect until you add one.Supported agents
Meridian ingests conversations from the following agents, each through a dedicated source adapter that normalises its native on-disk format into the same internal record shape. Everything downstream of the adapter — segmentation, sealing, summarising, classification — is agent-blind.
The shape of each row in
app_sessions is the same across every agent. You can filter to coding-agent rows with claude_session_uuid IS NOT NULL (the column name is historical — it carries the session UUID for every agent, not just Claude).
What gets captured
Each session becomes one or more segments, where each segment is a row inapp_sessions with the following distinguishing fields:
Coding-agent rows live in the same table as screen sessions, so every existing query, every MCP tool, and the dashboard timeline all see them automatically. See Sessions for the rest of the schema.
Session names
Most agents name their sessions — automatically after the first exchange, or via a custom title the user sets — and Meridian writes that name intowindow_titles using the canonical [{"window_name": "...", "count": 1}] shape. The dashboard session list and the classifier read coding-agent rows exactly like screen-capture rows as a result. Agents that do not name their sessions (Codex, Copilot CLI) store an empty window_titles array; placeholders like Cursor’s New Agent are filtered out.
A name that appears after the first exchange (Cursor names a chat once a reply arrives) refreshes the live row; sealed rows stay immutable.
Segmenting a long transcript
A single transcript can run for hours, so Meridian splits it into segments using two rules:- An idle gap longer than one hour between turns opens a new segment.
- A one-hour time-box caps each segment, but the cut only happens at the next real user prompt — so a segment always ends on a complete assistant turn and the next one opens on a user message.
(claude_session_uuid, segment_started_at) pair is the unique key. Re-running the indexer on the same store produces the same rows; there is no DELETE-then-INSERT.
The SessionEnd hook
Claude Code supports aSessionEnd hook that fires the instant a session closes. Meridian’s installer registers one entry into ~/.claude/settings.json that invokes the meridian coding-agent-hook subcommand with the transcript path on stdin. The hook seals exactly one session, exits in under 100 ms, and always returns 0 — a misbehaving hook can never block Claude.
The installer merges into your existing settings.json. Other hooks you have configured are left untouched, and re-running the installer is idempotent: the existing Meridian entry is replaced, nothing else is touched.
./install.sh runs this for you on a fresh setup. The other agents (Codex, Copilot, Cursor) have no equivalent hook, so their sessions are caught by the daemon’s source-adapter sweep on the next indexer tick.
The hook is the 99% happy path for Claude Code. The in-daemon indexer is the backstop for everything else — it seals settled rows that the hook missed (Claude crashes, force-quit, machine sleep), polls the other agents’ stores, and re-parses changed conversations to refresh the live tail of any in-flight session.
The lifecycle
Each coding-agent row walks one column —task_method — through its life. You can query the column directly to see where a session is in the pipeline.
Per-agent summarisation
The summariser routes each session to the engine that knows the agent best, with the on-device MLX server as the shared fallback when every primary engine fails or is rate-limited:
All engines target the same schema, so downstream consumers cannot tell which engine produced a given summary except by reading
summary_source. A primary engine that is rate-limited short-circuits to MLX immediately; if both the primary and MLX are down, the row is left pending and retried on the next sweep.
The session-summary skill
The Claude engine invokes claude -p /session-summary, which expects a Claude Code command file at ~/.claude/commands/session-summary.md. Without it, every Claude Code session silently falls back to MLX — you lose the higher-quality, subscription-priced summary for no visible reason.
Install or repair the skill file with:
meridian doctor checks for the file at startup and warns when it is missing; meridian doctor --fix auto-installs it.
Supervised vs autonomous agent time
A coding-agent session can overlap with your own foreground screen time (you were watching Claude work in another pane) or run entirely while you were away from the keyboard (the agent kept going during lunch). Meridian splits the agent’s wall-clock time into two slices so the dashboard can label each one honestly:- Supervised agent time — the intersection of agent intervals with your active foreground presence. This is AI-assisted work you were doing.
- Autonomous agent time — the agent intervals that ran while you were not present (no foreground session, or a
user_idlegap). This is the slice that lifts a task above your hands-on hours.
your_time + autonomous_agent_time, with autonomous time labelled + Xm agent while you were away.
Role in the worklog pipeline
The worklog ledger reads the sameapp_sessions rows but treats coding-agent segments specially:
- An unsettled coding-agent row (
task_methodincoding_agent_live,pending_summariser, orpending_classifier) blocks its hour from being drafted, so the worklog never quotes a transcript that hasn’t been summarised and classified yet. - A settled row (
mlx_directwith atask_key) contributes itssession_summaryas evidence to the worklog draft for that ticket. - A dead-lettered row (
subprocess_error) is skipped, so a single oversized transcript never blocks the rest of the hour.
Configuring and operating
Most users do not need to touch the pipeline. If you do:--day <YYYY-MM-DD> against coding-agent-summarise to backfill a specific day on demand.
meridian doctor reports the state of every supported agent — which CLIs are on PATH, which stores exist, whether cursor-agent needs cursor-agent login, and whether the session-summary skill is installed — and meridian doctor --fix resolves the auto-fixable findings.
Privacy
Coding-agent transcripts are read from your own local stores (~/.claude, ~/.codex, ~/.copilot, ~/.cursor, and the relevant VS Code storage directories). Summaries are generated either by your local agent CLI (using your existing subscription) or by the on-device MLX server. The transcript itself is never sent to any remote service by Meridian — only the ticket update you have configured (Jira, GitHub, or Linear) leaves your machine, and only after the row has been classified and the worklog ledger decides to draft.
Next steps
Sessions
The shared
app_sessions schema that coding-agent rows live in.Task Classification
How sessions — including coding-agent segments — get linked to a Jira, GitHub, or Linear ticket.
CLI Reference
Full reference for
meridian coding-agent-hook, coding-agent-install-skill, coding-agent-summarise, and related subcommands.Dashboard
Where supervised and autonomous agent time appear on the timeline and per-task views.