Session activity

SessionActivity

A session’s transcript lifted into turns, tool uses, and edits.

Usage

Source

SessionActivity(
    session_id,
    turns,
)

Attributes

session_id: SessionId

The Claude session UUID, the only session key.

turns: tuple[Turn, …]
The session’s turns, indexed by position.

Example

>>> activity = SessionActivity.from_session(session_id)
>>> activity.edits_before(anchor, lookback_turns=40)

Attributes

Name Description
edits Every edit in the session, in chronological order.
edits

Every edit in the session, in chronological order.

edits: tuple[Edit, …]

Methods

Name Description
edits_after() Edits to file_path after anchor, oldest-first.
edits_before() Edits in the lookback window before anchor, newest-first.
from_events() Lifts parsed events into turns.
from_session() Discovers, parses, and lifts session_id’s transcript from disk.
turn_of() The turn containing ref’s event.
edits_after()

Edits to file_path after anchor, oldest-first.

Usage

Source

edits_after(anchor, *, file_path, lookahead_turns)

Covers the rest of the anchor turn plus the lookahead_turns turns after it. A compacted-away anchor yields ().

edits_before()

Edits in the lookback window before anchor, newest-first.

Usage

Source

edits_before(anchor, *, lookback_turns)

Covers the lookback_turns turns strictly before the anchor’s turn plus edits earlier in the anchor turn itself. A compacted-away anchor yields ().

from_events()

Lifts parsed events into turns.

Usage

Source

from_events(session_id, events, *, user_classifier=native_user_classifier)

Each event for which user_classifier returns True opens a new turn; everything else folds into the current one. Events before the first qualifying prompt form turn 0 with prompt "".

from_session()

Discovers, parses, and lifts session_id’s transcript from disk.

Usage

Source

from_session(session_id, *, user_classifier=native_user_classifier, root=None)
Parameters
session_id: SessionId

The session to load.

user_classifier: UserClassifier = native_user_classifier

Decides which user events open turns.

root: Path | None = None
The projects directory to search; defaults to ~/.claude/projects.
Raises
TranscriptExpiredError
When no transcript for session_id exists on disk — Claude Code prunes them after roughly thirty days.
turn_of()

The turn containing ref’s event.

Usage

Source

turn_of(ref)
Returns
Turn | None

The turn, or None when the event is gone — a reference compacted

away inside a still-living transcript. Never raises for a miss.

ActivityLift

A session’s lift that grows with its transcript.

Usage

Source

ActivityLift(session_id, *, user_classifier=native_user_classifier)

Each extend() folds the events appended since the previous call into the activity lifted so far: closed turns are kept, the open turn grows by the appended events alone, and a tool use whose result arrives in the tail is re-paired wherever it sits. The result always equals SessionActivity.from_events() over every event fed so far. A step costs the appended events, the tool uses they re-pair, and copies of the turn tuple and of the open turn’s event and tool-use tuples; it never re-derives the session.

Feed only the events appended since the previous call: nothing checks provenance, so events fed twice lift twice. The contract is append-only: a cursor’s transcript is assumed never rewritten behind the events it has been fed, and a transcript rewritten in place, rather than appended to, needs a new cursor. Claude Code and Codex transcripts satisfy it.

The classifier is read once, at construction, and must be deterministic and event-only: its answer for an event has to stay the same as later events are appended, since turns lifted under it are never revisited.

Example

>>> lift = ActivityLift(session_id)
>>> activity = lift.extend(events)
>>> lift.extend(appended) == SessionActivity.from_events(session_id, [*events, *appended])

True

Attributes

Name Description
activity Everything lifted so far.
session_id The session being lifted.
user_classifier Decides which user events open turns.
activity

Everything lifted so far.

activity: SessionActivity

session_id

The session being lifted.

session_id: SessionId

user_classifier

Decides which user events open turns.

user_classifier: UserClassifier

Methods

Name Description
extend() Lifts events, appended after everything fed so far, into activity.
extend()

