Field Manual
Session Stores
Session stores hold continuity: prompts, tool records, local state, memory, and resume metadata that can tie a timeline together.
Why it matters
Without session stores, an investigation may see final files but miss the sequence of decisions and tool actions that produced them.
Evidence to look for
- Session IDs
- Conversation JSONL or databases
- Workspace paths
- Tool-call transcripts
- Resume markers
- Local agent memory
Common pitfalls
- Running tools that rotate or compact sessions
- Collecting only visible chat export
- Sharing raw stores that contain secrets
Session store formats by agent
Each agent uses a different storage format and directory structure. Understanding these differences is essential for locating, preserving, and parsing session evidence.
Codex CLI session store
Codex stores sessions as JSONL files organized by date. Each session file contains a session_meta header followed by event_msg records. Codex maintains three session directories: active sessions, archived sessions, and headless sessions.
Artifact Paths
Active sessions
~/.codex/sessions/YYYY/MM/*.jsonl JSONL files organized by year and month.
Archived sessions
~/.codex/archived_sessions/*.jsonl Completed sessions moved from active.
Headless sessions
~/.codex/headless/*.jsonl Non-interactive agent runs.
{"type":"session_meta","timestamp":"2026-04-03T06:00:00Z","payload":{"source":"cli","model_provider":"fixture-provider","agent_nickname":"fixture-agent","model":"fixture-model"}}
{"type":"event_msg","timestamp":"2026-04-03T06:00:01Z","payload":{"type":"user_message","message":"Inventory the MCP configuration for this synthetic workspace."}}
{"type":"event_msg","timestamp":"2026-04-03T06:00:02Z","payload":{"type":"tool_call","tool_name":"mcp_inspector","command":"probe mcp servers","arguments":{"server":"filesystem","inventory_method":"tools/list"}}}
Codex sessions always start with a session_meta record. Respects $CODEX_HOME if set.
Claude Code session store
Claude Code stores sessions as JSONL files organized by project. Each project directory contains session files with alternating user and assistant message records.
Artifact Paths
Project sessions
~/.claude/projects/<project-hash>/*.jsonl One directory per project. Each JSONL file is one session.
{"type":"user","sessionId":"claude-tool-use","timestamp":"2026-04-27T12:10:00Z","message":{"role":"user","content":[{"type":"text","text":"Read the project README and summarize it."}]}}
{"type":"assistant","sessionId":"claude-tool-use","timestamp":"2026-04-27T12:10:01Z","message":{"role":"assistant","model":"claude-fixture-model","content":[{"type":"text","text":"I will read the public README only."},{"type":"tool_use","id":"toolu_fixture_read","name":"Read","input":{"file_path":"README.md"}}]}}
Claude Code sessions use type values of user and assistant at the top level. Tool calls and results are nested inside message.content arrays.
Gemini CLI session store
Gemini CLI stores each session as a single JSON file. Unlike JSONL-based agents, the entire session is one JSON object with a messages array.
Artifact Paths
Session files
~/.gemini/tmp/*.json Single JSON file per session. Contains the full session in one object.
{
"sessionId": "gemini-uc001-tool-result",
"projectHash": "fixture-project",
"startTime": "2026-04-27T12:30:00Z",
"lastUpdated": "2026-04-27T12:30:02Z",
"model": "gemini-fixture-model",
"messages": [
{ "type": "user", "content": "Check the repository status." },
{ "type": "tool_call", "name": "repo_status", "input": { "format": "json" } },
{ "type": "tool_result", "tool": "repo_status", "content": "status=ok" }
]
}
Gemini sessions are atomic JSON files. Session metadata (sessionId, projectHash, model) lives at the top level alongside the messages array.
OpenCode session store
OpenCode uses a SQLite database for current sessions and legacy JSON files for older installations. The SQLite database is the primary store; the JSON files are a legacy format.
Artifact Paths
Current (SQLite)
~/.local/share/opencode/opencode.db SQLite database. macOS: ~/Library/Application Support/opencode/opencode.db.
Legacy (JSON)
~/.local/share/opencode/storage/message/<session-id>/*.json One JSON file per message or a JSON array per session directory.
[
{
"id": "msg-cred-1",
"sessionID": "opencode-uc002-credential-publish",
"type": "tool_call",
"tool_name": "bash",
"arguments": { "command": "cat ~/.aws/credentials" },
"modelID": "fixture-model",
"providerID": "fixture-provider",
"time": "2026-04-28T10:00:00Z",
"agent": "build"
}
]
Legacy format uses tool_name and arguments fields. Current SQLite installations preserve the same field names in database rows.
Roo Code and Kilo Code session store
Roo Code and Kilo Code store sessions as JSON files in VS Code extension globalStorage directories. Each task directory contains a ui_messages.json file with a flat JSON array of all events.
Artifact Paths
Roo Code
~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/tasks/<task-id>/ui_messages.json VS Code extension storage. macOS: ~/Library/Application Support/Code/. Windows: %APPDATA%\Code\.
Kilo Code
~/.config/Code/User/globalStorage/kilocode.kilo-code/tasks/<task-id>/ui_messages.json Same format as Roo Code. macOS: ~/Library/Application Support/Code/. Windows: %APPDATA%\Code\.
[
{ "type": "user", "content": "Check the repository status." },
{ "type": "tool_call", "name": "repo_status", "input": { "format": "json" } },
{ "type": "tool_result", "tool": "repo_status", "content": "status=ok" }
]
The ui_messages.json file contains a flat JSON array. The array preserves chronological order. VS Code extension paths follow platform conventions for globalStorage.
GitHub Copilot session store
GitHub Copilot CLI records sessions as plain text process logs in the repository directory. This is the most limited and lossy session store format.
Artifact Paths
Process logs
<repo>/logs/copilot/process-*.log Plain text log files. Tool calls are embedded as JSON in log lines.
2026-04-27T16:16:57.841Z [INFO] Workspace initialized: copilot-uc001-tool-result (checkpoints: 0)
2026-04-27T16:16:57.847Z [INFO] Starting Copilot CLI: 1.0.36
2026-04-27T16:17:17.990Z [INFO] Accumulated output items (1): [{"arguments":"{\"format\":\"json\"}","call_id":"call_fixture_001","id":"c1","name":"repo_status","status":"completed","type":"function_call"}]
2026-04-27T16:17:45.200Z [INFO] Session completed.
Copilot process logs are the most lossy format. User intent, system instructions, and structured content are not preserved. Tool call arguments are stringified JSON.
Preservation priorities
When preserving session stores for investigation, follow these priorities:
- Copy the raw files first. Do not parse, normalize, or transform before preserving. Use forensic copy tools when possible.
- Record the source path and collection time. Provenance metadata is essential for defending the evidence chain.
- Check for variant directories. Codex has active, archived, and headless sessions. OpenCode has both SQLite and legacy JSON. Missing a variant means missing evidence.
- Hash the preserved files. SHA-256 hashes let you verify that preserved copies have not been modified.
- Do not run the agent or its tools on the preserved copy. Session stores can be modified by agent startup, compaction, or rotation.
- Check for VS Code extension variants. Roo Code and Kilo Code store data under VS Code globalStorage paths that differ from CLI-based agents.