Guide

Sessions

Typed schemas for the transcript formats, and where each harness writes them.

Where

harness.sessions lists the locations, with scope: "data" and a note where the directory name is derived:

HarnessFormatPath
Claude CodeJSONL~/.claude/projects/<dash-encoded-cwd>/*.jsonl
Codex CLIJSONL, SQLite~/.codex/sessions/, ~/.codex/state_5.sqlite
Gemini CLIJSON~/.gemini/history/<project-id>/
Grok CLIJSONL, JSON, SQLite~/.grok/sessions/<encoded-cwd>/<session-id>/updates.jsonl
OpenCodeSQLite~/.local/share/opencode/opencode.db
PiJSONL~/.pi/agent/sessions/<dash-encoded-cwd>/<timestamp>_<session-id>.jsonl
OMPJSONL, SQLite~/.omp/agent/sessions/<dash-encoded-cwd>/…jsonl, history.db, agent.db
AntigravityProtocol Buffers, JSONL, SQLite~/.gemini/antigravity-cli/conversations/
Mastra CodeSQLite~/.local/share/mastracode/mastra.db
FreebuffJSON, JSONL~/.config/manicode/projects/<project-name>/chats/<timestamp>/
Cursor, Copilot-No known session location

Each harness page has the full list with notes.

Types

Session schemas are types and nothing else. No runtime code, no validators, no dependency:

import type {
  ClaudeSessionEntry,
  ClaudeUserEntry,
  ClaudeAssistantEntry,
  CodexThread,
  CodexLogEntry,
  GeminiConversationRecord,
  OpenCodeSession,
  OpenCodeMessage,
  OpenCodePart,
} from "@agntn/harnesses";

import { readFileSync } from "node:fs";

const entries = readFileSync(path, "utf8")
  .split("\n")
  .filter(Boolean)
  .map((line) => JSON.parse(line) as ClaudeSessionEntry);

for (const entry of entries) {
  if (entry.type === "assistant") {
    entry.message.content; // ClaudeContentBlock[]: text, thinking, tool_use, tool_result
  }
}

Fields whose upstream shape moves between releases are typed unknown on purpose. Narrow them at the call site with what you actually observe; a schema that claims more than the harness promises breaks on the next minor version.

What's covered

  • Claude: ClaudeSessionEntry as a union of user, assistant and summary entries, with content blocks and usage. ClaudeHistoryEntry for history.jsonl.
  • Codex: CodexThread, CodexLogEntry, CodexHistoryEntry.
  • Gemini: GeminiConversationRecord with message records, thoughts, tool call records and token summaries.
  • OpenCode: OpenCodeSession, OpenCodeMessage and the part union: text, reasoning, tool, file, subtask, step start and finish, snapshot, patch, agent, retry, compaction. Plus OpenCodeTodo and OpenCodeProject.

Grok, Pi, OMP, Antigravity, Mastra Code and Freebuff have their locations mapped and no schema yet. If you read one of those formats and have a stable shape, that is the contribution this package wants most.

@agntn/harnesses·MIT license· Paths follow the upstream CLIs and carry their evidence level. This site reads nothing from your machine.