Documentation
¶
Overview ¶
Package transcript reads an AI coding agent's on-disk conversation transcript and renders it to a neutral, agent-agnostic Markdown document.
It supports Claude Code and Codex as source agents. The rendered output is handed to a different agent during an in-place migration (see docs/design/2026-06-24-cross-agent-conversation-migration-design.md) so the new agent can continue the work with the full readable history.
Reading is deliberately defensive: undocumented, drifting formats and partially-written (live) files are tolerated by skipping unparseable lines and counting them, rather than failing.
Index ¶
- Constants
- Variables
- func BuildForkSeedPrompt(srcAgent, contextPath string) string
- func BuildSeedPrompt(srcAgent, contextPath string) string
- func CodexRolloutID(path string) (string, bool)
- func CodexSessionIDSince(root, worktreePath string, since time.Time) (string, bool)
- func LocateCodexSince(worktreePath string, since time.Time) (string, bool)
- func LocateCodexSinceIn(root, worktreePath string, since time.Time) (string, bool)
- func Supported(agent string) bool
- type Conversation
- type RenderKind
- type RenderOptions
- type Role
- type Source
- type ToolCall
- type Turn
- type Usage
Constants ¶
const ( AgentClaude = "claude" AgentCodex = "codex" )
Agent identifiers for supported source transcripts.
Variables ¶
var ErrNoTurns = errors.New("transcript contains no usable turns")
ErrNoTurns is returned by Read when a transcript parsed successfully but contained no usable conversation turns. Callers use this to fail fast before disrupting a running session.
var ErrUnsupportedAgent = errors.New("unsupported source agent for migration")
ErrUnsupportedAgent is returned for source agents without a reader.
Functions ¶
func BuildForkSeedPrompt ¶ added in v0.69.0
BuildForkSeedPrompt is the opening prompt for a cross-agent fork. Unlike a migration (which retains the source's worktree), a fork starts in a FRESH worktree branched from the base branch, so the source session's code changes — both uncommitted edits and commits on its branch — are NOT present on disk. The prompt says so explicitly to stop the new agent assuming they exist.
func BuildSeedPrompt ¶
BuildSeedPrompt is the short instruction passed to the target agent as its opening prompt, pointing it at the rendered context file.
func CodexRolloutID ¶
CodexRolloutID reads a rollout's session_meta id. Exported for the daemon's post-start id capture.
func CodexSessionIDSince ¶ added in v0.59.0
CodexSessionIDSince returns the native session id of the Codex rollout for a cwd created at/after `since`. Unlike LocateCodexSinceIn (newest-by-mtime), it refuses to guess when the (since, cwd) window contains rollouts with two or more DIFFERENT session ids — the concurrent mirror / in-place case — returning ("", false) so the caller falls back to a non-pinned resume rather than cross-assigning another session's conversation. Pass root "" for the daemon default.
func LocateCodexSince ¶
LocateCodexSince returns the newest Codex rollout for a cwd whose mtime is at or after `since`. Used for post-start session-id capture: filtering by start time avoids picking a stale rollout from a prior session in the same cwd (a real hazard for in-place sessions and codex→codex migrations).
func LocateCodexSinceIn ¶ added in v0.59.0
LocateCodexSinceIn is LocateCodexSince scoped to an explicit Codex state root (CODEX_HOME). Pass "" to use the daemon's default root. This matters because the daemon-side scrape runs in the daemon process, but CODEX_HOME can be set per-session via the agent's launch env — reading the daemon's os.Getenv would scan the wrong directory and silently miss the rollout.
Types ¶
type Conversation ¶
type Conversation struct {
SrcAgent string
Turns []Turn
DroppedLines int // unparseable/skipped lines (format drift, partial tail)
}
Conversation is the parsed, normalized transcript.
func Read ¶
func Read(agent, agentSessionID, worktreePath string) (*Conversation, error)
Read locates and parses the transcript for a session. agentSessionID is the id graith tracks for the source agent (used to locate Claude transcripts); worktreePath is the session's working directory (used to locate Codex transcripts and as a fallback). Returns ErrNoTurns if the transcript parsed but yielded nothing usable.
func (*Conversation) Render ¶
func (c *Conversation) Render(opts RenderOptions) string
Render produces the neutral Markdown context document handed to the target agent. Turns are selected newest-first within the size budget but rendered chronologically so the document reads as a narrative.
type RenderKind ¶ added in v0.69.0
type RenderKind int
RenderKind selects the framing of the rendered document's header, which differs between an in-place migration and a cross-agent fork.
const ( // RenderMigrate frames the document for an in-place agent take-over: the // worktree is retained, so prior code changes are already on disk. RenderMigrate RenderKind = iota // RenderFork frames the document for a cross-agent fork: the new agent runs // in a FRESH worktree branched from base, so prior code changes are NOT on // disk and must be re-applied. RenderFork )
type RenderOptions ¶
type RenderOptions struct {
// Kind selects the header framing (migrate vs fork). Defaults to
// RenderMigrate (the zero value).
Kind RenderKind
// MaxBytes is the approximate size budget for the rendered body. When the
// transcript exceeds it, the oldest turns are elided (newest kept). 0 uses
// a default.
MaxBytes int
// MaxToolOutput caps each tool output block. 0 uses a default.
MaxToolOutput int
}
RenderOptions tunes the Markdown output.
type Source ¶ added in v0.69.0
Source is one on-disk transcript file contributing to a session's usage, with the stat fields the daemon fingerprints to decide whether a re-parse is needed (unchanged size+mtime ⇒ reuse the cached Usage without reading).
func Locate ¶ added in v0.69.0
Locate returns every readable transcript file for the current agent of a session, with stat metadata for fingerprinting. It resolves without parsing so the caller can skip a re-read when nothing changed.
Claude resolves to a single file (its transcript is one JSONL keyed by the agent session id). Codex resolves to the single located rollout in v1; summing across a resumed session's multiple rollouts is deferred until the resume append-vs-fork behaviour is confirmed with a real fixture (#644), to avoid over-counting unrelated same-cwd sessions in the meantime. The []Source return keeps that a drop-in extension.
type ToolCall ¶
ToolCall is a single tool invocation and its result, flattened from whatever nested or call-id-linked representation the source agent used.
type Turn ¶
type Turn struct {
Role Role
Text string
Tool *ToolCall // non-nil when Role == RoleTool
SrcAgent string // source agent that produced the turn
}
Turn is one neutral conversation turn.
type Usage ¶ added in v0.69.0
type Usage struct {
Input int64 // fresh, uncached input tokens
Output int64 // completion tokens
CacheCreation int64 // cache-write tokens (Claude only; Codex has no such concept)
CacheRead int64 // cache-hit input tokens
Unclassified int64 // provider aggregate we can't break down (legacy Codex)
// Found reports whether at least one valid usage record was observed. A
// transcript with no usage records yields Found=false — distinct from a
// genuine zero — so callers never present a confident zero for a file they
// couldn't read usage from.
Found bool
// Dropped counts records that were skipped or conflicted (format drift,
// duplicate usage with differing values, un-deduplicatable records). A
// nonzero value flags the total as approximate.
Dropped int
}
Usage is aggregated token usage parsed from one or more transcript files.
The four token categories plus Unclassified are MUTUALLY EXCLUSIVE by construction, so Total() is a real total rather than a sum of overlapping buckets. Each reader is responsible for producing an exclusive breakdown; a provider aggregate that can't be broken down (legacy Codex) lands in Unclassified rather than being misattributed to a semantic category.
See docs/design/2026-07-13-per-session-token-accounting.md.