Packages
relayburn@3.0.0(tag:relayburn-v3.0.0)@relayburn/sdk@3.0.0(tag:sdk-v3.0.0)@relayburn/mcp@3.0.0(tag:mcp-v3.0.0)@relayburn/cli-darwin-arm64@3.0.0(tag:cli-darwin-arm64-v3.0.0)@relayburn/cli-darwin-x64@3.0.0(tag:cli-darwin-x64-v3.0.0)@relayburn/cli-linux-arm64-gnu@3.0.0(tag:cli-linux-arm64-gnu-v3.0.0)@relayburn/cli-linux-x64-gnu@3.0.0(tag:cli-linux-x64-gnu-v3.0.0)@relayburn/sdk-darwin-arm64@3.0.0(tag:sdk-darwin-arm64-v3.0.0)@relayburn/sdk-darwin-x64@3.0.0(tag:sdk-darwin-x64-v3.0.0)@relayburn/sdk-linux-arm64-gnu@3.0.0(tag:sdk-linux-arm64-gnu-v3.0.0)@relayburn/sdk-linux-x64-gnu@3.0.0(tag:sdk-linux-x64-gnu-v3.0.0)
Crates
relayburn-sdk@3.0.0(tag:relayburn-sdk-v3.0.0) — https://crates.io/crates/relayburn-sdk/3.0.0relayburn-cli@3.0.0(tag:relayburn-cli-v3.0.0) — https://crates.io/crates/relayburn-cli/3.0.0
Release Notes
Added
burn overhead deltas: per-inference context-window attribution. New--session,--top,--min-delta,--owner,--explain,--jsonflags surface "what blew up my context between inference N and inference N+1?" — pairs same-railInferencespans, attributes the delta ininput + cache_read + cache_writeto interveningToolResult/UserPrompt/SystemReminderleaves, surfaces compaction events as their own row (never a negative delta), and isolates main-rail deltas from subagent rails. SDK entry point:LedgerHandle::context_delta(opts). (#432)burn flow --session <id>: inference-flow DAG over a session's span
trees. One column per turn on the main rail; dispatched subagents
branch onto their own rails inheriting the dispatching inference's
Y, withdispatch/returnedges between rails andunattached
edges for orphan subagents. Renders Mermaid (default), SVG
(--output flow.svg), and JSON (--json).--max-turnsdefaults
to 50. New SDK surface:LedgerHandle::flow_graph(session, opts)
and free-functionflow_graph_from_trees. (#431)relayburn-sdk: per-turn span tree as derived analytical primitive.
NewLedgerHandle::turn_span_tree(session_id, turn_id)and
session_span_trees(session_id)verbs projectTurnRecord+
tool_result_eventrows + Claude subagent sidecars into an
OTel-styleTurnSpanTree { Turn -> { UserPrompt, Inference -> ToolUse -> { ToolResult, Subagent } } }. Pure projection — no schema change,
no caching. Orphan subagents surface as siblingSubagentspans
withunattached=true. Locked attribute keys (tokens.*,model,
request_id,tool_use_id,agent_id,stop_reason) for
downstream consumers (inference-flow DAG, context-delta attribution).
(#430)relayburn-sdk:ingest_claude_transcript_path(ledger, path, opts)—
per-transcript Claude fast-path used byburn ingest --hook claudeso
the hook ingests only the one JSONL the payload points at instead of a
full sweep.
Changed
relayburn-cli:burn ingest --hook claudenow drives the new
single-transcript fast-path, bounding per-hook cost to one JSONL parse.relayburn-cli:burn ingest --quietis now accepted in default
(one-shot) and--watchmodes (no longer hook-only). Suppresses the
progress spinner, watch banner, and per-tick summaries; one-shot mode
still writes its final summary line to stdout for pipeline capture.relayburn-sdk:Inferenceaggregate keys per-API-call rollups by
(source, session_id, request_id)with merged usage andkind
(reasoning/message/tool-use/mixed). Read via
LedgerHandle::inferences(opts)(free functioninferences()too);
persisted at ingest into the newinferencestable. Falls back to
message_idfor harnesses without arequestId(Codex, opencode,
older Claude). (#434)burn summary: one-lineTurn outcomes: …breakdown of assistant
stop_reasoncounts, plus astopReasonsblock in--json. (#437)- Ledger fingerprint primitive (
{count}:{maxMtimeUnix}:{totalBytes}) for
cheap "did anything change" polling. Exposed asLedgerHandle::fingerprint
on the Rust SDK,sdk.fingerprint()on@relayburn/sdk,
burn state fingerprint [--session | --project]on the CLI, and
burn__fingerprinton the MCP server. OptionalSession(id)/
Project(path)scopes; all-sessions is the default. (#440) burn hotspots: newBytescolumn on the per-tool tables and--rank-by bytesmode rank tools by raw output payload size, so a 4 MB Bash result that got truncated to a small token count still surfaces alongside small-bytes / large-tokens reads. JSON output gainstotalOutputBytes,maxOutputBytes, andtruncatedCounton every aggregation row. (#436)relayburn-sdk:ToolResultEventRecordcarries newoutputBytesandoutputTruncatedfields populated at ingest fromcontent.as_bytes().len()plus Claude truncation-marker detection;ToolAttribution/FileAggregation/BashAggregation/BashVerbAggregation/SubagentAggregationexpose the rolled-uptotal_output_bytes,max_output_bytes, andtruncated_count. (#436)relayburn-sdk: Claude Task subagent sidecar discovery + pairing. Newdiscover_subagents/pair_to_main/count_subagents_underhelpers undercrate::reader::claude::subagentswalk<sessionId>/subagents/agent-*.jsonl, pair each sidecar against the parent'stoolUseResult.agentId, and surface unpaired sidecars (slash-command synthetic dispatches and crash-mid-dispatch) as theUnattachedGroupbucket. Discovery is lazy — the directory is only stat'd when something asks for it. (#435)burn summary: newsubagents: X paired, Y orphanline (and matchingsubagentskey in--json) populated by a lazy walk over~/.claude/projects/. Skipped entirely when no sidecars exist anywhere reachable so pre-#435 outputs stay byte-identical. HonorsBURN_CLAUDE_PROJECTS_DIRfor test sandboxing. (#435)- Ledger schema bumped to v4 — new nullable
turns.subagent_id TEXTcolumn denormalizesTurnRecord.subagent.agent_idso subagent rows are queryable without re-deserializingrecord_json. Migrated in place byALTER TABLE … ADD COLUMN; pre-v4 rows stayNULLand are backfilled byburn state rebuild. (#435) relayburn-sdk: Claude slash-command triads (/review,/init, custom skills) now collapse into one syntheticSkillactivity instead of inflating the activity count three rows at a time. Detection pins on the caveat → invocation → stdout parent-UUID chain shape with<command-name>/<local-command-stdout>purpose checks, so real user prompts that happen to look structurally similar are not misdetected. Token attribution stays on the underlying assistant rows —Skillis a view, not a billing reattribution. NewActivityCategory::Skillvariant anddetect_slash_triadshelper. (#438)relayburn-sdk: Claude Code parser now skips harness-injected
<task-notification>rows when emittingUserTurnRecords. The detector
matches shape AND purpose across three envelope variants
(type: "queue-operation"+ content prefix,origin.kind, and
queued_commandattachment withcommandMode), so a real prompt that
literally types<task-notification>is not filtered. Drops user-turn
inflation from background Bash completions.relayburn-sdk: Claude Code activity classifier now associates each
assistant turn with its user prompt by walking theparentUuidchain
to the nearest user-prompt ancestor, instead of file order. Fixes
mis-classification of late-arriving assistant rows under out-of-order
JSONL flushes and interrupt + resume sessions. Falls back to the
previous file-order map for legacy/malformed rows without UUIDs.
Codex and opencode readers are unaffected — their rollouts don't carry
an equivalent chain field. (#433)- BREAKING
relayburn-sdk:TurnRecord.stop_reasonis now an
Option<StopReason>enum (kebab-case wire form); deserialization is
lenient so pre-3.0 ledgers replay cleanly. (#437) relayburn-sdkledger schema bumps to v3:turnsgains astop_reason TEXTcolumn (#437) andtool_result_eventsgains nullableoutput_bytes
/output_truncatedcolumns (#436). Both are migrated in place on
Ledger::open; existing rows leave the new columnsNULL. Runburn state rebuildto backfill an older ledger.relayburn-sdkledger schema bumps to v5: adds theinferences
derived table for per-API-call aggregates. Created idempotently on
open; rebuilt byburn state rebuild. Pre-v5 ledgers stay empty
until rebuild or the next ingest run. (#434)relayburn-sdk: Claude Code parser now correctly mergesusage
from the carrier row of a multi-block assistant message. Previously,
if the row carrying theusageblock was not the first row for a
givenmessage_id, its tokens were dropped. The new merge adopts
the carrier row's usage values whichever row owns them. (#434)
Package Changelogs
@relayburn/sdk
Added
fingerprint({ session?, project?, ledgerHome? })returns a
{count}:{maxMtimeUnix}:{totalBytes}polling primitive overturns.
Sub-millisecond per session-scope call; suitable for "did anything
change" gates without re-querying or re-ingesting. (#440)
@relayburn/mcp
Added
createFingerprintTool()factory +burn__fingerprinttool wrapping the
SDK's new fingerprint primitive ({count}:{maxMtimeUnix}:{totalBytes}).
Accepts optionalsessionId/projectto scope, mutually exclusive. (#440)