New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@tangle-network/harness-sessions

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tangle-network/harness-sessions

One reader for every coding-agent harness's native session (Claude Code, Codex, OpenCode, Pi): store layouts, a normalized session with messages, tool calls, served models, usage and ending errors, and projections to chat messages, OTLP spans and turns

Source
npmnpm
Version
0.1.6
Version published
Maintainers
1
Created
Source

@tangle-network/harness-sessions

One reader for every coding-agent harness's native session.

Each harness persists its session in its own store: Claude Code and Pi append JSONL, Codex appends a rollout JSONL, and OpenCode writes SQLite. This package declares each store's layout once and parses each format into one normalized HarnessSession. The session holds the messages, the tool calls with their inputs and results, every model call with the model that served it and its usage, and the error the session ended with.

npm install @tangle-network/harness-sessions

Where this fits

  • The sidecar's harness session contract (agent-container packages/cli-agent-registry) imports STORES and SessionFormatId from here; it keeps no second copy of where a harness writes.
  • The capture path reads captures through listCapture / readCapture.
  • Discovery's trace gate, agent-eval, agent-record and the blog read sessions only through this package.
  • Its only dependencies are @tangle-network/agent-trace-contract and Node built-ins (node:sqlite for OpenCode).

Formats

HarnessFormatStore under HOMEServed model fromUsage
claude-codeclaude-code.projects-jsonl.claude/projects/*/{id}.jsonl, subagents at */{id}/subagents/**/*.jsonlprovider response (message.model)per response, counted once per message.id
codexcodex.rollout-jsonlrollout-*-{id}.jsonl under sessions/ and archived_sessions/ of every Codex home (below)turn context (the configured model)per response (last_token_usage); session total from total_token_usage
opencodeopencode.sqlite.local/share/opencode/opencode.db (shared by every session)session record (providerID/modelID)per step (step-finish)
pipi.session-jsonl.pi/agent/sessions/**/*_{id}.jsonlsession record (provider/model)per assistant message

A HOME can hold several Codex homes, and codexReader.locate reads all of them (codexHomes(home) lists them):

  • .codex and each sibling .codex-<name>;
  • each acct account home, .config/agent-accounts/codex/<account>;
  • home itself when it is a Codex home by its path (isCodexHome), such as a fleet seat's codex directory passed as a store root;
  • for this process's own HOME only, $CODEX_HOME and $ACCT_CONFIG/codex/<account> in place of the default accounts directory. Another HOME, such as an archived host's store root or a capture, is read by its layout alone.

Homes that resolve to one directory count once. A session copied into several homes (acct move) is one ref, its largest copy. A lookup by id takes the rollout whose name ends in the id; when no name does, it reads the session_meta of each rollout modified since the id's UUIDv7 time.

Readers for Kimi, Factory, Gemini, Amp, Qwen, Copilot, Forge, Hermes, Prime and OpenClaw are added with the same real-data proof.

Use

import { readerFor, listCapture, toChatMessages, toOtlpSpans, toTurns } from '@tangle-network/harness-sessions'

// Sessions in a HOME, through the harness's declared store
const reader = readerFor('pi')
for (const ref of await reader.locate('/home/agent')) {
  const summary = await reader.summarize(ref) // constant memory; a 537 MB rollout reads in ~200 MB RSS
  const session = await reader.read(ref)      // full fidelity: nothing is truncated
}

// Sessions in a capture (provider retention layout today, raw-evidence archive v2 when given)
const { sessions, missing } = await listCapture(captureDir)

Projections trim; the reader never does:

  • toChatMessages(session): agent-eval's chat-with-tools messages.
  • toOtlpSpans(session): contract spans (@tangle-network/agent-trace-contract), one LLM span per model call and one TOOL span per tool call.
  • toTurns(session): the blog's turns, with the model, usage and error of each assistant turn.

For callers that are not JavaScript:

harness-sessions read <file|home|capture> [--harness h] [--session id] [--summary] [--json]

Rules the readers keep

  • The served model comes only from the provider response or the session record, never from the profile or the request. A failed request has no served model; requestedModel says which model it was sent to.
  • usage is null when the harness recorded none; it is never reported as zero. input excludes cache reads and cache writes, which have their own fields.
  • A session with zero model calls is not the trace of a turn.
  • locate(home, { cwd }) keeps a session whose recorded cwd is cwd or lies under it on a path boundary (withinPath): /w/agent matches /w/agent/sub, never /w/agent-dev-container. Every store is resolved against the home given; only the Codex environment overrides above depend on the process.
  • An unparsable record is counted in integrity.unparsedRecords and never stops a read (corruption: 'strict' throws instead). A record cut off at the end of a live copy is reported as a torn tail, not as corruption.
  • ending.status is completed, error, aborted or open. open means the records stop mid-turn: the turn was still running or the process died.
  • An OpenCode store is opened read-only where it lies, with no copy: SQLite never writes the store or its write-ahead log. With a log present it reads the log's committed rows and keeps only its own shared-memory index (-shm) current; without one the store is opened immutable and nothing is created beside it. A store SQLite cannot open in place (a log with no -shm in a directory it cannot write, such as a capture on read-only storage, or any store under Node before 22.15, whose node:sqlite takes no URI file names) is read from a private copy. integrity.sourceFiles names the session as <store>#session=<id> with a digest of the rows read for it.

Tests

The fixtures are sessions that the real harness CLIs wrote while talking to the trace-proof scripted model; the tests assert that script. The proof against the readers this package replaces is a comparison over stored sessions, recorded with each release.

FAQs

Package last updated on 16 Oct 2026

Related posts