anomalyco / anomalyco/opencode

Session load parses summary.diffs patches from message rows; hundreds of MB of JSON per session, multi-GB heap spike on resume

Open
#50,089 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

opencode 1.18.30, macOS (Apple Silicon, 36 GB). Bun runtime.

With snapshot tracking on, each user message stores summary.diffs[].patch: the full
unified diff of every working-tree change since the previous turn. In a large working
tree the patches get enormous. One session of 68 messages holds 390 MB of message JSON;
a single message is 330 MB (24,444 file diffs: other agents sharing the same working
directory were unpacking archives during that turn). Across my store, 48 messages hold
2.2 GB (33 sessions); the part table for the same sessions is ~7 MB.

Effect: resuming a session (opencode --session <id>) parses all of it. Measured with
vmmap: 53 MB at start, 5.7 GB resident at 61 s, peak footprint 5.0 GB, settling to ~0.7 GB
after GC while idle. Sending one prompt in that session took the process to 8.2 GB.
With 13 restored sessions resuming together the machine jetsammed (44 GB across opencode
processes).

Related: the event table grows without bound (30.6 GB, 83k rows; message.updated and
message.part.updated copy the full message/part JSON per update), and a 6 h session
wrote 550 GB via WAL checkpoints.

Workarounds that hold: "snapshot": false in config stops new patches; deleting
summary.diffs from the oversized rows (json_remove) and VACUUM took the store from
2.4 GB to 220 MB with the session still exporting intact; the same session then peaks
at 750 MB instead of 5.0 GB.

Suggestions: cap or truncate stored patches (or store diffs out of the message row and
load them lazily), and bound the event table (compact or drop replayed events).

Code paths (v1.18.30 tag; same at HEAD ebb7b76)
  • packages/opencode/src/session/summary.ts summarize(): loads every message of the
    session (sessions.messages, line 116) on each turn, computes snapshot.diffFull(from, to)
    (line 98) and writes the result into the user message (target.info.summary = {..., diffs},
    line 125) via sessions.updateMessage. Nothing bounds the number of files or the total size.
  • packages/opencode/src/snapshot/index.ts diffFull: git show of the before and after
    content for every added/deleted/modified file between the two snapshot hashes. The only
    guard is the per-file limit = 2 * 1024 * 1024 (line 24) at tracking time, so a turn that
    touches thousands of files stores thousands of full-content patches.
  • packages/opencode/src/session/session.ts updateMessage (line 631): publishes
    SessionV1.Event.MessageUpdated with the whole info object, diffs included, so the event
    store persists a full copy of the payload on every update.
  • packages/opencode/src/cli/cmd/export.ts (lines 173, 207) is the only reader of
    summary.diffs besides the UI "changes" chip; the model request never uses it, which is
    why lazy-loading it out of the message row is safe.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading packages/opencode/src/session/summary.ts and packages/opencode/src/session/session.ts, then trace snapshot.diffFull in packages/opencode/src/snapshot/index.ts. Inspect packages/opencode/src/cli/cmd/export.ts to understand the summary.diffs reader. Done means resuming large sessions no longer causes the reported memory spike while session export remains intact and event growth is addressed.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, typescript
Domain
backend, databases, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.