| name | session-recap |
| description | Extract a compact recap from previous pi or Claude Code session JSONL without reading raw JSONL. Use for 'last session', 'what was I doing', continuity restore, and pi-internal GPT vs ACP recall via --source pi --harness gpt|acp. Preserves the skip-before-size edge case; retry with --min-kb 0 when a real recent session is below the default size floor. |
session-recap โ extract a session summary
Extract only user/assistant text from a session JSONL.
Never read a raw JSONL directly โ it dumps ~50KB of JSON noise into context.
Multi-harness: handles both pi and Claude Code sessions. Default source is the
current harness (running under Claude Code โ claude, otherwise โ pi). To continue
prior work cleanly you want the same harness's sessions. Override with --source.
Inside --source pi, use --harness gpt|acp|all to distinguish pi native GPT/Codex
from entwurf Claude/Opus. --source claude still means Claude Code only.
Corpus filters (aligned with andenken session-indexer.ts โ 0d4432b "tighten
corpus to garden-native >300KB, drop tmp + legacy"). Same discipline as session
embeddings, so recap usually sees substantive sessions instead of probes. Three filters
exist, and their order is part of the contract:
- Structural filters (applied before skip):
- tmp dirs excluded (both runtimes) โ pi
--tmpโฆ-- / claude -tmpโฆ scratch.
- pi garden-native filename only โ
_YYYYMMDDTHHMMSS-<6hex>.jsonl (0.9.0+). Legacy
forms (_<uuid>/_delegate-/_entwurf-) excluded. claude is always UUID, so no
filename filter.
- Pi harness filter
--harness gpt|acp|all (applied after skip, before size):
gpt = pi native OpenAI/Codex (openai-codex / gpt-*), acp = entwurf
Claude (entwurf / claude-*). Unknown pi sessions pass only with all.
- Size filter
--min-kb 300 (applied after skip + harness): drops short test/probe
fragments from what's shown. This is a heuristic, not truth: a real GPT/Codex
session can be below 300KB. Disable with --min-kb 0 when the expected session is
missing or the header looks stale.
Why size filter runs after skip (bug fix 2026-06-19). --skip 1 drops the current
live session, identified by the invariant current session = newest mtime (true on
any harness โ it's the file being written right now). Early in a session that file is
still small (<300KB). If the size filter ran first it would drop the current session
from the list, so --skip 1 would then drop the most-recent real session instead and
recap would surface a stale one. So: structural filters โ skip on the full recency list
โ optional pi harness filter โ size filter on the survivors.
Size-floor edge case. If --source pi --harness gpt (or acp) returns no session or
an older-than-expected header, do not switch project names or read raw JSONL. First
retry the same command with --min-kb 0 (or a lower floor such as --min-kb 100). The
300KB default is there to suppress probes; it is allowed to hide a real but shorter
conversation.
This skill is the low-level extractor under /recall. Single repo/session restore lives
here; multi-axis recall (cross-project, day-query, journal ยง/llmlog) follows
commands/recall.md. (The old slash name /recap collided with a Claude Code built-in
and was renamed 2026-05-12.)
API
python3 {baseDir}/scripts/session-recap.py -p <PROJECT> -m 15
| Flag | Default | Description |
|---|
-p, --project NAME | all | Project filter (exact match). Always specify. |
-m, --messages N | 20 | Last N messages per session |
-s, --sessions N | 1 | Last N sessions |
-c, --chars N | 300 | Max chars per message |
-a, --all-projects | - | Include all projects |
--commits | off | Include git commit commands |
--cost | off | Session cost summary |
--skip N | 1 | Skip newest N sessions (the current one) |
-f, --format | text | text or json |
--source | current harness | pi, claude, all. Unset โ Claude Code=claude, else pi |
--harness | all | pi-internal filter: gpt, acp, all. Use with --source pi or all |
--min-kb N | 300 | Size floor, size > N*KB. 0 disables; use it when a real recent GPT/ACP session is below the default floor |
Examples
python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15
python3 {baseDir}/scripts/session-recap.py -p dictcli -m 20 --cost
python3 {baseDir}/scripts/session-recap.py -a -m 10
python3 {baseDir}/scripts/session-recap.py -p notes -s 3 -m 10
python3 {baseDir}/scripts/session-recap.py -p nixos-config --commits
python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --source pi
python3 {baseDir}/scripts/session-recap.py -p entwurf -m 15 --source pi --harness gpt
python3 {baseDir}/scripts/session-recap.py -p entwurf -m 15 --source pi --harness acp
python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --source claude
python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --source all
python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --min-kb 0
Choosing -p (project name)
Default rule: the last directory component of CWD.
project = repo directory name (~/repos/gh/agent-config โ agent-config).
| CWD | -p value |
|---|
~/repos/gh/agent-config | agent-config |
~/repos/work/some-proj | some-proj |
/home/junghan (home) | home |
User intent overrides the CWD rule
In these cases don't use the CWD basename mechanically โ use the project of the
context the user pointed at:
- "home ๋๋ ํ ๋ฆฌ ๋ถ์ ", "Entwurf", "๋ถ์ ๊ธฐ๋ก" โ
-p home
- "COS" / ๋น์์ค์ฅ session โ
-p cos
- a named repo steward session โ that repo name (
andenken, notes, entwurf, โฆ)
When unsure:
ls -lt ~/.pi/agent/sessions/ | head
inspect the recent session dirs and confirm the user's stated task matches a recent
session name.
Without -p, you get the single newest session across all projects โ possibly a
different repo's.
Workflow: "what was I just doing?"
Step 0: First decide if the user means home / Entwurf / COS / a specific repo steward.
Step 1: python3 {baseDir}/scripts/session-recap.py -p <PROJECT> -m 15
(source unset โ current harness auto: claude under Claude Code, else pi)
Step 2: Verify the target via the header (`โโโ project [source] (file...) โโโ` or
`โโโ project [pi:gpt|pi:acp] (...) โโโ`) and the first 1โ3 messages.
Step 3: If empty, stale, or too short โ rerun the SAME axis with --min-kb 0 first
(small recent session), then widen to --source all โ -s 3 --skip 0
Step 4: Summarize from the verified output only.
Escalation: multi-axis recall
Don't stop at session-recap โ escalate to the /recall protocol when:
- The retrieved session is short (1-turn entwurf / smoke / "Reply OK").
- The user says "์ด์ ์ ์ฒด", "์ค๋ ์ด์ด์", "๊ธฐ์ต์ถ", "compact ์์ด", "๋๋ฅผ ๋ฆฌ์ฝ".
- The current repo session is right but cross-project recall (agent-config / andenken /
voscli โฆ) looks important.
- A journal
ยงrepo marker or llmlog may be the real spine of the work.
Escalation order: session-recap โ extract proper nouns from the output โ
two-pass session_search โ if needed day-query (gitcli --summary, denotecli day,
lifetract, calendar) โ report both the axis you saw and the one you didn't.
Why harness-matched default? To continue prior work you must read the same
harness's sessions (claude under Claude Code, pi under pi โ auto). Historically Claude
Code produced many 1โ2 message stubs, which argued for preferring pi; the >300KB
size filter now removes those stubs, so claude sessions also retain only real work.
Use --source all to see across harnesses. Use --source pi --harness gpt when the
operator says "GPT session" and means pi native GPT/Codex, not a project named gpt.
Answer rules (important)
A summary answer must include at least these two lines:
์กฐํ ํ๋ก์ ํธ: <PROJECT>
๋์ ์ธ์
: โโโ ... โโโ (the header line)
And the summary must be grounded strictly in the actual output text. Do not blend in
memory, other sessions, or similar-looking work.
Recommended response template
์กฐํ ํ๋ก์ ํธ: home
๋์ ์ธ์
: โโโ home [pi] (2026-04-19T23-53-12-415Z_...) โโโ
# or: ๋์ ์ธ์
: โโโ entwurf [pi:gpt] (...) โโโ
์์ฝ:
- ...
- ...
- ...
Writing the header first pins what you are actually looking at into the answer.
When the output differs from the expected topic
If the expected topic (e.g. a denote wrapper) isn't in the output, don't force-fit it โ
say so first:
ํ์ฌ ์กฐํ๋ ์ธ์
์๋ denote wrapper ๋งฅ๋ฝ์ด ์์ต๋๋ค.
์ง๊ธ ์ถ๋ ฅ์ ๋ชจ๋ธ ํ์ธ/์ธ์ฌ ์ธ์
์
๋๋ค.
์ํ๋ฉด -p home ๋๋ -s 3์ผ๋ก ๋ค์ ํ์ธํ๊ฒ ์ต๋๋ค.
A mismatch is a signal, not a failure. Report it, then widen scope.
Do not:
- โ
read the raw session JSONL (50KB JSON noise)
- โ Re-check the raw JSONL after
session_search (redundant)
- โ Re-run the same command with tweaked flags 5+ times when empty
- โ Summarize from memory without checking the output header
- โ Use the CWD basename mechanically and ignore the user's stated context
(home / Entwurf / COS / a specific repo steward)
Cost
| Method | Context | Cost |
|---|
| raw JSONL read | ~100KB | ~$0.63 |
| session-recap | ~4KB | ~$0.09 |