agent-canonical
v0.2.1
Published
Canonical session/transcript schemas and per-CLI transcript-format knowledge for AI coding agents (claude-code, codex, opencode, cursor, gemini, qwen, kilo, goose, cline, copilot)
Downloads
1,377
Maintainers
Readme
agent-canonical
One package that owns the canonical session shape and every piece of per-CLI transcript-format knowledge for AI coding agents, so no consumer vendors or re-implements format knowledge and copies cannot drift.
Install
npm install agent-canonicalzod is a peer dependency (^4.4.3). The package ships compiled ESM with type
declarations, one entry per subpath export — e.g.
import { … } from "agent-canonical/schemas".
Subpath exports
agent-canonical/schemas— zod schemas + inferred types for the canonical entities:Session(live CLI instance) wrappingTranscript(recorded messages / tool calls / lossless tier), plusSettingsandArtifactstubs. No runtime dependency besides zod (peer,^4.4.3).agent-canonical/dialects— pure-data descriptors, one per supported CLI (claude-code, codex, opencode, cursor, gemini, qwen, kilo, goose, cline, copilot): transcript store locations, turn-end signals, config paths, capability flags, and an optionalvalidatedAgainstprovenance record (the CLI version(s) and store schema version a captured session confirmed the parser against). Zero dependencies.agent-canonical/materializers— bounded Codex rollout-family discovery and deterministic verbatim source plans. A family starts at one exact root rollout and contains every captured transitive child linked byparentSessionId. Each selected JSONL file is limited to 64 MiB and the complete family to 256 MiB. Unrelated rollouts do not consume the family byte budget. A successfulspawn_agentresult without its child rollout fails closed, as do malformed JSONL and orphan, reordered, or contradictory child-start records. Unknown but valid JSON records are preserved. Token totals retain missing-field coverage by session ID instead of silently treating missing values as zero. This version does not materialize Claude Code workflows, Cursor sessions, or OpenCode databases.agent-canonical/parsers/<cli>— one entry per CLI (claude-code, codex, opencode, cursor, gemini, qwen, kilo, goose, cline, copilot) turning that CLI's on-disk transcript store into a canonicalSession. Layered: a pure event decoder + a pure session reducer per dialect, withparseSessionFile(and, for the SQLite dialects,parseSessionFromDb/listSessionIdsover a structural DB handle — nobetter-sqlite3import) as thin shells. Kilo Code is an OpenCode fork whosekilo.dbhas an OpenCode-compatible reader shape, so the kilo entry reuses opencode's DB shell + reducer and only varies the stamped identity (cli/id-prefix/patch name). Goose keeps a single globalsessions.dbwith a serde{type,…}-tagged content union and cross-row tool correlation, so its entry is a genuinely new decoder + reducer. Cline writes Anthropic-nativemessages-contract-v1content across two per-session JSON files, a genuinely new file-based decoder. GitHub Copilot CLI writes a typedevents.jsonlevent stream per session ({type, data, id, timestamp, parentId}lines, cross-event tool correlation bytoolCallId), another genuinely new file-based decoder. Every fallible call returnsParseResult<T>({success, data, issues} — nevernull, never throw-by-default). Golden tests use synthetic or capture-derived fixtures whose identifiers and provenance are explicit placeholders.
Every dialect supports full-store parsing. Claude Code, Codex, OpenCode, and Cursor also export
snapshotCursor / readEventsSince because their stores provide a reliable live event boundary.
Gemini, Qwen, Kilo, Goose, Cline, and Copilot are full-store-only. Gemini and Qwen advertise
turnEnd.kind: "unavailable", so live consumers can select a bounded fallback instead of treating
an intermediate record as turn-end. Kilo has an explicit on-disk turn-end signal, Goose and Cline
a derived one, and Copilot an explicit one (assistant.turn_end + session.shutdown), but each of
these entries exposes only the full-store parser pair.
The opencode, kilo, and goose parsers take a structural DB handle instead of importing
better-sqlite3, so no subpath resolves a native module; native deps always stay external. The
cline and copilot parsers read plain JSON / JSONL files, so they have no native dependency either.
Goose's transcriptStore.root is the human-readable <Goose data dir>/sessions, not a fixed
home-relative path. Goose 1.43's path helper resolves that data directory from XDG on current
Unix/macOS installs, %APPDATA%\Block\goose\data on Windows, or <GOOSE_PATH_ROOT>/data when
the override is set. Older macOS installs may retain
~/Library/Application Support/Block/goose/data for compatibility.
