pi-cap-context-images

Bound the number of images kept in a pi session's outgoing provider payload. Prevents the 'infinite compaction' loop caused by base64 screenshots (browser/winshot/image tools) accumulating in context — compaction can summarize text but can only keep or dr

Packages

Package details

extension

Install pi-cap-context-images from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-cap-context-images
Package
pi-cap-context-images
Version
0.1.0
Published
Jun 2, 2026
Downloads
not available
Author
blue-b
License
MIT
Types
extension
Size
17.9 KB
Dependencies
0 dependencies · 1 peer

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-cap-context-images

Stop long pi coding agent sessions from getting stuck in an endless compaction loop when screenshots pile up. Keeps only the most-recent images on the wire to the model, so accumulated base64 captures can never blow past the context limit.

English | 한국어

License: MIT Platform GitHub stars GitHub issues

Zero dependencies, ~100 lines. One before_provider_request hook, no native modules, no extra services.

Why

Tools like browser automation (pi-playwright) and screen capture (pi-winshot) hand the model base64 images. In a long session these stack up — and here's the trap:

Compaction can summarize text, but it cannot shrink an image. It can only keep an image whole or drop it whole.

Once a few dozen screenshots are sitting in the verbatim "recent" region that compaction preserves, every compaction pass keeps them all. tokensBefore never falls below the threshold, so the agent compacts again… and again… forever.

This is not hypothetical. A single real session accumulated 51 images ≈ 4.5 MB and fired 6 back-to-back compactions at ~900K–968K tokens that never converged — the session was effectively frozen.

pi-cap-context-images removes the root cause: it caps how many images ever reach the provider, so token usage stays bounded and compaction can actually do its job.

How it works

pi fires before_provider_request with the full outgoing payload and lets an extension return a modified copy — the same public hook the built-in sanitize-tool-call-ids extension uses. On every request this extension:

  1. walks the payload in document order and finds every image content block,
  2. keeps the most-recent N images (default 3),
  3. replaces the older ones with a one-line text placeholder.
 conversation (oldest → newest)
 ┌────────────────────────────────────────────────┐
 │ 🖼  🖼  🖼  🖼  🖼  🖼  🖼   🖼   🖼   🖼 │
 │  ↓   ↓   ↓   ↓   ↓   ↓   ↓                       │
 │ [placeholder × 7]            🖼  🖼  🖼          │  → sent to model
 └────────────────────────────────────────────────┘
                                  └── KEEP_IMAGES (3) ──┘

The model still sees your latest screenshots, so active visual work keeps working — only the stale ones are dropped from the wire payload.

Only the outgoing payload is touched. The persisted session .jsonl is left intact, so your transcript and scrollback still show every screenshot you ever captured.

Image block shapes handled: pi-internal {type:"image", data, mimeType}, Anthropic {type:"image", source:{…}}, and OpenAI {type:"image_url", image_url:{…}}.

Install

pi install pi-cap-context-images
/reload

or from a clone:

git clone https://github.com/Blue-B/pi-cap-context-images
pi install ./pi-cap-context-images
/reload

or, if you keep local packages, add the folder to packages in your pi settings.json (path is relative to the settings file):

{
  "packages": [
    "../../projects/pi-cap-context-images"
  ]
}

Requirements

  • pi coding agent ≥ 0.70.
  • Nothing else — it's a single hook with no runtime deps.

Config

Env var Default Meaning
PI_CAP_CONTEXT_IMAGES 3 How many of the most-recent images to keep on the wire. 0 strips every image.
PI_CAP_CONTEXT_IMAGES=5 pi   # keep the last 5 screenshots instead of 3

Project layout

pi-cap-context-images/
├── package.json
├── extensions/cap-context-images/index.ts   # the before_provider_request hook
├── README.md
└── LICENSE

Revert

Remove the packages entry (or pi uninstall pi-cap-context-images) and /reload.

Sponsor

GitHub Sponsors Buy Me A Coffee PayPal

If this extension saved your session from an infinite-compaction freeze, supporting the project directly funds maintenance:

  • Your support helps: keeping the image-block detection in sync as pi and provider payload formats evolve, testing across providers (Anthropic / OpenAI / bridge), and faster issue response.
  • Transparency: funds go to maintenance time and testing infra. One-time donations stay one-time — no obligations.
  • Monthly sponsors ($3/mo via GitHub Sponsors) get best-effort priority triage for "Sponsor Request" issues.

License

MIT