@zhcsyncer/pi-recap

Recent activity recap extension for Pi with optional session title and tmux window sync.

Packages

Package details

extension

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.2.0
Published
Jul 18, 2026
Downloads
759/mo · 480/wk
Author
zhcsyncer
License
MIT
Types
extension
Size
49.9 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 current 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@v0.2.0

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:

  1. collect recent activity since the previous recap;
  2. call a model to generate a one-line recap;
  3. generate a short title;
  4. persist state with pi.appendEntry("recap", ...);
  5. display the recap in an editor widget;
  6. optionally apply the title to the Pi session name;
  7. optionally sync the session name to the current tmux window.
/recap-config

Open the TUI config screen and save common settings to:

~/.pi/agent/recap.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/agent/recap.json
.pi/recap.json

Project-local .pi/recap.json is read only when the project is trusted, and it overrides global config.

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
  },
  "tmux": {
    "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.

Customize tmux window name:

{
  "tmux": {
    "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.

tmux behavior

When tmux.enabled is true:

  • It only runs when process.env.TMUX exists.
  • It disables automatic-rename for the current tmux window to avoid shell-command overwrites.
  • It renames the current tmux window when Pi session name changes.
  • If restoreOnShutdown is true, it restores the previous window name and automatic-rename setting when Pi exits.

All of these trigger tmux sync:

pi --name "auth refresh"
/name auth refresh

and recap calling pi.setSessionName(title) when enabled by config.

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"
  }
}