Lifts events, appended after everything fed so far, into activity.

Usage

Source

extend(events)

Turn

One prompt-to-prompt span of a session.

Usage

Source

Turn(index, prompt, started_at, ended_at, events, tool_uses)

Attributes

index: int

The turn’s position in the session, starting at 0. Events before the first qualifying prompt form turn 0 with prompt "".

prompt: str

The user text that opened the turn.

started_at: datetime | None

The first timestamp among the turn’s events, or None when no event carries one.

ended_at: datetime | None

The last timestamp among the turn’s events, or None when no event carries one.

events: tuple[TranscriptEvent, …]

Every transcript event in the turn, in file order.

tool_uses: tuple[ToolUse, …]
Every tool invocation lifted from the turn’s assistant events, in order.

Attributes

Name Description
edits The turn’s file modifications: one entry per edited file (every file of an
edits

The turn’s file modifications: one entry per edited file (every file of an

edits: tuple[Edit, …]

apply_patch), in order.

ToolUse

One tool invocation lifted from a turn’s assistant events.

Usage

Source

ToolUse(ref, call, result, result_ts, edits, turn_index, ts)

Attributes

ref: EventRef

The resolvable reference to the tool-use block.

call: ToolCall | FallbackCall

The typed tool call, constructed once at lift time.

result: ToolResultBlock | None

The matching result block, or None when none ever arrived.

result_ts: datetime | None

The timestamp of the user entry carrying the result, or None when no result ever arrived.

edits: tuple[tuple[str, tuple[Hunk, …]], …]

The call’s lowered (file_path, hunks) entries, one per edited file.

turn_index: int

The index of the turn the call fired in.

ts: datetime
The timestamp of the assistant entry carrying the call.

Attributes

Name Description
duration_ms Milliseconds from the call to its result, or None without a result.
typed_result The result parsed into the typed result hierarchy, or None without a result.
duration_ms

Milliseconds from the call to its result, or None without a result.

duration_ms: int | None

typed_result

The result parsed into the typed result hierarchy, or None without a result.

typed_result: ToolResult | FallbackResult | None

The join point for ~cc_transcript.tools.parse_tool_result(): pairs this use’s tool name with its result block’s tool_use_result payload, degrading to ~cc_transcript.tools.OtherResult on any shape drift.

Edit

A file modification lowered from an edit-shaped tool call.

Usage

Source

Edit(file_path, hunks, tool, ref, turn_index, ts)

Attributes

file_path: str

The file the call targeted.

hunks: tuple[Hunk, …]

The before/after content pairs, in application order.

tool: str

The tool name exactly as invoked.

ref: EventRef

The resolvable reference to the originating tool use.

turn_index: int

The index of the turn the edit happened in.

ts: datetime
The timestamp of the assistant entry carrying the call.

UserClassifier

Decides which ~cc_transcript.models.UserEvent objects open a turn.

UserClassifier=Callable[["UserEvent"], bool]

native_user_classifier()

Whether a user event is a real prompt under native Claude Code semantics.

Usage

Source

native_user_classifier(event)

A prompt is non-meta, non-sidechain, not a compact summary, not an interruption marker, not an agent-injected relay banner, and not tool-result-only — it must carry real text.

hunk_overlap()

The fraction of a.new’s non-empty lines present in b.old.

Usage

Source

hunk_overlap(a, b)

Lines are whitespace-normalized — stripped, internal runs collapsed — before comparison, and lines empty after normalization are ignored.

Returns

float
A value in [0.0, 1.0]; 0.0 when a.new has no non-empty lines.

result_index()

Indexes tool results by the id of the tool use they answer.

Usage

Source

result_index(events)

Pairs each ~cc_transcript.models.ToolResultBlock with the timestamp of the UserEvent carrying it, keyed by the block’s tool_use_id — the single source for joining a call to its result and deriving the call’s duration.

Returns

dict[ToolUseId, tuple[ToolResultBlock, datetime | None]]

A mapping from tool-use id to a (result block, result timestamp)

pair.