← All @molecule/* packages · App templates
@molecule/api-agent-transcriptCore interface · agent-transcript · API (Node) · v1.0.0 · Apache-2.0
Reads a coding agent's session export (Claude Code, Codex, Molecule IDE) into one normalized session: turns, models and the files the agent wrote
npm install @molecule/api-agent-transcript@molecule/api-agent-transcript is the agent-transcript core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 4 providers: @molecule/api-agent-transcript-autodetect, @molecule/api-agent-transcript-claude-code, @molecule/api-agent-transcript-codex, @molecule/api-agent-transcript-molecule-ide.
import { readFileSync } from 'node:fs'
import { readTranscript, setProvider } from '@molecule/api-agent-transcript'
import { provider } from '@molecule/api-agent-transcript-autodetect'
setProvider(provider)
const session = readTranscript({
text: readFileSync('transcripts/my-post/claude-code-export.txt', 'utf8'),
fileName: 'claude-code-export.txt',
})
for (const turn of session.turns) {
console.log(
turn.role,
turn.model ?? session.model,
turn.text.slice(0, 60),
turn.files.map((f) => f.path),
)
}Providers (4): @molecule/api-agent-transcript-autodetect, @molecule/api-agent-transcript-claude-code, @molecule/api-agent-transcript-codex, @molecule/api-agent-transcript-molecule-ide
Works with: @molecule/api-bond, @molecule/api-i18n
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
One normalized shape for a coding agent's session, whatever harness recorded it.
Defines AgentSession — the turns of a conversation (the user's messages as
typed, the assistant's prose replies, and the files each assistant turn
wrote) — and the AgentTranscriptReader contract that format bonds
implement. Use it to publish, search, audit or attribute what an agent
wrote: @molecule/api-text-provenance takes these sessions to mark which
paragraphs of a document came from the AI.
Readers, one per real export format: @molecule/api-agent-transcript-claude-code
(the /export text and the session .jsonl), -codex (the Markdown export
and the rollout .jsonl), -molecule-ide (a Molecule IDE conversation's
JSON). @molecule/api-agent-transcript-autodetect bundles all three and
picks the one that recognizes each file — bond that unless you only ever
read one format.
import { readFileSync } from 'node:fs'
import { readTranscript, setProvider } from '@molecule/api-agent-transcript'
import { provider } from '@molecule/api-agent-transcript-autodetect'
setProvider(provider)
const session = readTranscript({
text: readFileSync('transcripts/my-post/claude-code-export.txt', 'utf8'),
fileName: 'claude-code-export.txt',
})
for (const turn of session.turns) {
console.log(
turn.role,
turn.model ?? session.model,
turn.text.slice(0, 60),
turn.files.map((f) => f.path),
)
}
core
npm install @molecule/api-agent-transcript @molecule/api-bond @molecule/api-i18n
AgentFileWriteA file the assistant wrote or edited during a turn.
interface AgentFileWrite {
/** The path as the session recorded it (absolute or relative to the session's working directory). */
path: string
/** `create` = the whole file was written; `edit` = part of an existing file was replaced. */
kind: 'create' | 'edit'
/**
* The text the assistant put into the file: the whole file for `create`, the
* inserted/replacement text for `edit`. Empty when the export omits it.
*/
text: string
/** False when the export shows only part of the text (collapsed, truncated or elided). */
complete: boolean
}
AgentSessionA whole session, normalized.
interface AgentSession {
/** The reader that produced it, e.g. `claude-code`, `codex`, `molecule-ide`. */
format: string
/** The harness's own name for itself, e.g. `Claude Code`. */
harness: string
/** The harness version, when the export records it. */
harnessVersion?: string
/** The session's model when a single one is named for the whole session. Per-turn models are on each turn. */
model?: string
/** ISO 8601 start time, when recorded. */
startedAt?: string
/** The turns, in order. */
turns: AgentTurn[]
}
AgentTranscriptReaderThe contract every transcript reader bond implements.
A reader recognizes its own format with detect() and never guesses: it
returns false for anything it does not positively recognize, so a composing
reader (@molecule/api-agent-transcript-autodetect) can try each in turn.
interface AgentTranscriptReader {
/** A stable id for the format family, e.g. `claude-code`. */
readonly format: string
/** A human label, e.g. `Claude Code`. */
readonly label: string
/**
* Whether this reader recognizes the input.
*
* @param input - The transcript.
* @returns True only when the input is positively this reader's format.
*/
detect(input: TranscriptInput): boolean
/**
* Read the transcript into a normalized session.
*
* @param input - The transcript.
* @returns The session.
* @throws {Error} When the input is not this reader's format.
*/
read(input: TranscriptInput): AgentSession
}
AgentTurnOne turn of the conversation. Consecutive assistant messages before the next user message form one turn.
interface AgentTurn {
/** Who spoke. */
role: AgentTurnRole
/**
* What was said. For `user`: the message as typed (the harness's injected
* context is never included). For `assistant`: its prose replies, joined by a
* blank line — tool calls are not prose; the files they wrote are in `files`.
*/
text: string
/** ISO 8601 time of the turn's first message, when the export records it. */
timestamp?: string
/** The model that produced an assistant turn, when the export records it. */
model?: string
/** Files an assistant turn wrote. Always empty for user turns. */
files: AgentFileWrite[]
}
TranscriptInputA transcript to read: its text, and its file name when known (some readers use the extension as a hint).
interface TranscriptInput {
/** The file's full text. */
text: string
/** The file name or path, e.g. `session.jsonl`, `codex-session.md`. */
fileName?: string
}
AgentTurnRoleWho said a turn. Tool calls and their results are folded into the assistant turn that made them.
type AgentTurnRole = 'user' | 'assistant'
canReadTranscript(input)Whether the bonded reader recognizes a transcript.
function canReadTranscript(input: TranscriptInput): boolean
input — The transcript text and, when known, its file name.Returns: True when the bonded reader can read it.
getProvider()Retrieves the bonded transcript reader, throwing if none is configured.
function getProvider(): AgentTranscriptReader
Returns: The bonded reader.
hasProvider()Checks whether a transcript reader is bonded.
function hasProvider(): boolean
Returns: true if a reader is bonded.
readTranscript(input)Read a transcript into a normalized session with the bonded reader.
function readTranscript(input: TranscriptInput): AgentSession
input — The transcript text and, when known, its file name.Returns: The normalized session.
setProvider(provider)Registers a transcript reader as the active one. Called during application startup.
function setProvider(provider: AgentTranscriptReader): void
provider — The reader to bond.| Provider | Package |
|---|---|
| Agent transcript autodetect | @molecule/api-agent-transcript-autodetect |
| Claude Code transcript reader | @molecule/api-agent-transcript-claude-code |
| Codex CLI transcript reader | @molecule/api-agent-transcript-codex |
| Molecule IDE transcript reader | @molecule/api-agent-transcript-molecule-ide |
Peer dependencies:
@molecule/api-bond ^1.0.1@molecule/api-i18n ^1.0.1@molecule/api-bond
@molecule/api-i18n
A user turn is only what the person typed. Harness-injected context (environment blocks, slash-command echoes, platform auto-continue messages, tool results) is dropped by every reader, so a user turn is safe to show as "the prompt".
Assistant text is prose only. Tool calls are not text; the files they
wrote are in turn.files (create = whole file, edit = the replacement
text). Content an agent put in a file counts as the agent's writing.
Exports lose detail, and complete: false says so. Claude Code's
/export renders markdown (headings lose their #, bold loses its **)
and collapses some edits; prefer its session .jsonl when you have it. A
Molecule IDE conversation may elide long file contents.
Readers never guess: detect() is false for anything not positively
recognized, and read() throws on it. Keep the transcript's original file
name when you have it — it is a detection hint.
Parsing is pure and synchronous; nothing is fetched or written.