{
  "schemaVersion": 1,
  "updatedAt": "2026-10-15",
  "contracts": [
    {
      "harness": "claude-code",
      "variant": "sessions-current",
      "default": true,
      "stability": "documented-internal",
      "discovery": {
        "roots": ["~/.claude/projects", "$CLAUDE_CONFIG_DIR/projects"],
        "pathTemplate": "projects/<encoded-cwd-or-CLAUDE_CODE_PROJECT_DIR_NAME>/<session-id>.jsonl"
      },
      "container": {
        "format": "jsonl",
        "compression": ["none"]
      },
      "recordDiscriminator": "type",
      "envelopeFields": [
        "type",
        "uuid",
        "parentUuid",
        "sessionId",
        "timestamp",
        "version",
        "cwd",
        "gitBranch",
        "entrypoint",
        "isSidechain",
        "userType",
        "message"
      ],
      "ordering": {
        "basis": "file append order; message records also chain via parentUuid",
        "ordinalMode": "optional"
      },
      "identifiers": [
        "sessionId",
        "uuid",
        "parentUuid",
        "logicalParentUuid",
        "leafUuid",
        "promptId",
        "requestId",
        "agentId",
        "toolUseID",
        "sourceToolAssistantUUID"
      ],
      "usageFields": [
        "message.usage.input_tokens",
        "message.usage.output_tokens",
        "message.usage.cache_creation_input_tokens",
        "message.usage.cache_read_input_tokens",
        "message.usage.server_tool_use",
        "cost-state.modelUsage",
        "cost-state.totalCostUSD"
      ],
      "features": [
        "resume",
        "fork-lineage",
        "subagent-lineage",
        "subagent-sidecars",
        "tool-result-sidecars",
        "compaction",
        "ai-title",
        "custom-title",
        "file-history-snapshots",
        "pr-link",
        "retention",
        "optional-session-persistence",
        "transcript-local-gc"
      ],
      "formatVersionSignal": "version",
      "evidence": [
        "claude-sessions-docs",
        "transcripts-claude-code-code-claude-com-docs-en-claude-directory",
        "compaction-3",
        "claude-subagents-docs",
        "claude-cli-reference-docs",
        "claude-commands-docs",
        "claude-web-docs",
        "memory-claude-code-code-claude-com-docs-en-settings-reference",
        "steering-claude-code-docs-en-agent-sdk-typescript",
        "image-input-docs-0",
        "steering-claude-code-docs-en-agent-sdk-python",
        "claude-hooks-docs",
        "claude-interactive-docs",
        "claude-remote-control-docs",
        "transcripts-claude-code-code-claude-com-docs-en-data-usage"
      ],
      "references": {
        "location": "https://code.claude.com/docs/en/sessions#where-transcripts-are-stored",
        "records": "https://code.claude.com/docs/en/claude-directory#cleaned-up-automatically"
      },
      "notes": [
        "Claude Code says the entry format is internal and can change between versions.",
        "Prompt history (~/.claude/history.jsonl) is a different artifact."
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Each session is saved as `~/.claude/projects/<project>/<session-id>.jsonl`, grouped per working directory: `<project>` is the directory path with every non-alphanumeric character replaced by `-` (names over 200 characters are truncated and given a hash suffix). `CLAUDE_CONFIG_DIR` moves the whole tree off `~/.claude`, and `CLAUDE_CODE_PROJECT_DIR_NAME` (only honoured together with `CLAUDE_CONFIG_DIR`, v2.1.234+) lets you choose the `<project>` folder name yourself.",
          "reference": "https://code.claude.com/docs/en/sessions#where-transcripts-are-stored",
          "evidence": ["claude-sessions-docs", "compaction-3"],
          "notes": [
            "Moving a session with `/cd` relocates its transcript to the new directory's project folder."
          ]
        },
        "format": {
          "status": "partial",
          "answer": "Transcripts are JSONL: one JSON object per line for a message, tool use, or metadata entry, each tagged with a `type` such as `user`, `assistant`, `system`, or `attachment`. Anthropic documents the entry format as internal and says it changes between versions, so for anything durable use `/export`, `claude -p --output-format json`/`stream-json`, or the Agent SDK session functions rather than parsing the files.",
          "reference": "https://code.claude.com/docs/en/sessions#where-transcripts-are-stored",
          "evidence": ["claude-sessions-docs"],
          "notes": [
            "Each message record carries the writing Claude Code `version`, which is the only per-record version signal."
          ]
        },
        "contents": {
          "status": "supported",
          "answer": "The transcript holds the full conversation: every prompt, response, tool call and tool result, plus thinking blocks, per-response token usage, compaction markers (`compact_boundary` with `preTokens`) and summaries, session titles, and other metadata. Large tool outputs and full-size MCP images spill into `<session-id>/tool-results/`, and pre-edit file snapshots for checkpoints live separately in `~/.claude/file-history/<session>/`.",
          "reference": "https://code.claude.com/docs/en/claude-directory#cleaned-up-automatically",
          "evidence": [
            "transcripts-claude-code-code-claude-com-docs-en-claude-directory",
            "claude-subagents-docs"
          ],
          "notes": [
            "Everything is plaintext and unencrypted; a secret printed by a tool ends up in the transcript.",
            "Since v2.1.299 the bytes of @-mentioned PDFs are no longer kept in the transcript."
          ]
        },
        "resume": {
          "status": "supported",
          "answer": "`claude --continue` (`-c`) reopens the most recent session in the current directory, `claude --resume` (`-r`) opens a picker, and `claude --resume <session-id|name|/abs/path/to/file.jsonl>` resumes a specific one; inside a session use `/resume [session]`. Add `--fork-session` (or run `/branch` in-session) to continue in a copy with a new session ID, and `claude -p --resume <id> \"prompt\"` continues one non-interactively.",
          "reference": "https://code.claude.com/docs/en/sessions#resume-a-session",
          "evidence": ["claude-sessions-docs", "claude-cli-reference-docs"],
          "notes": [
            "Flags such as `--mcp-config`, `--settings`, `--plugin-dir` and `--add-dir` are not restored and must be passed again.",
            "Resuming a background session that is still running attaches to it instead (v2.1.285+)."
          ]
        },
        "find": {
          "status": "supported",
          "answer": "`claude --resume` or `/resume` opens a session picker for the current worktree; type to search, `Space` to preview, `Ctrl+R` to rename, `Ctrl+B` to filter by branch, `Ctrl+W` for all worktrees and `Ctrl+A` for every project on the machine. Name sessions with `claude -n <name>` or `/rename` so `claude --resume <name>` finds them, and `claude --from-pr <number|url>` lists sessions linked to a pull request.",
          "reference": "https://code.claude.com/docs/en/sessions#use-the-session-picker",
          "evidence": ["claude-sessions-docs"],
          "notes": [
            "Sessions created with `claude -p`, the Agent SDK, or starting with `/loop` are hidden from the picker and `--continue`, but still resume by ID."
          ]
        },
        "export": {
          "status": "partial",
          "answer": "`/export` copies the current conversation to the clipboard or saves it as a plain-text file (`/export <filename>` writes directly). There is no built-in Markdown, HTML or share link for local CLI sessions; for JSON use `claude -p --output-format json` or read the `.jsonl` file, and only cloud sessions on claude.ai/code can be shared by link with Private/Team/Public visibility.",
          "reference": "https://code.claude.com/docs/en/sessions#export-and-locate-session-data",
          "evidence": ["claude-sessions-docs", "claude-commands-docs", "claude-web-docs"],
          "notes": [
            "`/feedback`, `/bug` and `/share` send a transcript to Anthropic as a report, not as a shareable link."
          ]
        },
        "retention": {
          "status": "supported",
          "answer": "A background sweep deletes transcripts, subagent transcripts and tool-result sidecars older than `cleanupPeriodDays` (default 30, minimum 1; `0` is rejected, so use a large value like `3650` to keep them long). Desktop and Cowork transcripts are kept at any age unless you set `desktopSessionCleanupPeriodDays`. Delete sooner with `claude purge [path]` (`--dry-run`, `--yes`, `--all`; formerly `claude project purge`) or by removing files under `~/.claude/projects/`.",
          "reference": "https://code.claude.com/docs/en/claude-directory#cleaned-up-automatically",
          "evidence": [
            "transcripts-claude-code-code-claude-com-docs-en-claude-directory",
            "memory-claude-code-code-claude-com-docs-en-settings-reference"
          ],
          "notes": [
            "`claude rm <id>` on a background session leaves its transcript on disk.",
            "The sweep is skipped with `claude -p --bare` and pauses if settings can't be parsed."
          ]
        },
        "disable": {
          "status": "supported",
          "answer": "Set `CLAUDE_CODE_SKIP_PROMPT_HISTORY=1` to stop writing transcripts and prompt history in any mode; such sessions can't be resumed. For a single non-interactive run use `claude -p --no-session-persistence`, and in the TypeScript Agent SDK set `persistSession: false`.",
          "reference": "https://code.claude.com/docs/en/claude-directory#plaintext-storage",
          "evidence": [
            "transcripts-claude-code-code-claude-com-docs-en-claude-directory",
            "claude-cli-reference-docs",
            "compaction-3"
          ],
          "notes": [
            "The Python Agent SDK has no `persistSession` option; use the environment variable.",
            "`CLAUDE_CODE_TRANSCRIPT_LOCAL_GC=1` instead trims long `-p`/SDK transcripts past 5 MB after each compaction."
          ]
        },
        "programmatic": {
          "status": "supported",
          "answer": "The Agent SDK exposes `listSessions()`, `getSessionMessages()`, `getSessionInfo()`, `renameSession()`, `tagSession()` and `forkSession()` in TypeScript (`list_sessions()`, `get_session_messages()` and friends in Python), plus `resume`/`forkSession` options and a `sessionStore` adapter for mirroring transcripts to your own storage. From the CLI, `claude -p --output-format json` or `stream-json` returns the result, session ID, usage and cost, and hooks and status line commands receive the live `transcript_path`.",
          "reference": "https://code.claude.com/docs/en/agent-sdk/typescript#listsessions",
          "evidence": [
            "steering-claude-code-docs-en-agent-sdk-typescript",
            "image-input-docs-0",
            "steering-claude-code-docs-en-agent-sdk-python",
            "claude-sessions-docs",
            "claude-hooks-docs"
          ]
        },
        "history": {
          "status": "supported",
          "answer": "Prompt history is a separate file, `~/.claude/history.jsonl`, with one line per typed prompt (text, pasted content, project path, session ID, timestamp); up-arrow recall and `Ctrl+R` search filter it per working directory. It isn't swept by `cleanupPeriodDays` (except under HIPAA configuration), but `claude purge` removes a project's lines and `CLAUDE_CODE_SKIP_PROMPT_HISTORY=1` stops it being written.",
          "reference": "https://code.claude.com/docs/en/claude-directory#kept-until-you-delete-them",
          "evidence": [
            "transcripts-claude-code-code-claude-com-docs-en-claude-directory",
            "claude-interactive-docs"
          ],
          "notes": [
            "Large pastes in recalled prompts are stored in `~/.claude/paste-cache/`, which is swept by age."
          ]
        },
        "subagents": {
          "status": "supported",
          "answer": "Subagent transcripts are written beside the parent at `~/.claude/projects/<project>/<session-id>/subagents/agent-<agentId>.jsonl` (with an `agent-<agentId>.meta.json` sidecar) and are deleted together with the parent session. Forks made with `/branch` or `--fork-session` become ordinary top-level sessions with their own IDs, and SubagentStop hooks receive `agent_transcript_path` pointing at the subagent file.",
          "reference": "https://code.claude.com/docs/en/sub-agents#resume-subagents",
          "evidence": [
            "claude-subagents-docs",
            "transcripts-claude-code-code-claude-com-docs-en-claude-directory",
            "claude-sessions-docs",
            "claude-hooks-docs"
          ],
          "notes": [
            "Compacting the main conversation does not alter subagent transcripts; subagents log their own `compact_boundary` records."
          ]
        },
        "sync": {
          "status": "supported",
          "answer": "Local CLI transcripts stay on your machine by default and `--resume` doesn't list cloud sessions. While Remote Control is connected, the session transcript is also stored on Anthropic servers to sync with claude.ai and the Claude app; cloud sessions on claude.ai/code are stored by Anthropic and can be pulled into a terminal copy with `claude --teleport` or `/teleport`. Transcripts are uploaded only when you send `/feedback`, `/bug` or `/share`, or answer Yes to the optional session-transcript survey (disable with `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1`).",
          "reference": "https://code.claude.com/docs/en/remote-control#connection-and-security",
          "evidence": [
            "claude-remote-control-docs",
            "claude-web-docs",
            "transcripts-claude-code-code-claude-com-docs-en-data-usage",
            "image-input-docs-0"
          ],
          "notes": [
            "Turn Remote Control auto-connect off with `remoteControlAtStartup: false` or `/config`.",
            "Teleport is one-way: work continued in the terminal isn't pushed back to the cloud session."
          ]
        }
      },
      "observedVersion": "2.1.299"
    },
    {
      "harness": "codex",
      "variant": "current",
      "default": true,
      "stability": "source-observed",
      "discovery": {
        "roots": ["$CODEX_HOME/sessions", "$CODEX_HOME/archived_sessions"],
        "pathTemplate": "sessions/YYYY/MM/DD/rollout-YYYY-MM-DDThh-mm-ss-<thread-id>[_<rollout-id>].jsonl[.zst] (archived: archived_sessions/<same filename>, flat)"
      },
      "container": {
        "format": "jsonl",
        "compression": ["none", "zstd"]
      },
      "recordDiscriminator": "type",
      "envelopeFields": ["timestamp", "ordinal", "type", "payload", "metadata"],
      "ordering": {
        "basis": "file-order-or-ordinal",
        "ordinalMode": "optional (written for paginated-history threads; indexed by thread_history_1.sqlite)"
      },
      "identifiers": [
        "session_meta.payload.id (thread id)",
        "session_meta.payload.session_id",
        "rollout_id (filename suffix)",
        "forked_from_id",
        "forked_from_ordinal_exclusive",
        "parent_thread_id",
        "history_base",
        "source.subagent.thread_spawn.parent_thread_id",
        "agent_role",
        "agent_nickname",
        "agent_path",
        "turn_id",
        "response_id"
      ],
      "usageFields": [
        "input_tokens",
        "cached_input_tokens",
        "cache_write_input_tokens",
        "output_tokens",
        "reasoning_output_tokens",
        "total_tokens",
        "model_context_window"
      ],
      "features": [
        "compaction",
        "fork-lineage",
        "resume",
        "subagent-lineage",
        "archive",
        "paginated-history",
        "world-state",
        "inter-agent-communication",
        "token-usage-records",
        "thread-rollback"
      ],
      "formatVersionSignal": "session_meta.payload.history_mode: legacy|paginated",
      "references": {
        "location": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/rollout/src/recorder.rs#L1740-L1762",
        "records": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/history/src/rollout_payload.rs#L30-L72"
      },
      "evidence": [
        "transcripts-codex-codex-rs-rollout-src-recorder-rs",
        "transcripts-codex-codex-rs-history-src-rollout-payload-rs",
        "transcripts-codex-learn-chatgpt-com-docs-reference-troubleshooting",
        "transcripts-codex-codex-rs-rollout-src-rollout-file-name-rs",
        "transcripts-codex-learn-chatgpt-com-docs-config-file-environment-variables",
        "transcripts-codex-codex-rs-state-src-sqlite-rs",
        "transcripts-codex-codex-rs-history-src-lib-rs",
        "transcripts-codex-codex-rs-protocol-src-protocol-rs",
        "transcripts-codex-codex-rs-cli-src-migrate-rollouts-rs",
        "transcripts-codex-codex-rs-rollout-src-policy-rs",
        "transcripts-codex-codex-rs-protocol-src-models-rs",
        "codex-developer-commands-docs",
        "transcripts-codex-learn-chatgpt-com-docs-non-interactive-mode",
        "transcripts-codex-codex-rs-tui-src-resume-picker-rs",
        "codex-appserver-docs",
        "transcripts-codex-codex-rs-rollout-src-session-index-rs",
        "transcripts-codex-codex-rs-tui-src-app-transcript-export-rs",
        "transcripts-codex-codex-rs-thread-store-src-local-archive-thread-rs",
        "transcripts-codex-codex-rs-core-src-session-session-rs",
        "transcripts-codex-codex-rs-message-history-src-lib-rs",
        "transcripts-codex-learn-chatgpt-com-docs-codex-sdk",
        "instructions-codex-learn-chatgpt-com-docs-config-file-config-advanced",
        "memory-codex-codex-rs-config-src-types-rs",
        "transcripts-codex-codex-rs-core-src-agent-control-rs",
        "transcripts-codex-codex-rs-state-migrations-0021-thread-spawn-edges-sql",
        "transcripts-codex-x-rs-app-server-src-request-processors-feedback-processor-rs",
        "delegation-codex-codex-rs-core-src-config-mod-rs"
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Each session is one file at `~/.codex/sessions/YYYY/MM/DD/rollout-<timestamp>-<thread-id>.jsonl`. Files are grouped by date, not by project; the working directory is recorded inside the file and the resume picker filters on it. Archived sessions move to the flat `~/.codex/archived_sessions/` directory. Setting `CODEX_HOME` moves both directories. `sqlite_home` or `CODEX_SQLITE_HOME` only moves the SQLite index databases (`state_5.sqlite`, `thread_history_1.sqlite`).",
          "reference": "https://learn.chatgpt.com/docs/reference/troubleshooting#feedback-and-logs",
          "evidence": [
            "transcripts-codex-learn-chatgpt-com-docs-reference-troubleshooting",
            "transcripts-codex-codex-rs-rollout-src-recorder-rs",
            "transcripts-codex-codex-rs-rollout-src-rollout-file-name-rs",
            "transcripts-codex-learn-chatgpt-com-docs-config-file-environment-variables",
            "transcripts-codex-codex-rs-state-src-sqlite-rs"
          ],
          "notes": ["If `CODEX_HOME` is set, the directory must already exist."]
        },
        "format": {
          "status": "partial",
          "answer": "Each file is JSON Lines. Every record carries `timestamp`, a `type` (`session_meta`, `response_item`, `event_msg`, `turn_context`, `compacted`, `token_usage_record`, `world_state` and others) and a `payload`. Records can also carry `ordinal` and `metadata`. The docs give the location but don't publish a schema, so the format can change between releases. Since 0.158.0, new local threads use `history_mode: \"paginated\"`. Older threads use `legacy`, and `codex migrate-rollouts --apply` converts them. For a stable interface, use the app-server thread APIs.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/history/src/rollout_payload.rs#L30-L72",
          "evidence": [
            "transcripts-codex-codex-rs-history-src-rollout-payload-rs",
            "transcripts-codex-codex-rs-history-src-lib-rs",
            "transcripts-codex-codex-rs-protocol-src-protocol-rs",
            "transcripts-codex-codex-rs-cli-src-migrate-rollouts-rs"
          ],
          "notes": [
            "Cold files may be stored as `.jsonl.zst` when the under-development `local_thread_store_compression` feature is enabled. It is off by default, and Codex reads both forms."
          ]
        },
        "contents": {
          "status": "supported",
          "answer": "The first record, `session_meta`, holds the thread id, cwd, CLI version, model provider, git info, base instructions and lineage fields. Later records include user and assistant messages, reasoning items, every tool call and its output (shell, custom, MCP, web search, image generation), per-turn context and settings, and turn start/complete/abort events. Compaction is recorded as `compacted` records with the summary and replacement history. Token usage is recorded as `token_usage_record` and `token_count` records. Attached images are stored as `input_image` content, either as an inline `image_url` (a data URL) or as an uploaded `file_id`.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/rollout/src/policy.rs#L78-L160",
          "evidence": [
            "transcripts-codex-codex-rs-rollout-src-policy-rs",
            "transcripts-codex-codex-rs-protocol-src-protocol-rs",
            "transcripts-codex-codex-rs-history-src-lib-rs",
            "transcripts-codex-codex-rs-protocol-src-models-rs"
          ],
          "notes": [
            "Reasoning is stored as the model returns it, usually a summary plus encrypted content rather than raw chain of thought.",
            "Since 0.162.0, paginated history caps persisted command output at 64 KiB and truncates oversized MCP results."
          ]
        },
        "resume": {
          "status": "supported",
          "answer": "Run `codex resume` to open a picker, `codex resume --last` to continue the most recent session in the current directory, or `codex resume <SESSION_ID|name>` for a specific one. Add `--all` to search outside the current directory and `--include-non-interactive` to include `codex exec` runs. Inside the TUI, use `/resume`. For scripts, use `codex exec resume --last \"<prompt>\"` or `codex exec resume <SESSION_ID> \"<prompt>\"`. `codex fork`, `codex exec fork` or `/fork` copies a session into a new one.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#codex-resume",
          "evidence": [
            "codex-developer-commands-docs",
            "transcripts-codex-learn-chatgpt-com-docs-non-interactive-mode"
          ],
          "notes": [
            "When the saved working directory differs from the current one, Codex asks which to use. Set `tui.resume_cwd = \"current\"` or `\"session\"` to skip the question; `-C` overrides it."
          ]
        },
        "find": {
          "status": "supported",
          "answer": "`codex resume` and `/resume` open a paginated picker of sessions in the current directory. Type to filter the loaded rows, press Tab to switch the filter to all directories or to archived sessions, and press Ctrl+E to preview a transcript. Give a session a name with `/rename` so `codex resume <name>` can find it. `codex agents` (or `/agents`) lists chats on the shared background server. Programs can call app-server `thread/list`, which supports `searchTerm`, `cwd`, `archived` and source filters.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#codex-resume",
          "evidence": [
            "codex-developer-commands-docs",
            "transcripts-codex-codex-rs-tui-src-resume-picker-rs",
            "codex-appserver-docs",
            "transcripts-codex-codex-rs-rollout-src-session-index-rs"
          ],
          "notes": [
            "Session names are kept in `~/.codex/session_index.jsonl`, an append-only file where the latest entry wins."
          ]
        },
        "export": {
          "status": "partial",
          "answer": "`/export` in the TUI exports the whole conversation as Markdown, either to the clipboard or to a file (`/export session.md`). `/copy` (or Ctrl+O) copies only the latest response. There is no HTML export and no share link for local sessions. To get JSON, copy the rollout `.jsonl` file or read the thread through the app-server API.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#export-a-conversation-with-export",
          "evidence": [
            "codex-developer-commands-docs",
            "transcripts-codex-codex-rs-tui-src-app-transcript-export-rs"
          ],
          "notes": ["Wait for the current turn to finish before running `/export`."]
        },
        "retention": {
          "status": "partial",
          "answer": "Session files are kept until you remove them; Codex never deletes them by age. `codex archive <SESSION>` or `/archive` moves a session to `~/.codex/archived_sessions` and out of the picker, and `codex unarchive` restores it. `codex delete <SESSION>` or `/delete` permanently removes the transcript, its spawned subagent sessions and their metadata; `--force` skips the prompt but only accepts a UUID. Only the separate prompt history file is size-capped, via `history.max_bytes`.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#codex-delete",
          "evidence": [
            "codex-developer-commands-docs",
            "codex-appserver-docs",
            "transcripts-codex-codex-rs-thread-store-src-local-archive-thread-rs"
          ],
          "notes": [
            "If you delete files by hand, the SQLite index in `state_5.sqlite` can keep stale entries until the next listing scan repairs it. `codex delete` keeps both in sync."
          ]
        },
        "disable": {
          "status": "partial",
          "answer": "For non-interactive runs, `codex exec --ephemeral \"<prompt>\"` writes no session file and no state-DB row. App-server clients can pass `ephemeral: true` to `thread/start` or `thread/fork`, and `/side` opens an ephemeral side chat. Interactive `codex` has no ephemeral flag or config setting. `history.persistence = \"none\"` only stops prompt history (`history.jsonl`); session transcripts are still written.",
          "reference": "https://learn.chatgpt.com/docs/non-interactive-mode#basic-usage",
          "evidence": [
            "transcripts-codex-learn-chatgpt-com-docs-non-interactive-mode",
            "transcripts-codex-codex-rs-core-src-session-session-rs",
            "codex-developer-commands-docs",
            "transcripts-codex-codex-rs-message-history-src-lib-rs"
          ],
          "notes": [
            "The config reference describes `history.persistence` as controlling whether session transcripts are saved to `history.jsonl`. In practice it only gates prompt history, not the rollout files under `sessions/`."
          ]
        },
        "programmatic": {
          "status": "supported",
          "answer": "The supported interface is `codex app-server` (JSON-RPC). `thread/list`, `thread/read`, `thread/turns/list` and `thread/items/list` read stored threads without resuming them; `thread/resume`, `thread/fork`, `thread/archive` and `thread/delete` manage them. `codex exec --json` streams JSONL events (`thread.started` with `thread_id`, `item.*`, `turn.completed`) for a live run. The TypeScript and Python SDKs can resume a thread by id, for example `codex.resumeThread(threadId)`. You can also parse the rollout JSONL files directly, but they have no published schema.",
          "reference": "https://learn.chatgpt.com/docs/app-server#threads",
          "evidence": [
            "codex-appserver-docs",
            "transcripts-codex-learn-chatgpt-com-docs-non-interactive-mode",
            "transcripts-codex-learn-chatgpt-com-docs-codex-sdk"
          ],
          "notes": [
            "`codex app-server generate-json-schema` and `generate-ts` (both experimental) emit the protocol types."
          ]
        },
        "history": {
          "status": "supported",
          "answer": "Prompt history for Up/Down recall and Ctrl+R search is a separate file, `~/.codex/history.jsonl`. Each line is `{\"session_id\",\"ts\",\"text\"}` and it holds only your submitted prompts, shared across all sessions. Turn it off with `[history] persistence = \"none\"`, or cap its size with `history.max_bytes`; when the cap is exceeded, the oldest entries are dropped.",
          "reference": "https://learn.chatgpt.com/docs/config-file/config-advanced#history-persistence",
          "evidence": [
            "instructions-codex-learn-chatgpt-com-docs-config-file-config-advanced",
            "transcripts-codex-codex-rs-message-history-src-lib-rs",
            "memory-codex-codex-rs-config-src-types-rs",
            "codex-developer-commands-docs"
          ],
          "notes": [
            "The docs call this file 'session transcripts', but full transcripts live in `~/.codex/sessions/`."
          ]
        },
        "subagents": {
          "status": "supported",
          "answer": "Each subagent gets its own rollout file in the same `~/.codex/sessions/YYYY/MM/DD/` tree. Its `session_meta.source` records `subagent.thread_spawn` with `parent_thread_id`, `depth`, `agent_role` and `agent_nickname`, and the parent-child link is also kept in the `thread_spawn_edges` table in `state_5.sqlite`. Forks are new files with `forked_from_id` set. Auto-review (Guardian) sessions are saved in `sessions/` too. Archiving or deleting a parent also archives or deletes its spawned descendants. Use `/subagents` to open a child thread.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/protocol/src/protocol.rs#L2937-L2952",
          "evidence": [
            "transcripts-codex-codex-rs-protocol-src-protocol-rs",
            "transcripts-codex-codex-rs-core-src-agent-control-rs",
            "transcripts-codex-codex-rs-state-migrations-0021-thread-spawn-edges-sql",
            "codex-developer-commands-docs",
            "codex-appserver-docs"
          ],
          "notes": ["Ephemeral subagents and `/side` chats are not written to disk."]
        },
        "sync": {
          "status": "partial",
          "answer": "Local sessions are not uploaded. They stay under `CODEX_HOME`, which the CLI, the IDE extension and the ChatGPT desktop app's Codex view all share, so `/app` can continue the same saved chat in the desktop app. `codex remote-control` lets another device drive your local background server, but transcripts stay on your machine. Codex Cloud tasks (`codex cloud`) are separate cloud chats. The only upload path is `/feedback`: if you choose to include logs, it attaches the session's rollout files.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#continue-in-the-desktop-app-with-app",
          "evidence": [
            "codex-developer-commands-docs",
            "transcripts-codex-x-rs-app-server-src-request-processors-feedback-processor-rs",
            "delegation-codex-codex-rs-core-src-config-mod-rs"
          ],
          "notes": [
            "ChatGPT Work local-thread sync is a separate ChatGPT Work feature; Codex keeps its own history."
          ]
        }
      },
      "observedVersion": "0.162.1",
      "sourceRevision": "092d3acd6bec3e3a14bdc7e7a2810ab628ab759d",
      "notes": [
        "Rollout JSONL is a harness-owned durable artifact, not a published compatibility API.",
        "Prompt history.jsonl is a different artifact; history.persistence controls only that file."
      ]
    },
    {
      "harness": "cursor-agent",
      "variant": "current",
      "default": true,
      "stability": "live-observed",
      "discovery": {
        "roots": [
          "~/.cursor/chats (moves with CURSOR_CONFIG_DIR, else $XDG_CONFIG_HOME/cursor/chats)",
          "~/.cursor/projects/<workspace-slug>/agent-transcripts (moves with CURSOR_DATA_DIR)"
        ],
        "pathTemplate": "~/.cursor/chats/<md5(absolute workspace path)>/<chatId>/store.db"
      },
      "container": {
        "format": "sqlite",
        "compression": ["none"]
      },
      "recordDiscriminator": "role",
      "envelopeFields": ["id", "role", "content", "providerOptions"],
      "ordering": {
        "basis": "Content-addressed blobs in table blobs(id, data); the conversation is a tree reached from meta.latestRootBlobId (meta table key '0', hex-encoded JSON). A parallel JSONL transcript is append-ordered by line.",
        "ordinalMode": "optional"
      },
      "identifiers": [
        "agentId (chat/session id, also the directory name)",
        "latestRootBlobId",
        "blob id",
        "message id",
        "toolCallId",
        "parent conversation id (subagents/ path in JSONL transcripts)"
      ],
      "usageFields": [],
      "features": [
        "resume",
        "fork",
        "rewind",
        "compaction",
        "rename",
        "subagent-lineage",
        "per-session-prompt-history",
        "cloud-handoff",
        "jsonl-mirror"
      ],
      "formatVersionSignal": "meta.json schemaVersion (per chat directory); none inside store.db or the JSONL",
      "references": {
        "location": "https://cursor.com/docs/cli/reference/configuration#file-location",
        "records": "https://cursor.com/docs/hooks#common-schema"
      },
      "evidence": [
        "transcripts-cursor-agent-cursor-com-docs-cli-reference-configuration",
        "cursor-hooks-docs",
        "cursor-cli-changelog",
        "cursor-cli-using-docs",
        "cursor-cli-overview-docs",
        "cursor-cli-parameters-docs",
        "transcripts-cursor-agent-cursor-com-help-ai-features-shared-transcripts",
        "transcripts-cursor-agent-cursor-com-docs-cli-reference-output-format",
        "cursor-acp-docs",
        "transcripts-cursor-agent-cursor-com-help-security-and-privacy-privacy",
        "transcripts-cursor-agent-cursor-com-docs-enterprise-privacy-and-data-governance"
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "In CLI 2026.10.12 each chat lives in `~/.cursor/chats/<md5 of the absolute workspace path>/<chatId>/` (`store.db`, `meta.json`, `prompt_history.json`), so chats are grouped per directory. A readable JSONL copy is written to `~/.cursor/projects/<workspace path with non-alphanumerics turned into dashes>/agent-transcripts/<chatId>/<chatId>.jsonl`. The chats root follows `CURSOR_CONFIG_DIR` (or `$XDG_CONFIG_HOME/cursor`), and the projects root follows `CURSOR_DATA_DIR`.",
          "reference": "https://cursor.com/docs/cli/reference/configuration#file-location",
          "evidence": [
            "transcripts-cursor-agent-cursor-com-docs-cli-reference-configuration",
            "cursor-hooks-docs"
          ],
          "notes": [
            "Only the config directory override is documented; the chats/ and projects/ layout is how CLI 2026.10.12 behaves on disk."
          ]
        },
        "format": {
          "status": "partial",
          "answer": "The session itself is a SQLite database (`store.db`) with two tables: `meta` (hex-encoded JSON with the chat name, mode, model and root blob id) and `blobs` (content-addressed JSON and protobuf blobs forming a message tree). The JSONL mirror has one object per line: `{\"role\",\"message\":{\"content\":[...]}}` plus `{\"type\":\"turn_ended\",\"status\"}` lines. Neither file format is documented, so treat both as internal and liable to change.",
          "reference": "https://cursor.com/docs/hooks#common-schema",
          "evidence": ["cursor-hooks-docs"],
          "notes": [
            "The documented, stable machine format is the headless `--output-format json|stream-json` stream, not the files on disk."
          ]
        },
        "contents": {
          "status": "partial",
          "answer": "`store.db` keeps the full model context: system prompt, user and assistant messages, tool calls and tool results, reasoning (often stored as redacted reasoning), request ids, and summary archives created by `/summarize` or automatic summarization. The JSONL mirror keeps user and assistant text (with any thinking text), tool calls as `tool_use` name and input, and turn-end status, but not tool results or the system prompt. Per-message token usage is not stored in either file.",
          "reference": "https://cursor.com/docs/hooks#common-schema",
          "evidence": ["cursor-hooks-docs", "cursor-cli-changelog"],
          "notes": [
            "Token counts are available to `afterAgentResponse` hooks at run time, not in the saved session."
          ]
        },
        "resume": {
          "status": "supported",
          "answer": "Run `agent resume` or `agent --continue` (an alias for `--resume=-1`) to reopen the latest chat, `agent --resume <chatId>` to open a specific one, or `/resume` (Ctrl+Y) inside a session. Resume also works with `-p` for headless follow-ups, and `/fork` branches the current chat into a new session.",
          "reference": "https://cursor.com/docs/cli/using#history",
          "evidence": [
            "cursor-cli-using-docs",
            "cursor-cli-overview-docs",
            "cursor-cli-parameters-docs"
          ]
        },
        "find": {
          "status": "supported",
          "answer": "`agent ls` (or `agent --resume` with no id, or `/resume`) opens a picker that lists All chats across workspaces by default, with Created and Last updated columns. Left/Right switches to This workspace. There is no full-text search over CLI chats; `/copy-conversation-id` copies the current chat id.",
          "reference": "https://cursor.com/docs/cli/changelog#jul-6-2026-sessions-and-subagents",
          "evidence": [
            "cursor-cli-changelog",
            "cursor-cli-overview-docs",
            "cursor-cli-parameters-docs"
          ]
        },
        "export": {
          "status": "partial",
          "answer": "The CLI has no export or share command. You can copy the JSONL file under `~/.cursor/projects/<slug>/agent-transcripts/<chatId>/` yourself. Share links (`cursor.com/s/...`) are created from the Cursor editor's chat header and need a Teams or Enterprise plan.",
          "reference": "https://cursor.com/help/ai-features/shared-transcripts#how-do-i-share-a-conversation",
          "evidence": ["transcripts-cursor-agent-cursor-com-help-ai-features-shared-transcripts"],
          "notes": ["`/copy` copies only a previous user message, not the conversation."]
        },
        "retention": {
          "status": "partial",
          "answer": "Local CLI chats have no expiry and are kept until you delete them. In the `agent ls` / `/resume` picker, press Backspace or Delete on a chat and confirm to permanently remove its `~/.cursor/chats/.../<chatId>` folder. You can also delete that folder, and the matching `agent-transcripts/<chatId>` folder, by hand.",
          "reference": "https://cursor.com/docs/cli/overview#sessions",
          "evidence": ["cursor-cli-overview-docs"],
          "notes": [
            "Deleting from the picker removes the chat folder. The JSONL copy under ~/.cursor/projects is a separate file, so check it too."
          ]
        },
        "disable": {
          "status": "unsupported",
          "answer": "There is no flag, setting or environment variable to run without saving the session; every interactive and `-p` run creates a chat under `~/.cursor/chats`. To get a throwaway session, point `CURSOR_CONFIG_DIR` and `CURSOR_DATA_DIR` at a temporary directory (you will need credentials there too) or delete the chat afterwards.",
          "reference": "https://cursor.com/docs/cli/reference/configuration#file-location",
          "evidence": ["transcripts-cursor-agent-cursor-com-docs-cli-reference-configuration"]
        },
        "programmatic": {
          "status": "supported",
          "answer": "Headless runs (`agent -p --output-format json` or `stream-json`) emit a documented NDJSON stream with `session_id`, messages and tool call start/completion events, and you can pass that id back with `--resume`. `agent create-chat` returns a new chat id, hooks receive `transcript_path` (and `CURSOR_TRANSCRIPT_PATH`), and `agent acp` exposes sessions over the Agent Client Protocol, including `session/load`.",
          "reference": "https://cursor.com/docs/cli/reference/output-format#stream-json-format",
          "evidence": [
            "transcripts-cursor-agent-cursor-com-docs-cli-reference-output-format",
            "cursor-hooks-docs",
            "cursor-acp-docs",
            "cursor-cli-parameters-docs"
          ],
          "notes": ["`thinking` events are left out of print-mode output."]
        },
        "history": {
          "status": "supported",
          "answer": "Up-arrow history is per conversation: since June 2026 it is saved in that chat's own `~/.cursor/chats/<hash>/<chatId>/prompt_history.json` (up to 500 entries), separate from `store.db`. An older global `~/.cursor/prompt_history.json` may still exist from earlier versions.",
          "reference": "https://cursor.com/docs/cli/changelog#jun-22-2026-terminal-experience",
          "evidence": ["cursor-cli-changelog", "cursor-cli-using-docs"]
        },
        "subagents": {
          "status": "partial",
          "answer": "Subagent transcripts are written next to their parent at `~/.cursor/projects/<slug>/agent-transcripts/<parentChatId>/subagents/<subagentId>.jsonl`, and the `subagentStop` hook receives the path as `agent_transcript_path`. Completed subagents keep checkpoints so they can be resumed. A `/fork` creates a new independent chat in the same `~/.cursor/chats/<hash>/` folder.",
          "reference": "https://cursor.com/docs/hooks#subagentstop",
          "evidence": ["cursor-hooks-docs", "cursor-cli-changelog"]
        },
        "sync": {
          "status": "partial",
          "answer": "CLI chats are stored only on your machine and are not synced to the Cursor editor, the web or other devices. Your prompts and context still go to Cursor's servers for each model request, and Privacy Mode controls whether that data can be retained or used for training. Prefixing a message with `&` hands the conversation off to a Cloud Agent, which you can then open at cursor.com/agents.",
          "reference": "https://cursor.com/docs/cli/using#cloud-agent-handoff",
          "evidence": [
            "cursor-cli-using-docs",
            "transcripts-cursor-agent-cursor-com-help-security-and-privacy-privacy",
            "transcripts-cursor-agent-cursor-com-docs-enterprise-privacy-and-data-governance"
          ],
          "notes": ["The resume picker can also list your cloud agents next to local chats."]
        }
      },
      "observedVersion": "2026.10.12-d47ca18"
    },
    {
      "harness": "opencode",
      "variant": "1.x",
      "default": false,
      "stability": "source-observed",
      "discovery": {
        "roots": ["~/.local/share/opencode (XDG_DATA_HOME/opencode)"],
        "pathTemplate": "~/.local/share/opencode/opencode.db (tables session, message, part; non-stable channels use opencode-<channel>.db; OPENCODE_DB overrides)"
      },
      "container": {
        "format": "sqlite",
        "compression": ["none"]
      },
      "recordDiscriminator": "message.data.role (user|assistant); part.data.type (text|reasoning|tool|file|step-start|step-finish|patch|snapshot|compaction|subtask|agent|retry)",
      "envelopeFields": [
        "id",
        "session_id",
        "message_id (part only)",
        "time_created",
        "time_updated",
        "data"
      ],
      "ordering": {
        "basis": "message rows ordered by (session_id, time_created, id) with ascending sortable IDs; parts by (message_id, id)",
        "ordinalMode": "optional"
      },
      "identifiers": [
        "session.id (ses_...)",
        "session.parent_id",
        "session.project_id",
        "session.workspace_id",
        "message.id (msg_...)",
        "assistant parentID (user message id)",
        "part.id (prt_...)"
      ],
      "usageFields": [
        "assistant tokens.input",
        "tokens.output",
        "tokens.reasoning",
        "tokens.cache.read",
        "tokens.cache.write",
        "tokens.total",
        "cost",
        "step-finish part tokens/cost",
        "session.tokens_* and session.cost totals"
      ],
      "features": [
        "resume",
        "fork-copy",
        "subagent-lineage",
        "compaction",
        "revert",
        "share-link",
        "export-import",
        "tool-output-truncation",
        "event-log"
      ],
      "formatVersionSignal": "session.version (opencode version that created the session) plus __drizzle_migrations; no per-record schema version",
      "references": {
        "location": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/core/src/database/database.ts#L43-L55",
        "records": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/core/src/session/sql.ts#L22-L98"
      },
      "evidence": [
        "transcripts-opencode-packages-core-src-database-database-ts",
        "transcripts-opencode-packages-core-src-session-sql-ts",
        "opencode-cli-stable-docs",
        "opencode-storage-docs",
        "instructions-opencode-packages-core-src-global-ts",
        "transcripts-opencode-packages-schema-src-v1-session-ts",
        "opencode-tui-docs",
        "transcripts-opencode-opencode-ai-docs-share",
        "opencode-server-docs",
        "instructions-opencode-opencode-ai-docs-config",
        "mcp-opencode-packages-opencode-src-tool-truncate-ts",
        "transcripts-opencode-opencode-ai-docs-sdk",
        "steering-opencode-packages-opencode-src-cli-cmd-run-ts",
        "transcripts-opencode-packages-tui-src-prompt-history-tsx",
        "delegation-opencode-packages-opencode-src-tool-task-ts",
        "transcripts-opencode-packages-opencode-src-session-session-ts"
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Sessions live in one SQLite database at `~/.local/share/opencode/opencode.db` (follows `XDG_DATA_HOME`; `opencode db path` prints it). It is shared by all projects, and each session row carries a `project_id` and `directory` instead of per-project folders. Set `OPENCODE_DB` to an absolute path, or to a name relative to the data dir, to move it. Non-stable release channels use `opencode-<channel>.db` unless `OPENCODE_DISABLE_CHANNEL_DB=1`.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/core/src/database/database.ts#L43-L55",
          "evidence": [
            "transcripts-opencode-packages-core-src-database-database-ts",
            "opencode-cli-stable-docs",
            "opencode-storage-docs",
            "instructions-opencode-packages-core-src-global-ts"
          ],
          "notes": [
            "The Storage section of the troubleshooting docs still describes an older `project/<slug>/storage/` JSON layout that current builds no longer use for sessions."
          ]
        },
        "format": {
          "status": "partial",
          "answer": "SQLite (WAL mode). Sessions are in the `session` table, messages in `message`, and message parts in `part`, with each message or part body stored as a JSON `data` column. The schema is internal and migrated automatically, so for a stable interface use `opencode export` or the server/SDK APIs.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/core/src/session/sql.ts#L22-L98",
          "evidence": [
            "transcripts-opencode-packages-core-src-session-sql-ts",
            "opencode-cli-stable-docs",
            "transcripts-opencode-packages-schema-src-v1-session-ts"
          ]
        },
        "contents": {
          "status": "supported",
          "answer": "Each message records role, agent, model, timing and errors. Assistant messages also record `cost` and token counts (`input`, `output`, `reasoning`, `cache.read`, `cache.write`). Parts record text, reasoning (thinking), tool calls with input/output/status, attached files and images, step-start/step-finish with per-step tokens, patches and snapshots, subtasks, and `compaction` markers. Session rows keep running token and cost totals, plus diff summaries and revert state.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/schema/src/v1/session.ts#L453-L490",
          "evidence": [
            "transcripts-opencode-packages-schema-src-v1-session-ts",
            "transcripts-opencode-packages-core-src-session-sql-ts"
          ],
          "notes": [
            "Very large tool outputs are truncated in the transcript, and the full text goes to `~/.local/share/opencode/tool-output/`, which is cleaned after 7 days."
          ]
        },
        "resume": {
          "status": "supported",
          "answer": "Run `opencode --continue` (`-c`) for the last session or `opencode --session <id>` (`-s`) for a specific one. Add `--fork` to branch into a copy instead. The same flags work on `opencode run` and `opencode attach`. Inside the TUI, `/sessions` (aliases `/resume`, `/continue`) switches sessions.",
          "reference": "https://opencode.ai/docs/cli/#flags",
          "evidence": ["opencode-cli-stable-docs", "opencode-tui-docs"]
        },
        "find": {
          "status": "supported",
          "answer": "Use `/sessions` in the TUI to list and pick one. On the command line, `opencode session list` shows top-level sessions; add `-n <N>` to limit and `--format json` for machine output. There is no built-in full-text search, but you can query the database with `opencode db \"<SQL>\"`.",
          "reference": "https://opencode.ai/docs/cli/#list-3",
          "evidence": ["opencode-cli-stable-docs", "opencode-tui-docs"]
        },
        "export": {
          "status": "supported",
          "answer": "`opencode export [sessionID]` writes the session and all its messages as JSON, and `--sanitize` redacts sensitive transcript and file data. `opencode import <file|share-url>` loads one back. In the TUI, `/export` opens a Markdown transcript in `$EDITOR`. `/share` creates a public `opncd.ai/s/<id>` link and `/unshare` removes it.",
          "reference": "https://opencode.ai/docs/cli/#export",
          "evidence": [
            "opencode-cli-stable-docs",
            "opencode-tui-docs",
            "transcripts-opencode-opencode-ai-docs-share"
          ]
        },
        "retention": {
          "status": "partial",
          "answer": "Sessions are kept indefinitely, with no age-based cleanup. Delete one with `opencode session delete <sessionID>`, which also removes its child sessions, or through `DELETE /session/:id` on the server API. `OPENCODE_DISABLE_PRUNE` only turns off pruning of old tool outputs from the model context, not deletion of stored sessions.",
          "reference": "https://opencode.ai/docs/cli/#delete",
          "evidence": [
            "opencode-cli-stable-docs",
            "opencode-server-docs",
            "instructions-opencode-opencode-ai-docs-config",
            "mcp-opencode-packages-opencode-src-tool-truncate-ts"
          ],
          "notes": ["Shared copies stay on opncd.ai until you `/unshare`."]
        },
        "disable": {
          "status": "partial",
          "answer": "There is no documented no-save mode. Setting `OPENCODE_DB=:memory:` runs against an in-memory database, so sessions disappear on exit, but this also discards all other stored state for that run.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/core/src/database/database.ts#L44-L46",
          "evidence": ["transcripts-opencode-packages-core-src-database-database-ts"]
        },
        "programmatic": {
          "status": "supported",
          "answer": "`opencode serve` exposes an OpenAPI HTTP server with `GET /session`, `GET /session/:id`, `GET /session/:id/children` and `GET /session/:id/message` (returns `{info, parts}[]`). The `@opencode-ai/sdk` client wraps these as `session.list()` and `session.messages()`. `opencode run --format json` streams raw JSON events (`text`, `tool_use`, `reasoning`, `step_start`, `step_finish`, `error`), and `opencode db --format json \"<SQL>\"` queries the database directly.",
          "reference": "https://opencode.ai/docs/server/#messages",
          "evidence": [
            "opencode-server-docs",
            "transcripts-opencode-opencode-ai-docs-sdk",
            "opencode-cli-stable-docs",
            "steering-opencode-packages-opencode-src-cli-cmd-run-ts"
          ]
        },
        "history": {
          "status": "supported",
          "answer": "TUI up-arrow history is separate from transcripts. It is kept in `~/.local/state/opencode/prompt-history.jsonl` (under `XDG_STATE_HOME`), capped at the last 50 entries, with `frecency.jsonl` alongside for file-mention ranking.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/tui/src/prompt/history.tsx#L53",
          "evidence": ["transcripts-opencode-packages-tui-src-prompt-history-tsx"]
        },
        "subagents": {
          "status": "supported",
          "answer": "Subagent (task tool) runs are stored as their own child sessions in the same database, with `parent_id` set to the calling session. You can view them with `GET /session/:id/children` or `session.children()`. Forks (`--fork`, `POST /session/:id/fork`) copy the messages into a new independent session titled `<title> (fork #N)`, with no parent link.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/tool/task.ts#L156-L160",
          "evidence": [
            "delegation-opencode-packages-opencode-src-tool-task-ts",
            "opencode-server-docs",
            "transcripts-opencode-packages-opencode-src-session-session-ts"
          ]
        },
        "sync": {
          "status": "supported",
          "answer": "Transcripts are local unless shared. Sharing uploads the conversation to opncd.ai and keeps it updated. The `share` config key sets the mode: `\"manual\"` (default, use `/share`), `\"auto\"` (also `OPENCODE_AUTO_SHARE=true` or `opencode run --share`), or `\"disabled\"`. `/unshare` deletes the shared copy.",
          "reference": "https://opencode.ai/docs/share/#sharing",
          "evidence": [
            "transcripts-opencode-opencode-ai-docs-share",
            "instructions-opencode-opencode-ai-docs-config",
            "opencode-cli-stable-docs"
          ],
          "notes": [
            "Enterprise deployments can disable sharing, restrict it to SSO, or self-host it."
          ]
        }
      },
      "observedVersion": "1.19.0",
      "sourceRevision": "733b2c627e5aec39cb33cc22373bdce33053ef2c"
    },
    {
      "harness": "opencode",
      "variant": "2.x",
      "default": true,
      "stability": "source-observed",
      "discovery": {
        "roots": ["~/.local/share/opencode (XDG_DATA_HOME/opencode)"],
        "pathTemplate": "~/.local/share/opencode/opencode.db (tables session_v2, session_message; OPENCODE_DB overrides; channel-specific opencode-<channel>.db for non-standard channels)"
      },
      "container": {
        "format": "sqlite",
        "compression": ["none"]
      },
      "recordDiscriminator": "session_message.type (user|assistant|synthetic|system|skill|shell|compaction|idle|agent-switched|model-switched|location-switched)",
      "envelopeFields": ["id", "session_id", "type", "seq", "time_created", "time_updated", "data"],
      "ordering": {
        "basis": "per-session monotonically increasing seq (unique index on session_id, seq)",
        "ordinalMode": "optional"
      },
      "identifiers": [
        "session_v2.id",
        "session_v2.parent_id",
        "session_v2.fork_session_id",
        "session_v2.project_id",
        "session_v2.workspace_id",
        "session_message.id (msg_...)",
        "tool call id"
      ],
      "usageFields": [
        "assistant tokens.input",
        "tokens.output",
        "tokens.reasoning",
        "tokens.cache.read",
        "tokens.cache.write",
        "cost",
        "compaction tokens/cost",
        "session_v2.tokens_* and cost totals"
      ],
      "features": [
        "resume",
        "fork-lineage",
        "subagent-lineage",
        "compaction",
        "revert",
        "idle-turn-markers",
        "export-import",
        "v1-migration",
        "event-sourced"
      ],
      "formatVersionSignal": "session_v2.version (creating opencode version); kv key migration.v1-v2 records the in-place V1 to V2 migration",
      "references": {
        "location": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/cli/src/database-path.ts#L4-L13",
        "records": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/session/sql.ts#L22-L98"
      },
      "evidence": [
        "transcripts-opencode-packages-cli-src-database-path-ts",
        "transcripts-opencode-packages-core-src-session-sql-ts",
        "transcripts-opencode-opencode-ai-v2-docs-troubleshooting",
        "mcp-opencode-opencode-ai-v2-docs-cli",
        "transcripts-opencode-packages-util-src-global-roots-ts",
        "transcripts-opencode-packages-schema-src-session-message-ts",
        "transcripts-opencode-opencode-ai-v2-docs-compaction",
        "opencode-2-0-29-source",
        "transcripts-opencode-packages-tui-src-app-tsx",
        "transcripts-opencode-opencode-ai-v2-docs-sharing",
        "steering-opencode-packages-tui-src-routes-session-index-tsx",
        "instructions-opencode-opencode-ai-v2-docs-api",
        "transcripts-opencode-packages-core-src-tool-output-ts",
        "instructions-opencode-opencode-ai-v2-docs-migrate-v1",
        "transcripts-opencode-packages-tui-src-prompt-history-tsx",
        "delegation-opencode-packages-core-src-tool-plugin-subagent-ts",
        "transcripts-opencode-packages-core-src-session-projector-ts",
        "instructions-opencode-opencode-ai-v2-docs-config"
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Sessions live in the SQLite database `~/.local/share/opencode/opencode.db` (follows `XDG_DATA_HOME`). It is shared by every project, and each session row records its project and directory. `opencode debug paths db` prints the path, and `OPENCODE_DB` overrides it, with relative values resolving under the data directory.",
          "reference": "https://opencode.ai/v2/docs/troubleshooting/#service-files",
          "evidence": [
            "transcripts-opencode-opencode-ai-v2-docs-troubleshooting",
            "mcp-opencode-opencode-ai-v2-docs-cli",
            "transcripts-opencode-packages-cli-src-database-path-ts",
            "transcripts-opencode-packages-util-src-global-roots-ts"
          ]
        },
        "format": {
          "status": "partial",
          "answer": "SQLite. Sessions are in the `session_v2` table and transcript entries in `session_message`, one row per entry with a `type`, a per-session `seq` and a JSON `data` body. The schema is internal: the docs say not to edit the database and to back it up before inspecting it with external tools. Use `opencode session export` or the V2 API for a stable shape.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/session/sql.ts#L22-L98",
          "evidence": [
            "transcripts-opencode-packages-core-src-session-sql-ts",
            "transcripts-opencode-opencode-ai-v2-docs-troubleshooting",
            "transcripts-opencode-packages-schema-src-session-message-ts"
          ],
          "notes": [
            "On first start, 2.x migrates 1.x sessions in place within the same database from the old `session`/`message`/`part` tables into `session_v2`/`session_message`, and also imports any `opencode-next.db`."
          ]
        },
        "contents": {
          "status": "supported",
          "answer": "Entries cover user prompts (text, files, agents, skills), assistant turns whose content is text, reasoning and tool calls (input, output content, status, errors), and shell commands. They also include synthetic and system messages, skill loads, agent/model/location switches, compaction summaries (`summary`, `recent`, `reason`), and `idle` markers ending each turn. Assistant and compaction entries carry `cost` and `tokens` (`input`, `output`, `reasoning`, `cache.read`, `cache.write`), and the session row keeps totals.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/schema/src/session-message.ts#L213-L237",
          "evidence": [
            "transcripts-opencode-packages-schema-src-session-message-ts",
            "transcripts-opencode-opencode-ai-v2-docs-compaction"
          ]
        },
        "resume": {
          "status": "supported",
          "answer": "Run `opencode --continue` (`-c`) for the last session or `opencode --session <id>` (`-s`), which creates the session if the ID does not exist. `opencode run` and `opencode mini` take the same flags plus `--fork`. In the TUI, `/sessions` (aliases `/resume`, `/continue`) picks a session and `/fork` branches the current one.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/cli/src/commands/commands.ts#L376-L398",
          "evidence": [
            "opencode-2-0-29-source",
            "mcp-opencode-opencode-ai-v2-docs-cli",
            "transcripts-opencode-packages-tui-src-app-tsx"
          ]
        },
        "find": {
          "status": "supported",
          "answer": "Use `/sessions` in the TUI, or `opencode session list` for top-level sessions in the current project, newest first. `-n` limits the count (default 100) and `--format json` gives machine output. To search, query the database read-only, for example `sqlite3 \"$(opencode debug paths db)\"`.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/cli/src/commands/commands.ts#L417-L433",
          "evidence": ["opencode-2-0-29-source", "mcp-opencode-opencode-ai-v2-docs-cli"]
        },
        "export": {
          "status": "partial",
          "answer": "`opencode session export [id]` prints the session as JSON (`--sanitize` redacts it), and `opencode session import <file|url>` restores it. In the TUI, `/export` saves a transcript and `/copy` copies it to the clipboard. Share links are not available in 2.x: `/share` reports sharing as unavailable.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/cli/src/commands/commands.ts#L443-L466",
          "evidence": [
            "opencode-2-0-29-source",
            "transcripts-opencode-opencode-ai-v2-docs-sharing",
            "steering-opencode-packages-tui-src-routes-session-index-tsx",
            "instructions-opencode-opencode-ai-v2-docs-api"
          ],
          "notes": [
            "Export and import moved from top-level `opencode export`/`opencode import` in 1.x to the `opencode session` subcommands."
          ]
        },
        "retention": {
          "status": "partial",
          "answer": "Sessions are kept indefinitely, and `opencode uninstall` explicitly keeps session data. Delete a session and its child sessions with `opencode session delete <sessionID>` or the API's `session.remove`. Only spilled tool and shell output files are aged out, after 7 days.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/cli/src/commands/commands.ts#L436-L442",
          "evidence": [
            "opencode-2-0-29-source",
            "mcp-opencode-opencode-ai-v2-docs-cli",
            "instructions-opencode-opencode-ai-v2-docs-api",
            "transcripts-opencode-packages-core-src-tool-output-ts"
          ]
        },
        "disable": {
          "status": "partial",
          "answer": "There is no documented no-save switch. `OPENCODE_DB=:memory:` (accepted by `opencode debug paths`) keeps the database in memory, so nothing persists after the server stops. With the shared background service, it has to be set for a `--standalone` run or for the service itself.",
          "reference": "https://opencode.ai/v2/docs/cli/#paths",
          "evidence": [
            "mcp-opencode-opencode-ai-v2-docs-cli",
            "transcripts-opencode-packages-cli-src-database-path-ts"
          ]
        },
        "programmatic": {
          "status": "supported",
          "answer": "Every client talks to a local background server whose V2 HTTP API includes `session.list`, `session.get`, `session.message.list` (`GET /api/session/{sessionID}/message`), `session.log` and `experimental.session.export`. Use it through the `@opencode/client` package or `opencode api`. `opencode run --format json` emits JSON events. The V1 server API and SDK are not compatible with 2.x.",
          "reference": "https://opencode.ai/v2/docs/api/#session.message.list",
          "evidence": [
            "instructions-opencode-opencode-ai-v2-docs-api",
            "instructions-opencode-opencode-ai-v2-docs-migrate-v1",
            "opencode-2-0-29-source"
          ]
        },
        "history": {
          "status": "supported",
          "answer": "TUI prompt recall is separate from transcripts and kept in `~/.local/state/opencode/prompt-history.jsonl` (last 50 entries), with `frecency.jsonl` next to it. The web/desktop app keeps its own prompt history in app storage.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/tui/src/prompt/history.tsx#L93",
          "evidence": ["transcripts-opencode-packages-tui-src-prompt-history-tsx"]
        },
        "subagents": {
          "status": "supported",
          "answer": "Subagent runs become child sessions in the same `session_v2` table, with `parent_id` set to the calling session, and they report their results back to the parent. Forks are new sessions whose `fork_session_id` and `fork_boundary` point to the source session. `opencode session list` shows only top-level sessions.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/tool/plugin/subagent.ts#L186-L190",
          "evidence": [
            "delegation-opencode-packages-core-src-tool-plugin-subagent-ts",
            "transcripts-opencode-packages-core-src-session-projector-ts",
            "transcripts-opencode-packages-core-src-session-sql-ts",
            "instructions-opencode-opencode-ai-v2-docs-migrate-v1"
          ]
        },
        "sync": {
          "status": "partial",
          "answer": "Transcripts stay in the local database owned by your background server, and 2.x has no session sharing yet. The `share` config key (`manual`/`auto`/`disabled`) is accepted but has no effect. Other devices reach sessions only by connecting to your server, for example with `opencode pair` links or `--server <url>`; nothing is uploaded to a cloud service.",
          "reference": "https://opencode.ai/v2/docs/config/#sharing",
          "evidence": [
            "instructions-opencode-opencode-ai-v2-docs-config",
            "mcp-opencode-opencode-ai-v2-docs-cli"
          ]
        }
      },
      "observedVersion": "2.0.29",
      "sourceRevision": "042d0832f5f3a73eaa039a58a7d565776f6d4290"
    },
    {
      "harness": "opencode",
      "recordDiscriminator": "unknown",
      "envelopeFields": [],
      "ordering": {
        "basis": "unknown"
      },
      "identifiers": [],
      "usageFields": [],
      "features": ["entity-files", "storage-migrations"],
      "formatVersionSignal": "storage/migration numeric marker; storage migration version, not a transcript schema version",
      "variant": "dev-json-df35e84",
      "default": false,
      "stability": "source-observed",
      "sourceRevision": "df35e842f59bc115bb7c0479a8e11f017d443f2c",
      "discovery": {
        "roots": ["<Global.Path.data>/storage"],
        "pathTemplate": "storage/<entity>/<key-components>.json"
      },
      "container": {
        "format": "json-documents"
      },
      "evidence": ["opencode-storage-source"],
      "references": {
        "storage": "https://github.com/anomalyco/opencode/blob/df35e842f59bc115bb7c0479a8e11f017d443f2c/packages/opencode/src/storage/storage.ts#L63-L225"
      },
      "notes": [
        "Source uses project, session, message, part, and session_diff entities.",
        "Superseded: OpenCode 1.x now keeps sessions in the SQLite opencode.db; see the 1.x record."
      ]
    },
    {
      "harness": "pi",
      "variant": "current",
      "default": true,
      "stability": "documented-public",
      "discovery": {
        "roots": ["~/.pi/agent/sessions"],
        "pathTemplate": "~/.pi/agent/sessions/--<cwd with leading separator removed and / \\ : replaced by ->--/<ISO timestamp with : and . replaced by ->_<session-id>.jsonl"
      },
      "container": {
        "format": "jsonl",
        "compression": ["none"]
      },
      "recordDiscriminator": "type",
      "envelopeFields": ["type", "id", "parentId", "timestamp"],
      "ordering": {
        "basis": "append order in file; conversation structure is an id/parentId tree with the active leaf selecting the branch",
        "ordinalMode": "optional"
      },
      "identifiers": [
        "session header id (UUIDv7 by default, or custom via --session-id)",
        "entry id (8-char hex)",
        "parentId",
        "parentSession (header, path of source session for /fork, /clone)",
        "targetId (label, context_edit)",
        "fromId (branch_summary)",
        "firstKeptEntryId (compaction)",
        "message.toolCallId"
      ],
      "usageFields": [
        "input",
        "output",
        "cacheRead",
        "cacheWrite",
        "cacheWrite1h",
        "reasoning",
        "totalTokens",
        "cost.input",
        "cost.output",
        "cost.cacheRead",
        "cost.cacheWrite",
        "cost.total"
      ],
      "features": [
        "in-file-branching",
        "fork-lineage",
        "resume",
        "compaction",
        "branch-summary",
        "context-edit",
        "model-change",
        "thinking-level-change",
        "usage-entries",
        "system-prompt-and-tool-deltas",
        "labels",
        "session-name",
        "custom-entries",
        "custom-messages",
        "thinking",
        "images",
        "tool-calls",
        "auto-migration"
      ],
      "formatVersionSignal": "version field on the type:\"session\" header line (current 3)",
      "references": {
        "location": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#file-location",
        "records": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#entry-types"
      },
      "evidence": [
        "transcripts-pi-packages-coding-agent-docs-session-format-md",
        "memory-pi-packages-coding-agent-docs-sessions-md",
        "steering-pi-packages-coding-agent-docs-settings-md",
        "instructions-pi-packages-coding-agent-docs-environment-variables-md",
        "transcripts-pi-packages-coding-agent-src-core-session-manager-ts",
        "transcripts-pi-packages-coding-agent-src-main-ts",
        "transcripts-pi-packages-coding-agent-docs-message-types-md",
        "pi-docs-1-2-0",
        "instructions-pi-packages-coding-agent-docs-slash-commands-md",
        "steering-pi-packages-coding-agent-docs-keybindings-md",
        "transcripts-pi-g-agent-src-modes-interactive-components-session-selector-ts",
        "steering-pi-kages-coding-agent-src-modes-interactive-interactive-mode-ts",
        "transcripts-pi-packages-coding-agent-src-modes-interactive-session-share-ts",
        "transcripts-pi-packages-coding-agent-src-config-ts",
        "steering-pi-packages-coding-agent-docs-sdk-md",
        "steering-pi-packages-coding-agent-docs-rpc-commands-md",
        "steering-pi-packages-coding-agent-docs-json-md",
        "memory-pi-packages-coding-agent-examples-extensions-subagent-index-ts"
      ],
      "answers": {
        "where": {
          "status": "supported",
          "answer": "Each session is one file at `~/.pi/agent/sessions/--<cwd>--/<timestamp>_<session-id>.jsonl`, grouped into one folder per working directory (the path with `/`, `\\` and `:` turned into `-`). Set `PI_CODING_AGENT_DIR` to move the whole agent directory (sessions go to `<agent-dir>/sessions/`), or pick a session directory with `--session-dir <dir>`, `PI_CODING_AGENT_SESSION_DIR`, or the `sessionDir` setting (CLI beats env beats setting). A custom session directory is flat rather than grouped per project; Pi filters it by the `cwd` in each file's header.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#control-session-storage",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "steering-pi-packages-coding-agent-docs-settings-md",
            "instructions-pi-packages-coding-agent-docs-environment-variables-md",
            "transcripts-pi-packages-coding-agent-src-core-session-manager-ts",
            "transcripts-pi-packages-coding-agent-src-main-ts"
          ],
          "notes": [
            "`sessionDir` is honoured from a project's `.pi/settings.json` even before project trust is granted, so Pi can find that project's sessions.",
            "Run `/session` to see the current session's file path; tool shell commands also get it as `PI_SESSION_FILE`."
          ]
        },
        "format": {
          "status": "supported",
          "answer": "JSONL: the first line is a `{\"type\":\"session\",\"version\":3,...}` header, and every later line is an entry with `type`, `id`, `parentId` and `timestamp`, forming a tree. The format is publicly documented in `docs/session-format.md`. Older version 1 and 2 files are migrated to version 3 automatically when loaded.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#session-version",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "transcripts-pi-packages-coding-agent-docs-message-types-md",
            "transcripts-pi-packages-coding-agent-src-core-session-manager-ts"
          ],
          "notes": [
            "New entry types still appear (for example `context_edit` and `usage`), so parsers should skip unknown types and unknown usage `kind` values."
          ]
        },
        "contents": {
          "status": "supported",
          "answer": "`message` entries store user, assistant, tool-result, bash-execution, custom and system messages, including text, images, thinking blocks (with opaque signatures), tool calls with arguments, and tool outputs. Assistant messages record provider, model, `thinkingLevel`, stop reason and `usage` (input, output, cacheRead, cacheWrite, totalTokens, plus a cost breakdown). Other entry types record model and thinking-level changes, `compaction` summaries (with `tokensBefore`), `/tree` branch summaries, context edits, non-message usage such as cache warming, labels, session names and extension data.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#entry-types",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "transcripts-pi-packages-coding-agent-docs-message-types-md"
          ],
          "notes": [
            "The system prompt and tool list are saved too: the first request writes a full system message, and later changes are saved as deltas.",
            "Compaction and context edits never delete the original entries; the file keeps the full history."
          ]
        },
        "resume": {
          "status": "supported",
          "answer": "Run `pi --continue` (`-c`) to reopen the most recent session for the current folder, `pi --resume` (`-r`) for a picker, or `pi --session <path|id>` to open a file path, exact ID or partial ID. Inside Pi, `/resume` switches sessions and `/import <path>` imports and resumes a JSONL file. `pi --fork <path|id>` starts a new session copied from an existing one, and `--session-id <id>` opens that ID in this project or creates it.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/cli.md#sessions",
          "evidence": [
            "pi-docs-1-2-0",
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "instructions-pi-packages-coding-agent-docs-slash-commands-md",
            "transcripts-pi-packages-coding-agent-src-main-ts"
          ],
          "notes": [
            "If `--session` matches a session from another project, Pi offers to fork it into the current folder instead of opening it."
          ]
        },
        "find": {
          "status": "supported",
          "answer": "`pi --resume` or `/resume` opens a picker for the current folder that can switch to all folders. You can type to search, and use `Ctrl+P` to show paths, `Ctrl+S` to change sort order, `Ctrl+N` to show only named sessions, `Ctrl+R` to rename and `Ctrl+D` to delete. Name sessions with `/name` or `--name` so they're easier to spot, and run `/session` to see the current file, ID, message count, tokens and cost.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#continue-or-switch-sessions",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "steering-pi-packages-coding-agent-docs-keybindings-md",
            "transcripts-pi-g-agent-src-modes-interactive-components-session-selector-ts"
          ],
          "notes": [
            "Session files are plain JSONL, so `grep` across `~/.pi/agent/sessions` also works."
          ]
        },
        "export": {
          "status": "supported",
          "answer": "`/export [path]` writes the session as HTML, or as JSONL if the path ends in `.jsonl` (the JSONL export holds only the current branch). `pi --export <session.jsonl> [output.html]` turns a session file into HTML without starting a session. `/share` uploads the session and gives you a link. If you're signed in to Radius it creates an artifact your Radius organization can see; otherwise it creates a private GitHub gist through `gh` and gives you a `https://pi.dev/session/#<gist-id>` viewer link (change the base with `PI_SHARE_VIEWER_URL`).",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#export-or-share-a-session",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "instructions-pi-packages-coding-agent-docs-slash-commands-md",
            "pi-docs-1-2-0",
            "steering-pi-kages-coding-agent-src-modes-interactive-interactive-mode-ts",
            "transcripts-pi-packages-coding-agent-src-modes-interactive-session-share-ts",
            "transcripts-pi-packages-coding-agent-src-config-ts"
          ],
          "notes": [
            "Exports and shares can contain prompts, command output, file contents and any credentials that appeared in the conversation. Review them before sharing."
          ]
        },
        "retention": {
          "status": "supported",
          "answer": "Pi keeps sessions until you delete them; there's no automatic expiry or retention setting. Delete a session by removing its `.jsonl` file under `~/.pi/agent/sessions/`, or select it in `/resume` and press `Ctrl+D` and confirm. Pi uses the `trash` CLI when it's installed, so the file can be recovered.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#deleting-sessions",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "steering-pi-packages-coding-agent-docs-keybindings-md",
            "transcripts-pi-g-agent-src-modes-interactive-components-session-selector-ts"
          ],
          "notes": [
            "You can't delete the session that's currently open from the picker.",
            "A session file is only created once the session has a user or assistant message, so opening and closing Pi without chatting leaves no file."
          ]
        },
        "disable": {
          "status": "supported",
          "answer": "Start Pi with `--no-session` to keep the session in memory only; nothing is written, and the session can't be resumed after Pi exits. SDK hosts get the same thing with `SessionManager.inMemory()`.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#control-session-storage",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "pi-docs-1-2-0",
            "steering-pi-packages-coding-agent-docs-sdk-md",
            "transcripts-pi-packages-coding-agent-src-main-ts"
          ],
          "notes": [
            "There's no setting that turns persistence off for every run; pass the flag (or a shell alias) each time.",
            "`--no-session` can't be combined with `--fork`."
          ]
        },
        "programmatic": {
          "status": "supported",
          "answer": "The SDK (`@earendil-works/pi-coding-agent`) exports `SessionManager` with `create`, `open`, `continueRecent`, `list`, `listAll`, `forkFrom` and `inMemory`, plus tree and context helpers. `pi --mode json -p` streams a session header and then session events as JSONL on stdout. `pi --mode rpc` offers `get_messages`, `get_entries` (every entry, including abandoned branches and pre-compaction history, with a `since` cursor), `get_tree`, `get_state` (session ID and file), `get_session_stats`, `export_html`, `switch_session` and `fork`.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sdk.md#session-storage",
          "evidence": [
            "steering-pi-packages-coding-agent-docs-sdk-md",
            "steering-pi-packages-coding-agent-docs-rpc-commands-md",
            "steering-pi-packages-coding-agent-docs-json-md",
            "transcripts-pi-packages-coding-agent-src-core-session-manager-ts"
          ],
          "notes": [
            "You can also parse the JSONL files directly; `session-format.md` includes a parsing example."
          ]
        },
        "history": {
          "status": "supported",
          "answer": "Pi doesn't keep a separate prompt-history file. Up-arrow recall (`tui.editor.cursorUp` at the top of the editor, or the unbound `tui.editor.historyPrevious`/`historyNext` actions) cycles through prompts you sent in this run, and it's refilled from the user messages on the active branch when a session is opened or resumed. Your prompt history therefore comes from the session transcript.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/keybindings.md#cursor-movement",
          "evidence": [
            "steering-pi-packages-coding-agent-docs-keybindings-md",
            "steering-pi-kages-coding-agent-src-modes-interactive-interactive-mode-ts"
          ],
          "notes": ["Prompts sent with `--no-session` are forgotten when Pi exits."]
        },
        "subagents": {
          "status": "partial",
          "answer": "Pi has no built-in subagents. `/fork`, `/clone` and `--fork` write a new session file in the same project folder whose header `parentSession` holds the source file's path, while `/tree` branches stay inside the original file. The example `subagent` extension runs each child as `pi --mode json -p --no-session`, so child runs aren't saved as their own sessions.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#sessionheader",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "memory-pi-packages-coding-agent-examples-extensions-subagent-index-ts"
          ],
          "notes": ["Third-party subagent extensions can save child sessions any way they like."]
        },
        "sync": {
          "status": "supported",
          "answer": "Sessions stay on local disk and aren't synced to any cloud or other device. They only leave your machine when you run `/share` (a Radius artifact visible to your organization, or a private GitHub gist) or choose to attach the transcript to a `/bug` report, which uploads to `radius.pi.dev` unless you export the report as a zip instead. To sync across machines yourself, point `--session-dir`, `PI_CODING_AGENT_SESSION_DIR` or `sessionDir` at a synced folder.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#export-or-share-a-session",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "transcripts-pi-packages-coding-agent-src-modes-interactive-session-share-ts",
            "instructions-pi-packages-coding-agent-docs-environment-variables-md"
          ],
          "notes": [
            "`PI_OFFLINE` turns off automatic network activity, but `/share` and `/bug` are things you run yourself."
          ]
        }
      },
      "observedVersion": "1.2.0",
      "sourceRevision": "06a466935536f8c9bcacb2d5efc0fc021be1bdff"
    }
  ]
}
