Where Pi stores session history
Pi's default session root is ~/.pi/agent/sessions/. Each session is a JSONL file with a session header and message/tree entries:
<session root>/--<encoded-project-path>--/<timestamp>_<uuid>.jsonlA real path looks like this:
~/.pi/agent/sessions/--Users-me-apps-blog--/2026-08-23T09-49-28-819Z_01a02e06-6f73-7b54-8a4a-63e19fdca249.jsonlThe filename starts with an ISO 8601 timestamp, so a plain ls sorts sessions chronologically.
Finding the session root
Pi's root is configurable in three places, in this order of precedence:
- The
PI_CODING_AGENT_SESSION_DIRenvironment variable, if set and non-empty sessionDirin<agent dir>/settings.json- The default,
<agent dir>/sessions
The agent directory itself is PI_CODING_AGENT_DIR, defaulting to ~/.pi/agent. So with nothing configured, sessions live at ~/.pi/agent/sessions.
A one-shot --session-dir can write outside the root scanned by Sessions Viewer. Those files may exist but not appear in the app. Align the configured root; do not assume an unlisted file has been deleted.
The project directory name
The absolute project path with / replaced by -, wrapped in a leading and trailing --:
/Users/me/apps/blog → --Users-me-apps-blog--The directory name is a useful hint, not a reversible encoding. The cwd in the file's first session record is the adapter's source for the project.
What else lives in the agent directory
~/.pi/agent/
├── sessions/
├── extensions/ ← lifecycle extensions
├── settings.json
├── mcp.json
├── memory/
├── models-store.json
└── auth.json ← credentials, do not read thisTo read conversation history, inspect the session files rather than credential files. Sessions Viewer also reads settings.json to resolve a custom session root; tool management is a separate feature.
Reading a Pi session from the terminal
Extract stored user/assistant text (all stored branches, not only the active one):
jq -r 'select(.type=="message") | .message
| select(.role=="user" or .role=="assistant") | .content
| if type=="string" then . else .[]? | select(.type=="text") | .text end' \
~/.pi/agent/sessions/--Users-me-apps-blog--/*.jsonlMost recent session for a project:
ls -1 ~/.pi/agent/sessions/--Users-me-apps-blog--/*.jsonl | tail -1Count sessions per project:
for d in ~/.pi/agent/sessions/*/; do
printf '%4d %s\n' "$(ls "$d"*.jsonl 2>/dev/null | wc -l)" "$(basename "$d")"
done | sort -rnHow do I resume this session?
Run pi --session "/absolute/path/to/session.jsonl" from the project's directory with Pi installed. Pi resume uses the file path, not just the UUID. The app offers terminal resume, not in-app Pi chat.
Source and limitations
Implementation: Pi adapter. Upstream: Pi documentation.
Reference scope: checked against the Sessions Viewer 0.6.0 adapters on 2026-10-05, not a compatibility guarantee for every CLI release. Shell examples use macOS/Linux paths and require
jq(orsqlite3for opencode). Replace placeholders with real values and use your configured data root. Text extraction does not replay tools, images or the active branch of a session tree. Command regressions use downloadable synthetic samples, not private sessions. Check the capability and evidence matrix for tested scope. Browsing is distinct from resuming or editing data; see privacy and data handling.
Pi stores branches through entry IDs and parent IDs. The one-liner above reads stored text in file order; it is not an active-branch renderer. See missing-session troubleshooting.
Or open it in an app
Sessions Viewer resolves the session root the same way Pi does, checking the environment variable, then settings.json, then the default, and reads only the session records, never the auth or credential files beside them. It also reads Claude Code, Codex, Grok Build, Kimi Code, Antigravity CLI and opencode.
