# picc-recap

[![npm downloads](https://img.shields.io/npm/dt/@ladbabynpm/picc-recap.svg)](https://www.npmjs.com/package/@ladbabynpm/picc-recap)

Claude Code style **away summary** for [pi](https://pi.dev) — a faithful port of Claude Code's `services/awaySummary.ts` + `hooks/useAwaySummary.ts`.
Part of [picc](https://github.com/Ladbaby/picc), a pi agent setup mirroring Claude Code's harness.

After you step away and the agent has settled, a short, dim "while you were away"
line appears. It is generated by a small/fast model from your last ~30 messages,
using **Claude Code's exact prompt**.

This is intentionally a different thing from `@zhcsyncer/pi-recap`. pi-recap produces
a one-line recap + title (JSON), renames the session, and syncs a multiplexer.
`picc-recap` has **no side effects** — just the dim summary, like Claude Code.

## Install

```bash
pi install npm:@ladbabynpm/picc-recap
```

or from a git bundle / locally:

```bash
pi -e ./picc-recap
```

For local development the live config is a junction in `~/.pi/agent/extensions/picc-recap`.

## Behavior

- **Trigger (auto):** when the agent settles (`agent_settled`), a timer starts. If you
  stay idle for `idleAfterSettleMs` (default **5 min**, like Claude Code's `BLUR_DELAY_MS`)
  with no queued work, the summary is generated. Typing anything cancels it.
- **Trigger (manual):** `/away` generates immediately (with a cancellable loader).
- **Model:** a small/fast model by default (Claude Code's `getSmallFastModel()`), with
  thinking effectively off (small `maxTokens`). Configurable.
- **Display:** a TUI widget below the editor, dim, prefixed with Claude Code's `※`
  marker (U+203B, REFERENCE_MARK). Cleared as soon as you type or the agent starts.
- **Dedup:** at most one summary per user turn (Claude Code's
  `hasSummarySinceLastUserTurn`).
- **Not compaction:** the summary is shown as a widget and persisted as a `custom`
  entry. It is **never** injected into the LLM context.
- **TUI only:** headless modes (`print`, `json`, `rpc`) are no-ops, matching Claude
  Code's terminal requirement.

## Prompt (verbatim from Claude Code)

```
Session memory (broader context):
<session memory, if any>

The user stepped away and is coming back. Write exactly 1-3 short sentences. Start by
stating the high-level task — what they are building or debugging, not implementation
details. Next: the concrete next step. Skip status reports and commit recaps.
```

The memory block is included only when present.

## Config

Read from (project overrides global; project only read when the project is trusted):

```
$PICC_RECAP_CONFIG_PATH                                   (full file path, wins)
$PI_CODING_AGENT_DIR/extension-data/picc-recap/config.json
<project>/.pi/extension-data/picc-recap/config.json
```

```jsonc
{
	"enabled": true,            // master switch
	"auto": true,               // generate after idle (vs. /away only)
	"manualCommand": true,      // enable /away
	"idleAfterSettleMs": 300000, // 5 minutes
	"model": "small-fast",     // "current" | "small-fast" | "provider/modelId"
	"fallbackToCurrentModel": true,
	"recentMessageWindow": 30,  // Claude Code: 30
	"maxTokens": 300,
	"sessionMemoryPaths": []    // optional best-effort memory file(s)
}
```

### Model

`model` accepts:

- `"current"` — the active session model.
- `"small-fast"` (default) — picks a small/fast model from the registry (heuristic on
  ids containing `haiku`/`flash`/`nano`/`mini`/`small`/`fast`/`lite`/`instant`), preferring
  the current provider. Falls back to the current model if none match.
- `"provider/modelId"` — an exact registry lookup (e.g. `"Claude/claude-haiku"`).

## Deltas from Claude Code

Pi differs from Claude Code in a few ways that cannot be replicated exactly:

- **No terminal-focus detection** — Claude Code triggers on terminal *blur* + 5 min.
  Pi has no focus events, so the trigger is an idle-after-settle timer of the same duration.
- **No per-session memory file** — Claude Code reads
  `{projectDir}/{sessionId}/session-memory/summary.md`. Pi has no equivalent; set
  `sessionMemoryPaths` to read specific files as "broader context" (best-effort, omitted
  if missing — matching Claude Code's null path).
- **No "thinking disabled" knob** in pi-ai's `complete()` — emulated with a small/fast
  model and a small `maxTokens`.
- **Display** is a TUI widget rather than a persistent transcript message, so it clears
  when you act (arguably closer to the "while you were away" intent).

## Development

```bash
npm install
npm run lint && npm run typecheck && npm run test
```

Single test: `npx vitest run test/awaySummary.test.ts`
