Skip to main content

session-recap

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.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
junghan0611/agent-config
آخر نشاط في المصدر
٢ سبتمبر ٢٠٢٦ في ١٦:٢٦
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
3 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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 corpus**: handles pi and Claude Code sessions. The unset-source runtime fallback is Claude Code → `claude`, every other surface → `pi`; only those first two callers are truly harness-matched. Codex, Antigravity, and other third surfaces write neither indexed corpus, so they must choose `--source` explicitly and normally use `--skip 0`. 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 … >300KB, drop tmp + legacy"; the pi filename spec was re-pinned to the current native form on 2026-08-10). 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 current native filename only** — `<created-at>_<UUIDv7>.jsonl`, pi's present-day session id. **No backward compatibility** (GLG ruling 2026-08-10): the older garden-id form (`_YYYYMMDDTHHMMSS-<6hex>`), UUIDv4, `_delegate-`, and `_entwurf-` are *not* OR'd back in — corpus admission is one current spec. pi stopped emitting garden-id suffixes on 2026-08-06; a filter still demanding them made every pi session after that date invisible to both recap and the andenken session index. Filenames do not carry identity: the `garden id ↔ nativeSessionId ↔ transcriptPath` join belongs to the entwurf meta-record, and neither recap nor andenken reimplements it. 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 ```bash 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` | runtime fallback | `pi`, `claude`, `all`. Unset → Claude Code=claude, every other surface=pi; third surfaces should set explicitly | | `--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 | | `--device NAME` | all | Session-corpus device filter (`oracle`, `thinkpad`). **Implies `--skip 0`** unless you pass `--skip` yourself. Only meaningful with a corpus configured — see below | | `--session-file PATH` | — | **Exact selection.** One absolute `.jsonl` path. Bypasses every discovery filter; cannot be combined with any of them | ### Session corpus — other machines' sessions `ANDENKEN_SESSION_CORPUS` (set in `~/.env.local`, shared with andenken's indexer) points at the gathered corpus, where every device's sessions live under `<corpus>/<device>/` keeping the runtime's own path shape. Unset → live stores only, exactly as before. **The variable is the switch; `~/.env.local` is its SSOT.** When the variable is *absent* from the process environment, recap reads that one key out of the file before giving up. A process environment is captured once at login, so a line added to `.env.local` afterwards is invisible to every session, daemon and agent that started earlier — measured 2026-09-03, a shell carried every other `ANDENKEN_SESSION_*` but not `ANDENKEN_SESSION_CORPUS`, and the corpus was silently off while `semantic-memory` kept returning corpus paths that `--session-file` then refused. Setting the variable to the empty string (`export ANDENKEN_SESSION_CORPUS=`) is still a deliberate live-only opt-out and wins over the file. **That opt-out is read-side only.** andenken's `sync-sessions.sh` has the same fallback (its own `ANDENKEN_SESSION_CORPUS` guard near the top of the script, read 2026-09-03) but tests with `-z`, so an empty value there is treated as unset and the file wins. Same variable, two readings of the empty string: recap/improve-agent stay on live stores, the indexer still gathers. Use the empty string to scope a recap, not to disable the corpus system-wide. **Discovery reads live ∪ corpus, not corpus instead of live.** andenken's indexer replaces the live stores because `sync-sessions.sh` gathers first and so owns the corpus's freshness; recap has no gather step. Corpus-only discovery would drop *this machine's current session* whenever it was written after the last gather, and that silently breaks the `--skip 1` invariant (current session = newest mtime) the whole size-filter ordering above exists to protect. Copies of one session held by two devices are folded by **basename** (UUID session id): larger file wins — a transcript only grows, so the larger copy holds strictly more turns — and a size tie breaks on the lexicographically smaller path, which keeps the choice stable across machines. Same rule as andenken `dedupeByBasename`. Measured 2026-09-02: 2,104 live → 2,567 after union (+463 oracle), 0.07s. The header shows provenance as `[claude@oracle]` / `[pi:gpt@oracle]`; live sessions carry no `@` suffix. **A device says where a session was collected, not where it was created.** The two machines exchanged an `rsync -a` with mtimes preserved, so origin is not recoverable — use it to label and filter, never to rank. ### `--device` — what it selects, and why it skips nothing `--device` filters before the dedupe fold, so it names *the copy under that device*, not "the winner that happened to come from there". Two consequences, both measured 2026-09-03 on the live corpus: - **On this machine, `--device thinkpad` is the corpus copy, not the live one.** Of 2,575 discovered sessions the winning copy was live for 2,106 and `oracle` for 469 — **zero** thinkpad-corpus winners, because a live transcript is always at least as large as its gathered copy. `--device thinkpad` is therefore how you reach a session that was *deleted from the live store* and survives only in the append-only corpus; for anything still live it just names the other copy of the same session. - **`--device` implies `--skip 0`.** `--skip 1` exists to drop "the session being written right now", identified as newest mtime. That session is in the *live* store and carries no device, so it can never appear in a device-filtered list — skipping one there throws away the other machine's genuine newest session instead. Measured: `-p agent-config --device oracle` hid the 2026-09-02T19:08 session (`69f08580`) entirely until `--skip 0`. An explicit `--skip N` is still honoured. ## Exact selection — `--session-file` The flags above *search* for a session. `--session-file` **names** one. Use it when another tool already found the exact session — today that means `semantic-memory`, whose results carry the session `file`. Without this flag search hands you a precise answer and recap goes back to guessing "the recent session of this project". ```bash # semantic-memory found it → restore it exactly python3 {baseDir}/scripts/session-recap.py --session-file /abs/path/session.jsonl -m 20 ``` **What it bypasses — all of it, deliberately.** tmp exclusion, the pi native filename spec, `--min-kb`, and **`--skip 1`**. Dropping skip means exact selection *can target the live current session* — sometimes what you want, but never by accident. Reading your own live transcript may show an inverted `기간` line because the file is still being appended and is not strictly time-ordered; the extracted text is unaffected. **It refuses rather than guesses.** Combining it with `-s/-p/-a/--skip/--source/ --harness/--min-kb` is an error (exit 2), not a silent override — those flags describe a search that is no longer happening. Named errors, each a different fact: not absolute · not `.jsonl` · a symlink · unreadable · outside `~/.pi/agent/sessions`, `~/.claude/projects`, and (when set) the corpus roots · **parsed 0 messages** (exit 1 — the path is a real session file but holds no readable turns; nothing is printed to stdout, so you can never write a header for a session you did not actually read). The header contract is unchanged, plus one `파일:` line carrying the full path, so the answer rules below apply identically. ### Seam contract — what this flag does and does not join | Signal | Owner | Consumed here? | |---|---|---| | `file` / `sessionFile` (path) | semantic-memory | **Yes** — `--session-file` | | `line` / `lineNumber` | semantic-memory | **No.** Different address space | **`entwurf-peek` → recap is still an open seam.** peek resolves a citizen's transcript path internally but never emits it: `peek` prints only `<parent>/<name>` and has no `--json`, and `situation --json` rows carry no transcript path. So a garden id cannot be turned into a `--session-file` argument yet. Do not describe that path as available. `semantic-memory` reports `sessionFile:lineNumber` where `lineNumber` is the **raw JSONL line** (blank and non-message records included). recap counts **filtered messages**. The two never line up, so recap does not take a line anchor and will not grow one. To read around a semantic hit, that is semantic-memory's own job: `semantic-memory search-sessions ... --with-excerpt`. Division of labor: **the hit neighborhood belongs to semantic-memory, the exact session's spine belongs to recap.** ## Examples ```bash # last session python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 # previous session + cost python3 {baseDir}/scripts/session-recap.py -p dictcli -m 20 --cost # all recent sessions python3 {baseDir}/scripts/session-recap.py -a -m 10 # last 3 sessions python3 {baseDir}/scripts/session-recap.py -p notes -s 3 -m 10 # commit list python3 {baseDir}/scripts/session-recap.py -p nixos-config --commits # pi sessions only python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --source pi # pi native GPT/Codex sessions only python3 {baseDir}/scripts/session-recap.py -p entwurf -m 15 --source pi --harness gpt # entwurf Claude/Opus sessions only (not Claude Code) python3 {baseDir}/scripts/session-recap.py -p entwurf -m 15 --source pi --harness acp # Claude Code sessions only python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --source claude # both harnesses (default is current harness only) python3 {baseDir}/scripts/session-recap.py -p agent-config -m 15 --source all # recent session too small (<300KB) to pass the filter — disable size filter 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: ```bash ls -lt ~/.pi/agent/sessions/ | head # live store on this machine ``` 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 (pi/Claude Code: unset source follows that runtime; third surfaces: set it explicitly) 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 the runtime fallback?** To continue prior work under pi or Claude Code, read that same runtime's sessions (pi under pi, claude under Claude Code — automatic). Codex, Antigravity, and other third surfaces have no matching indexed source, so the fallback to pi is only a compatibility default, not a claim that pi is their current transcript. 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
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub