Pi extension that moves stale session files into a per-project archive/ directory, purges
archives past a retention window, and browses active plus archived sessions from one /pi-archive
picker.
It never edits a session file. Archiving is a rename into a subdirectory that pi's session discovery does not read, so archived sessions disappear from the built-in picker and come back untouched when you restore them.
pi install git:github.com/junkfactory/pi-archiveTry it without installing:
pi --extension /path/to/pi-archive/extensions/index.tsBoth keys are top-level entries in ~/.pi/agent/settings.json:
| Key | Default | Meaning |
|---|---|---|
sessionArchiveDays |
7 |
Archive a family when every session in it is older than this many days |
sessionArchivePurgeDays |
90 |
Delete archived sessions older than this many days |
0disables that behavior (no archiving / no purging).- A negative or non-numeric value also disables the behavior and reports a warning instead of silently falling back to the default.
- Only
~/.pi/agent/settings.jsonis read — never a repo-local.pi/settings.json, so a project cannot change retention for the whole machine.
Archives live next to the sessions they came from:
~/.pi/agent/sessions/
├── <project>/
│ ├── <timestamp>_<id>.jsonl # active sessions
│ └── archive/
│ └── <timestamp>_<id>.jsonl # archived sessions
└── <other-project>/
└── archive/
A forked child stays in its own project's archive/, so a family can span several archive/
directories. Restoring puts each file back in the directory it came from.
/pi-archive # open the picker
/pi-archive sweep # sweep now
/pi-archive is its own command — the built-in /session and /resume commands are untouched and
unchanged. There is no keyboard shortcut.
A sweep also runs on session start (reason: "startup", interactive runs only). It is silent on
success; warnings and failures surface as notifications. /pi-archive sweep always reports a
count, e.g. archived 3 from 2 families, purged 0.
| Key | Action |
|---|---|
letters |
Type to search |
Tab |
Cycle scope: Current → All → Archived (All is skipped when it duplicates Current) |
↑ / ↓ |
Move (or pgup / pgdn for a page) |
Enter |
Open the selected session |
ctrl+a |
Archive the selected family (Current/All only) |
ctrl+u |
Restore the selected family (Archived only) |
ctrl+d |
Delete (press ctrl+d again to confirm) |
Esc |
Clear the query, or close the picker when it is empty |
Typing while the picker is open starts a search. A query matches each session's id, name, first
message, user/assistant message text, and cwd; tool output and thinking blocks are not searched.
While a query is active, results are shown flat (no fork tree) and ordered by relevance.
Inside the search box ctrl+a and ctrl+u mean archive and restore — they do not move to line
start or delete the line.
Currentis the sessions of the working directory,Allis every project,Archivedis everyarchive/directory.- When no other working directory has active sessions,
Allwould list exactly theCurrentsessions, so the picker hides that tab;Tabthen cyclesCurrent↔Archived. - Selecting the already-open session shows
Session already activeand keeps the picker open. ctrl+ddeletes the selected row and its forks — the whole subtree below it. A fork never drags its parent or siblings along, so deleting a child deletes only that child. The confirmation states how many sessions die before a secondctrl+dis accepted.- Selecting an archived session restores it to its project directory first, then resumes it;
/newafterwards lands next to the restored file, not insidearchive/. ctrl+ais refused for the open session, for a family that contains the open session, and for a family another running pi window has open.
Sessions and their forks are treated as one unit:
- A family archives only when every member is stale and none is the active session. A recent child keeps an old parent active, and a stale child never moves on its own.
- Archiving a session archives its whole family (same as the sweep), so a manual
ctrl+acannot leave children behind in another project directory. - Restoring (
ctrl+u, orEnteron an archived row) restores the whole family together, so restoring a parent never leaves children archived. - A split family (some members in
archive/, some still in a project directory) is never purged, no matter how old the archived copies are. The sweep report lists it assplit.
Archived files older than sessionArchivePurgeDays are deleted with trash (macOS
/usr/bin/trash). Unattended purge never falls back to unlink: if trash is missing or
fails, the whole purge phase is skipped with one warning and every file is left in place.
Manual deletion in the picker (ctrl+d) is interactive and may fall back to unlink. It deletes
one subtree at a time (the row plus its forks), and refuses outright when that subtree contains the
session you have open.
/usagestill counts archived sessions.@tmustier/pi-usage-extensionwalks the whole sessions tree, includingarchive/, so totals stay historically accurate. Archiving is not usage-neutral by accident — it is intentionally not exempted.- The built-in
/resumenever shows the archive, before or after this extension is installed./resumeand/sessionwork exactly as they did; the archive is only reachable through/pi-archive. - Archive files are ordinary session files.
piwill still refuse to open one in place; use/pi-archiveso it is restored first.
The age-based sweep scans only ~/.pi/agent/sessions. If you start pi with a custom
--session-dir:
- the sweep ignores those sessions (they are never auto-archived or auto-purged);
- a manual
ctrl+ain the picker still works, and the result is visible underArchived, because the picker also reads<sessionDir>/archive.
Stop using the extension by removing its entry from packages in ~/.pi/agent/settings.json (or
by dropping --extension); no other package and no pi core code is modified. Deleting the two
settings keys restores the defaults.
Nothing is destroyed by uninstalling: archived sessions stay where they are and can be moved back
with a plain mv:
mv ~/.pi/agent/sessions/<project>/archive/*.jsonl ~/.pi/agent/sessions/<project>/Only purge is irreversible, and it goes to the trash, so trash restore covers it. The liveness
registry in ~/.pi/agent/pi-archive/live/ is disposable — stale entries self-prune.
See TESTING.md for the local gates and the disposable-agent-dir rehearsal.