Session lifecycle
A session is one agent.Session value persisted as a row in the sessions table (internal/state/sqlite/schema.sql). It has an id, a title, a chronologically-ordered slice of Message values, and timestamps. Once created, it exists until you delete it.
Sessions are created on-demand by every entry point:
rousseau chat— one session per TUI session (a new one on eachchatinvocation; you'd have to build a session-picker to reuse an existing one).- Every transport (
whatsapp,slack, …) — one session per JID, via the JID map (internal/state/sqlite/jidmap.go). rousseau cron— each fire is a one-shot session bounded to that run.
Enumerate
rousseau session list --limit 10
Output (from newSessionListCmd in internal/cli/session.go):
<short-id> <messages> <updated_at> <title>
--limit 0 returns unlimited rows.
Search
FTS5 across every recorded message:
rousseau session search 'retry logic'
rousseau session search '"exponential backoff" AND anthropic'
rousseau session search 'retr*' # prefix
The command wraps Store.Search (internal/state/sqlite/search.go) with SearchOptions{Limit: N}. Ranking is BM25; snippets are trimmed to ~200 characters.
Show
rousseau session show <session-id>
Prints the full transcript with → tool_use(name, input) and ← tool_result markers between assistant messages. Useful for auditing an unattended daemon's session.
Delete
rousseau session delete <session-id> --yes
The --yes flag is required (newSessionDeleteCmd). Deletion cascades through the FTS5 triggers so the recall index stays consistent.
Compression triggers
When agent.compression.enabled: true in config.yaml, the LLMCompressor (internal/agent/compressor.go) checks two conditions before each turn:
len(s.Messages) >= trigger_messages(default 60).len(s.Messages) > keep_recent(default 8).
If both hold, the compressor summarises the oldest slice into one synthetic user message prefixed with the marker [rousseau-compressed], then keeps the last keep_recent messages verbatim. The rewritten session replaces the original in memory and is persisted on the next Store.Save.
A second compression on an already-compressed session is skipped unless the session has grown to more than 2 * trigger_messages — this bounds runaway growth without paying to re-summarise every turn.
Log line:
INFO agent.compressed messages=68
Restoration
Sessions restore automatically. The transport router (internal/transport/router.go) looks up the JID → session id mapping on inbound, then Store.Load unmarshals the JSON payload back into an agent.Session. No manual step.
If a mapping is stale — session id exists in jid_sessions but not in sessions — you'll see router.stale_mapping (WARN), and the router creates a fresh session. Legacy artefact from a partial delete; safe to ignore.
Manual restoration from a backup
To roll back the entire session store from a .backup snapshot:
systemctl --user stop rousseau-agent
cp /backup/sessions.db.2026-07-12.bak ~/.local/share/rousseau/sessions.db
rm -f ~/.local/share/rousseau/sessions.db-wal ~/.local/share/rousseau/sessions.db-shm
systemctl --user start rousseau-agent
The -wal and -shm files must be dropped alongside the primary; SQLite reconstructs them on next open.
Bulk deletion by age
There is no built-in "delete sessions older than X" CLI. Drop through SQLite:
sqlite3 ~/.local/share/rousseau/sessions.db <<'SQL'
DELETE FROM sessions WHERE updated_at < datetime('now', '-90 days');
SQL
FTS5 triggers keep the recall index consistent.
Preserving privacy
Since session content is stored plaintext in a JSON blob, treat sessions.db as sensitive. Options:
- Filesystem-level encryption. LUKS on Linux, FileVault on macOS.
- Encrypted backups.
resticandborgboth encrypt at rest. - Delete-on-completion for one-shot sessions. For cron-driven daemons, a post-run hook could
rousseau session deletethe just-completed session id. Not built-in today; see Guides: Enterprise Onboarding for the review.
Full rousseau session command reference
List sessions, newest first:
rousseau session list
rousseau session list --limit 100
rousseau session list --json
Columns: ID, Title, Messages, UpdatedAt. The --json flag emits one object per line for scripted consumers.
Print a session's full transcript:
rousseau session show <session-id>
rousseau session show <session-id> --raw
--raw prints the JSON as stored (useful for debugging). Without --raw, tool calls render as → tool_use(name, input) and results as ← tool_result.
Full-text search across every session:
rousseau session search "refactor login"
rousseau session search "TODO" --limit 10
Uses the FTS5 index (see internal/state/sqlite/). Results are ranked by relevance and include a snippet with the matched terms highlighted.
Delete a session and its FTS5 entries:
rousseau session delete <session-id> --yes
The --yes flag is required — no interactive confirmation. Deletion cascades via SQL triggers so the recall index stays consistent.
Export a session as JSON:
rousseau session export <session-id> > session.json
The exported format matches the on-disk JSON blob; re-import is not yet supported (roadmap).
Troubleshooting
session not found
The ID you passed does not exist. Case-sensitive. Use rousseau session list to see valid IDs.
FTS5 search returns nothing
The index might be out of date on legacy sessions imported before FTS5 was wired. Rebuild by running any content-mutating operation (a delete triggers reindex), or reindex manually via SQLite.
database is locked on read
Another daemon is holding a WAL write lock. Use a read-only DSN (?mode=ro) if you only need to read.
Session store growing too fast
Enable compression (agent.compression.enabled: true) and periodically VACUUM the SQLite file to reclaim space.
Restore from backup produces stale state
Ensure you dropped -wal and -shm before starting the daemon. SQLite will replay the WAL if -wal is present, potentially undoing your restore.
Related pages
- Reference: Session store — schema and DDL.
- Guides: Managing workspaces — per-workspace stores.
- Guides: Context management — how compression decides what to keep.
- User Guide: CLI — command signatures.
- User Guide: Compression & Recall — internals of the compressor and FTS5 recall.
Further reading
internal/cli/session.go— CLI wiring.internal/state/sqlite/store.go— DSN, WAL, indexes.internal/agent/session.go— theSessionstruct.internal/agent/compressor.go—LLMCompressor.internal/agent/recall.go—SQLiteRecall.