A session shouldn't die because a screenshot got old.
OpenCode replays the conversation on every turn. Attach enough screenshots and the provider eventually refuses the whole request:
Upstream request failed: [invalid_request_error]
Too many images in request: 39 > 30
There is no setting to raise that cap. Image Guard keeps the newest images and replaces the older ones in the outgoing request, so the session keeps moving.
Install · How it works · Options · Good to know · Development
Most providers cap how many images a single request can carry. OpenCode sends the whole session every time, so a long chat with screenshots slowly walks into that ceiling. Once it does, every new turn fails before the model even sees it.
Deleting screenshots by hand works until it doesn't. Starting over loses the thread. Image Guard is the small, boring fix: keep the newest images, drop the oldest ones from the request, and leave the session alone.
- OpenCode assembles the messages for a model request.
- Image Guard counts image parts from newest to oldest.
- The newest
maxImagesstay. - Older image parts become a short text marker:
[an older image was omitted from this request to stay within the model's image limit] - The request goes out under the cap.
Only the outgoing request changes. The session still shows every original image, and nothing is deleted from disk.
Clone it into your OpenCode plugins directory:
git clone https://github.com/HoboStank/opencode-image-guard.git \
~/.config/opencode/plugins/image-guardPowerShell:
git clone https://github.com/HoboStank/opencode-image-guard.git `
"$env:USERPROFILE\.config\opencode\plugins\image-guard"Add it to opencode.json (or opencode.jsonc):
Restart OpenCode. The defaults are already useful; the object form is only needed when you want to tune it.
| Option | Default | What it does |
|---|---|---|
maxImages |
24 |
Image parts kept per request. 0 disables the guard. |
providerID |
"opencode-go" |
Only guard this provider. Set false for every provider. |
debug |
false |
Log pruning decisions through console.error. |
The OpenCode Go cap is 30 images per request, so 29 is the highest useful value. The default of 24 leaves headroom for provider-side counting differences.
- The newest images always survive. Older ones are replaced, never silently deleted from history.
- Images returned by tools count too.
- If one message carries more than
maxImagesimages, that message's oldest images go first. - A pruning failure is logged (with
debug) and never blocks the request. - The plugin is scoped to
opencode-goby default. If your provider has a different limit, changeproviderIDor set it tofalse.
Requires Bun. OpenCode loads the TypeScript directly; there is no build step.
bun testThe tests cover image detection, counting, pruning order, shape preservation, and option normalization.
MIT. Not affiliated with OpenCode.
Built by madebyhobo · @HoebenChris
{ "$schema": "https://opencode.ai/config.json", "plugins": [ { "package": "C:\\Users\\you\\.config\\opencode\\plugins\\image-guard", "options": { "maxImages": 24 } } ] }