Skip to content

sshkeda/lossless-agent-context

Repository files navigation

lossless-agent-context

Lossless session switching between Claude Code, Codex, and Pi.

Each of those tools stores its session context in its own native JSONL shape. This repo converts between them without dropping information, so you can hot-swap a session from one tool to another and keep working.

Install

git clone https://github.com/sshkeda/lossless-agent-context
cd lossless-agent-context
bun install

Usage

# Pi -> Claude Code conversion
bun src/cli/index.ts convert session.jsonl --to claude-code -o claude.jsonl

# Claude Code resume-safe seed
# Also writes claude-seed.jsonl.lossless.json when recovery metadata is needed.
bun src/cli/index.ts prepare-claude-code-resume session.jsonl --from pi -o claude-seed.jsonl

# stdin piping, source auto-detected from the first JSONL line
cat session.jsonl | bun src/cli/index.ts convert - --to codex

# Explicit source
bun src/cli/index.ts convert session.jsonl --from pi --to codex

Providers: pi | claude-code | codex. --from is auto-detected when omitted.

How it works

raw native JSONL  ↔  canonical event model  ↔  raw native JSONL
  (pi/claude/codex)                            (pi/claude/codex)

The canonical model is append-only and provider-agnostic. Exporters take canonical events back to any of the three native shapes.

When going cross-provider (e.g. Pi → Claude Code), exporters embed foreign native line envelopes as __lac_foreign / __lac_canonical fields when the target provider can safely carry them. Claude Code resume seeds are stricter than generic conversion JSONL, so prepare-claude-code-resume writes an adjacent recovery sidecar at <file>.jsonl.lossless.json. Keep that file next to the JSONL when converting back; the CLI reads it automatically for file-based Claude Code imports.

Layout

  • src/cli/lac convert CLI
  • src/core/ — canonical event schema
  • src/adapters/ — Pi / Claude Code / Codex JSONL importers + exporters
  • test/e2e/ — fixture-driven integration tests

Conversion coverage

  • Pi JSONL ↔ canonical
  • Claude Code JSONL ↔ canonical
  • Codex JSONL ↔ canonical
  • Cross-provider export (e.g. Pi → Claude Code) with lossless __lac_foreign / __lac_canonical carry-through
  • Deterministic recovery sidecars (*.lossless.json) for transforms that provider JSONL cannot safely carry directly, such as demoted reasoning markers
  • Native Codex response items including messages, reasoning, function/custom tool calls, web search calls, and image generation calls
  • Semantic Pi → Claude Code export validated by the real @anthropic-ai/claude-agent-sdkgetSessionMessages parses the converted output and returns the original Pi user/assistant chain

Development

bun run check         # typecheck + eslint + prettier
bun run test          # portable fixture-driven test suite
bun run verify:portable  # check + test in series (what CI proves)

Before cutting a release from a machine that has the local CLIs and session stores available, also run the real-log gate:

bun run test:real-logs

test:real-logs reads recent sessions from ~/.pi/agent/sessions, ~/.claude/projects, and ~/.codex/archived_sessions, validates target-native output at each hop, and checks byte-identical same-provider round-trips. Override picked files with LAC_REAL_PI_SESSION / LAC_REAL_CLAUDE_SESSION / LAC_REAL_CODEX_SESSION.

Design standard

Strict native fidelity:

  • provider -> lac -> other format -> lac -> provider must round-trip back to the original native session bytes.
  • This applies uniformly to Claude Code, Codex, and Pi.
  • If a rebuilt provider session is not byte-for-byte identical to the original native session, that is a bug in lac.
  • Provider-specific workarounds that rely on replaying preserved raw files instead of reconstructing them are not the intended end state — reconstruction itself must be lossless.

Current gap: Claude resume seeds are not yet natively lossless. Real experiments showed Claude Code can reject synthetic resume seeds with API Error: 400 due to tool use concurrency issues once enough historical tool_result pairs are preserved. The required fix is exact native fidelity in reconstruction: Claude -> lac -> pi -> lac -> Claude must produce the same native Claude bytes, including historical tool execution state.

License

MIT © 2026 Stephen Shkeda

About

Lossless session switching between Claude Code, Codex, and Pi. Convert JSONL sessions between any two formats without dropping context.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors