Search Sessions
Ranked full-text search across past session transcripts from the terminal
Search every stored session transcript from the terminal โ ranked by relevance, with a snippet centred on each match.
Quick Start
An agent recalls past sessions through the session_search tool โ the CLI reaches the same engine from your terminal.
from praisonaiagents import Agent
agent = Agent(
name="recall-agent",
instructions="Search past sessions when the user asks about earlier decisions.",
tools=["session_search"],
)
agent.start("What did we decide about the billing migration?")- Search your sessions
bash praisonai session search "billing migration"Prints a table of matching sessions ranked by score, each with a snippet centred on the match:
Search: billing migration โโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโโโโโโโโโณโโโโโโโโณโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโโโโโโโโโโโ โ ID โ Title โ Score โ Snippet โ When โ โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ โ zeta โ Zeta โ 5.0 โ we need a billing migration migration migrโฆ โ 2026-06-10T14:32โฆ โ โ alpha โ Alpha โ 2.0 โ one mention of migration here โ 2026-06-09T11:04โฆ โ โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโAn empty result prints:
No sessions matched: billing migration - Widen the search
Return more sessions and more context around each hit:
bash praisonai session search "billing migration" --limit 10 --window 8 - Get machine-readable output
Add the global
--jsonflag for a structured result:bash praisonai --json session search "billing migration"json { "query": "billing migration", "results": [ { "session_id": "zeta", "title": "Zeta", "when": "2026-06-10T14:32:00Z", "snippet": "we need a billing migration migration migrโฆ", "score": 5.0, "anchor_index": 12, "messages": [ {"index": 11, "role": "user", "content": "...", "timestamp": "...", "archived": true}, {"index": 12, "role": "assistant", "content": "...", "timestamp": "...", "archived": false} ] } ] }Each result is
SessionHit.as_dict()โ the same shape as the Cross-Session Recall Discovery return.Each message carries an
archivedboolean โtruemarks a turn recalled fromarchived_messages(compacted out of the active window by the defaultretention="compact"policy). See Recall Across Compacted History.
How It Works
session search delegates to SqliteSessionStore โ the same FTS5/bm25 engine as the session_search agent tool โ instead of a substring scan.
The command iterates the CLI’s canonical stores via canonical_cli_stores() โ the same helper session resume / show / delete / export use โ so id resolution stays consistent across every sub-command. See Session Resume.
| Step | What happens |
|---|---|
| Enumerate stores | Walks the project-scoped store then the global default store via canonical_cli_stores() |
| Index per store | Opens a SqliteSessionStore(session_dir=โฆ) and runs search(query, limit, window) |
| Rank | FTS5/bm25 scoring with snippets and lineage dedup, applied inside each store |
| Cross-store dedup | Collapses duplicate session_ids across stores, keeping the higher-scoring copy |
| Sort & truncate | Sorts by (score desc, when desc) and keeps the top --limit hits |
Cross-store dedup
A session resumed from the global default store keeps a project-side shadow, so the same id can match in both canonical stores. Without dedup those duplicate rows each consume a slot of --limit and crowd out distinct sessions. The command collapses by session_id, keeping the higher-scoring copy โ mirroring the lineage dedup the store already applies inside a single directory.
Compacted history stays searchable
The CLI walks the same archived + active projection as the session_search agent tool. A detail rolled into archived_messages under retention="compact" is still recallable via praisonai session search โ hits on archived turns come back with archived: true in each message entry (JSON mode) so the compaction boundary stays visible.
# The detail was rolled into archived_messages weeks ago โ still findable from the terminal:
praisonai session search "deploy token XZ99" --limit 5See Cross-Session Recall โ Recall Across Compacted History.
Flags
praisonai session search <query> [--limit/-n N] [--window/-w N]| Argument / Flag | Type | Default | Description |
|---|---|---|---|
query | str (positional, required) | โ | Free-text query to search across session transcripts |
--limit, -n | int | 5 | Maximum number of matching sessions to return |
--window, -w | int | 5 | Number of messages to include around each hit |
--json (global) | flag | off | Print {"query": ..., "results": [...]} instead of a table |
Text mode prints a table with columns ID | Title | Score | Snippet | When. JSON mode prints {"query": "...", "results": [...]} where each result is SessionHit.as_dict().
Common Patterns
From an agent tool to the terminal
The session_search agent tool and praisonai session search share the same store โ pick whichever fits your workflow.
# Same engine (SqliteSessionStore / FTS5+bm25) โ from the terminal:
praisonai session search "billing migration" --limit 5 --window 5Pipe JSON into a script
praisonai --json session search "auth refactor" \
| jq -r '.results[] | "\(.score)\t\(.session_id)\t\(.snippet)"'Resume the top hit
SID=$(praisonai --json session search "billing migration" | jq -r '.results[0].session_id')
praisonai session resume "$SID"Best Practices
Keep –window small for a quick scan
Start with the default --window 5. Widen only when you need more surrounding context after finding the right session โ then session resume it.
Treat scores as relative rankings
Scores are FTS5/bm25 ranks, not probabilities. A 5.0 beats a 2.0, but says nothing absolute โ read the snippets to confirm the match. Compaction count no longer skews a session’s rank โ the synthetic retention="compact" summary is kept for context in each hit but excluded from scoring (PraisonAI PR #6112).
Raise –limit when duplicates are expected
Cross-store dedup collapses same-id shadows, but distinct sessions on the same topic still compete for slots. Raise --limit when a topic spans many sessions.
Use –json to automate
The --json output is SessionHit.as_dict() per result โ pipe it into jq to feed ids straight into session resume, show, or export.