@zhcsyncer/pi-recap
Recent activity recap extension for Pi with optional session title and Herdr/tmux name sync.
Package details
Install @zhcsyncer/pi-recap from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@zhcsyncer/pi-recap- Package
@zhcsyncer/pi-recap- Version
0.4.0- Published
- Jul 28, 2026
- Downloads
- 964/mo · 205/wk
- Author
- zhcsyncer
- License
- MIT
- Types
- extension
- Size
- 70.2 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./extensions/recap.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-recap
pi-recap is a Pi extension that generates a recent activity recap. It is not compaction and does not replace or shrink the LLM context.
Features:
- Generate a recent activity recap with
/recap. - Automatically recap after the agent has been idle for a while.
- Cancel an unfinished automatic recap when a new message arrives, preventing stale results from being stored or displayed.
- Display automatic recap progress plus recap results and errors in an editor widget, without duplicating successful results in chat notifications.
- Generate a short title as a recap side effect.
- Optionally apply the title to the Pi session name.
- Optionally sync Pi session name changes to the nearest terminal multiplexer: a Herdr pane label or tmux window name.
- Configure common options with
/recap-config. - Edit full JSON config with
/recap-config json.
Installation
Install the whole zhcsyncer/pi-extensions bundle from Git:
pi install git:github.com/zhcsyncer/pi-extensions
Try without installing:
pi -e git:github.com/zhcsyncer/pi-extensions
Install from npm:
pi install npm:@zhcsyncer/pi-recap
Local development:
pi -e ./packages/pi-recap
Commands
/recap
Generate a recent activity recap. It will:
- collect recent activity since the previous recap;
- call a model to generate a one-line recap;
- generate a short title;
- persist state with
pi.appendEntry("recap", ...); - display the recap in an editor widget;
- optionally apply the title to the Pi session name;
- optionally sync the session name to the nearest Herdr pane or tmux window.
/recap-config
Open the TUI config screen and save common settings to:
$PI_CODING_AGENT_DIR/extension-data/pi-recap/config.json
/recap-config json
Edit the full JSON config.
TUI only
recap only runs in Pi TUI mode. Headless modes such as print, json, and rpc are skipped to avoid extra model calls, session writes, or naming side effects in scripts and multi-instance environments.
Config files
The extension reads:
$PI_CODING_AGENT_DIR/extension-data/pi-recap/config.json
.pi/extension-data/pi-recap/config.json
Project-local .pi/extension-data/pi-recap/config.json is read only when the project is trusted, and it overrides global config. On first load, the previous global and trusted-project paths are automatically migrated and upgraded; unmappable fields are dropped with a warning, and malformed files are preserved.
See example config:
examples/recap.json
Default config:
{
"recap": {
"enabled": true,
"auto": true,
"manualCommand": true,
"idleAfterTurnMs": 180000,
"minSessionTurns": 3,
"neverTwiceInARow": true,
"model": "current",
"fallbackToCurrentModel": true,
"maxRecentChars": 20000,
"maxTokens": 300,
"language": "auto"
},
"display": {
"widgetPlacement": "aboveEditor"
},
"title": {
"generate": true,
"applyToSessionName": false,
"applyPolicy": "if-empty-or-auto",
"maxLength": 50
},
"multiplexer": {
"enabled": true,
"template": "π {session} · {project}",
"maxLength": 48,
"restoreOnShutdown": true
}
}
Common config
Apply generated titles to Pi session names:
{
"title": {
"applyToSessionName": true,
"applyPolicy": "if-empty-or-auto"
}
}
Disable automatic recap and keep manual /recap only:
{
"recap": {
"auto": false
}
}
Use a specific recap model:
{
"recap": {
"model": "google/gemini-2.5-flash",
"fallbackToCurrentModel": true
}
}
Choose widget placement:
{
"display": {
"widgetPlacement": "aboveEditor"
}
}
Recap display always uses an editor widget; the display surface is not configurable. Automatic recap progress is replaced by the result in that widget. Manual /recap uses a cancellable loader while generating, then shows the result in the widget. The widget is cleared when the next message starts. If an automatic recap is still running, it is cancelled and cannot later store or redisplay a stale result.
When an older config is loaded, obsolete display.notify, display.mode, display.widget, and display.clearWidgetOnNextAgentStart fields are removed and the source config file is updated. display.widgetPlacement is preserved. Legacy tmux settings are migrated to multiplexer; when both exist, explicitly configured multiplexer fields take precedence.
Customize the Herdr pane label or tmux window name:
{
"multiplexer": {
"template": "π {project} · {session}",
"maxLength": 60
}
}
Supported variables:
{session}
{project}
{cwd}
{id}
Language
recap.language defaults to:
{
"recap": {
"language": "auto"
}
}
auto asks the model to use the same primary language as the recent activity. You can also force a language:
{
"recap": {
"language": "zh-CN"
}
}
or:
{
"recap": {
"language": "en"
}
}
Note: Pi currently does not expose a user language or locale field to extensions. This is an extension-level setting.
Terminal multiplexer behavior
When multiplexer.enabled is true, recap automatically selects the directly hosting layer:
HERDR_ENV=1with a non-emptyHERDR_PANE_IDselects the current Herdr pane label. TheherdrCLI must be available; Herdr may provide its absolute path throughHERDR_BIN_PATH.- If Herdr is not detected and
TMUXexists, recap selects the current tmux window name. - Otherwise, naming is a no-op.
In nested Herdr-inside-tmux sessions, recap only updates the Herdr pane. If Herdr is detected but its pane identity is incomplete or its CLI is unavailable, recap warns once and does not fall back to the inherited tmux layer.
For tmux, recap keeps the original behavior of disabling automatic-rename while it owns the window name. The original pane/window name is restored only if the current name still equals recap's last successful write, so a later manual rename is preserved. Disabling sync or reloading the extension releases ownership immediately; reload always restores before the new extension instance reapplies the name. On ordinary Pi exit, restoreOnShutdown controls restoration. tmux's captured automatic-rename setting is restored whenever owned sync is restored or disabled.
All of these trigger multiplexer sync:
pi --name "auth refresh"
/name auth refresh
and recap calling pi.setSessionName(title) when enabled by config. Recap does not modify Herdr's Pi agent-state integration.
Privacy and cost
- Recap makes an extra model call.
- By default it uses the current Pi model:
recap.model = "current". - Recent activity is sent to the current or configured provider.
- Disable automatic recap if you do not want extra background model calls:
{
"recap": {
"auto": false
}
}
Not compaction
pi-recap does not:
- call Pi compact;
- replace LLM history;
- inject recap into future LLM context;
- delete or compress session messages.
Recap history is persisted as extension state with pi.appendEntry("recap", ...) and does not participate in LLM context.
Discoverability in the Pi package gallery
Pi docs state that the package gallery displays packages tagged with the pi-package keyword. For public discovery, publish a public npm package and include:
{
"keywords": ["pi-package"]
}
Also include a pi manifest:
{
"pi": {
"extensions": ["./extensions/recap.ts"]
}
}
Optional gallery preview image:
{
"pi": {
"extensions": ["./extensions/recap.ts"],
"image": "https://example.com/screenshot.png"
}
}
or MP4 video:
{
"pi": {
"extensions": ["./extensions/recap.ts"],
"video": "https://example.com/demo.mp4"
}
}