feat: pi sessions and list mode#8
Draft
kakkoyun wants to merge 2 commits into
Draft
Conversation
Index a third session source: pi, whose sessions live at ~/.pi/agent/sessions/--<encoded-cwd>--/<ts>_<uuid>.jsonl in v3 JSONL format documented at https://github.com/mariozechner/pi-mono. Pi headers are {type: 'session', id, cwd, version, ...}; subsequent entries carry a top-level 'type' field. We index only user/assistant TextContent from {type: 'message'} entries. Other types (custom, custom_message, session_info, model_change, thinking_level_change, compaction, branch_summary, label) and non-conversational roles (toolResult, bashExecution) are skipped, matching the user+assistant-only behaviour of the existing Claude and Codex parsers. scripts/recall.py - PI_DIR / PI_SESSIONS_DIR constants - parse_pi_session(path) parser - pi glob added to index_sessions sources list - dispatch arm for source == 'pi' - --source choices include 'pi' scripts/read_session.py - detect_format() recognises pi headers (type=='session' with cwd or version) before falling through to claude/codex checks - iter_messages() pi branch handles {type: 'message', message: {role, content}} SKILL.md / README.md / CHANGELOG.md updated with pi as a third source in install/index/query diagrams, examples, tags, and resume hint. Verified on a real machine with claude+codex+pi history (1841 sessions, 29184 messages indexed in ~7s): recall 'buffer' --source pi # only pi-tagged results recall 'buffer' --days 7 # mixed [claude] [codex] [pi] read_session.py <pi-file> --pretty # auto-detects pi format
Make the positional query argument optional. When omitted, recall lists
every session in the time window without text matching — bypasses FTS
entirely and queries the sessions table by (timestamp, source, project),
sorted by recency.
Why: callers that want to enumerate every session in a window had no
ergonomic way to do it. Bare-* queries to FTS5 error with 'unknown
special query', and there is no "match-all" syntax in FTS5. Forcing
callers to invent a term that probably matches everything is fragile.
List mode is the right primitive: no query string, no FTS, just SQL.
Output banner reads 'Listed N sessions ...' (vs 'Found ...') and the
empty-result message reads 'No sessions in the time window.' (vs 'No
matching sessions found.'), so callers can see which path was taken.
scripts/recall.py
- list_sessions(conn, project, days, source, limit) — SQL-only path,
returns rows in the same shape as search() so main()'s rendering loop
is unchanged
- parser.add_argument('query', nargs='?')
- main() routes to list_sessions when args.query is None, search otherwise
SKILL.md / CHANGELOG.md updated. No schema change. No reindex needed.
Verified on a real machine:
recall --days 7 # every session, mixed agents
recall --days 7 --source pi # only pi-tagged sessions
recall 'buffer' --days 7 # FTS path unchanged
Owner
|
awesome, let me know when it's good to go! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two additive features. Draft for review while I exercise the changes locally for a few more days.
What
1. Index pi (mariozechner/pi-coding-agent) sessions —
~/.pi/agent/sessions/**/*.jsonl, alongside the existing Claude and Codex globs. Same FTS5 schema, same DB. New--source pifilter and[pi]result tag.read_session.pyauto-detects the format.2. Make the positional
queryoptional — when omitted,recalllists every session in the time window via direct SQL on thesessionstable. Bypasses FTS entirely. Banner readsListed N sessions ...(vsFound ...) so the caller can see which path ran. Useful when an agent / retro flow wants every session in a window rather than a search hit.Pi format reference: https://github.com/mariozechner/pi-mono · session-format docs ship with the
@mariozechner/pi-coding-agentnpm package underdocs/session-format.md.Diff
No schema change. No upstream API change to existing flags. Existing callers keep working unchanged;
queryis now optional but supplying it routes to the samesearch()path as before.Pi parser
Mirrors
parse_codex_sessionshape:{type: "session", id, cwd, version, ...}— extractcwd→ project,id→ session_id,timestamp→ earliest_ts.{type: "message"}entries — keep onlyrole ∈ {"user","assistant"}and only TextContent blocks (skipthinking,toolCall,image).custom,custom_message,session_info,model_change,thinking_level_change,compaction,branch_summary,label. Skip non-conversational rolestoolResult,bashExecution.Format detection
detect_format()returns one ofpi | claude | codexfrom the first non-empty parseable line. Pi headers are tested first because they carry the most distinctive signature (type == "session"withcwdorversionon the same line — only present on the header).Verified locally
Real machine with all three agents in history:
Reindex on this corpus: ~7s.
Backward compatibility
recall <query> ...: unchanged.recall ... --source claude|codex: unchanged.--source pi: new value.recall ...(no query): new list-mode path.--reindexonce after upgrade to pull pi sessions into the existing~/.recall.db.Why submit both as one PR
The list-mode commit lands on top of pi support and uses no pi-specific code, so the two are independent and easy to split if you'd prefer two PRs — say the word and I'll repoint commit 2 onto a separate branch. Bundled here because they ship together in the dotfiles deployment that drove this work.
Open questions
cwdfield, so detection works for both. Behaviour against very old (v1, linear, pre-tree) sessions hasn't been tested — none on this machine. If you have any v1 transcripts, I'd appreciate a sample for the regression test.