Skip to content

perf: ImageAddon defaults to 128 MB storage per pane — multi-pane sessions can hit GBs #565

@Axelj00

Description

@Axelj00

Problem

`src/pane-webgl.ts:115` constructs the xterm.js `ImageAddon` with no options:

```ts
const img = new ImageAddon();
```

Per the addon's type definitions (`@xterm/addon-image/typings/addon-image.d.ts:51`):

`storageLimit` — Storage limit in MB. The storage implements a FIFO cache removing old images, when the limit gets hit. Default is 128 MB.

That's 128 MB of image bitmap retention per pane. The user's mental model of a 4-tab × 2-pane workspace running Claude Code that occasionally renders screenshots (sixel / iTerm2 inline images) suddenly tops out at 8 × 128 MB = 1 GB just for image storage, on top of scrollback + Chromium baseline + Rust process.

The storage is FIFO-evicted within the 128 MB cap, but the cap itself never shrinks, and nothing tells the user about it. A single 100 MB screenshot pins the pane at 100 MB forever (until tab close / pane dispose deactivates the addon).

Why this matters now

Agent workflows have grown to include image output:

  • Claude Code with `--allow-screenshots` produces base64 PNGs via OSC 1337 (iTerm2 IIP).
  • Tools that pipe image previews (`imgcat`, `viu`, sixel emitters from `gnuplot` / `mpv` / `yt-dlp`).
  • Agent screenshots committed to scrollback as inline images.

ClawTerm advertises itself as the terminal for running many AI agents. The default 128 MB cap multiplied by typical pane counts is a real cost the user pays without ever opting in.

Proposal

Three options, each shipping independently:

1. Lower the default cap (cheapest, behavior change)

```ts
const img = new ImageAddon({ storageLimit: 32 });
```

32 MB per pane is still 8 × a single moderate screenshot, but caps the worst-case at ~256 MB across an 8-pane workspace. Trade-off: long agent sessions that produce many screenshots will see older ones replaced with the placeholder glyph sooner.

2. Config-driven (gives users a knob)

Add `pane.imageStorageLimitMb: number` (default 32) to `config-types.ts`. Users running image-heavy workflows can bump it; users running text-only agents can drop it to 0 (effectively disable).

3. "Reset images" command (manual escape hatch)

Surface `imageAddon.reset()` via the command palette and/or right-click pane menu. Lets a user reclaim the memory without closing the pane or tab.

Suggest (1) + (3) for v1 — lower the default and add a manual reset. (2) is the right shape long-term but a config field is more surface area than this needs to start.

Verification path

Before merging the default change, do a memory comparison:

  1. Open Activity Monitor → ClawTerm RSS at startup.
  2. Open 4 tabs, run a Claude session in each that includes `imgcat ~/Downloads/test-screenshot-5mb.png`.
  3. Note the RSS plateau.
  4. Apply the storageLimit change, repeat.

If the plateau shrinks proportionally to the cap, the fix is working as intended.

References

Out of scope

  • Disposing ImageAddon on tab hide (analogous to scrollback compaction). Would force re-decode of every image on tab return, breaking the "click around panes" UX. The cap-then-evict approach trades less obtrusively.
  • Replacing ImageAddon entirely. xterm.js has no built-in image support; the addon is the only practical option.

Metadata

Metadata

Assignees

No one assigned

    Labels

    memory-leakResource leaks and cleanup issuesperformancePerformance improvementspriority: highShould be addressed soon

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions