Skip to content

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>.jsonl

A real path looks like this:

~/.pi/agent/sessions/--Users-me-apps-blog--/2026-08-23T09-49-28-819Z_01a02e06-6f73-7b54-8a4a-63e19fdca249.jsonl

The 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:

  1. The PI_CODING_AGENT_SESSION_DIR environment variable, if set and non-empty
  2. sessionDir in <agent dir>/settings.json
  3. 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 this

To 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):

bash
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--/*.jsonl

Most recent session for a project:

bash
ls -1 ~/.pi/agent/sessions/--Users-me-apps-blog--/*.jsonl | tail -1

Count sessions per project:

bash
for d in ~/.pi/agent/sessions/*/; do
  printf '%4d  %s\n' "$(ls "$d"*.jsonl 2>/dev/null | wc -l)" "$(basename "$d")"
done | sort -rn

How 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 (or sqlite3 for 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.