npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-fold-diffs

v0.2.0

Published

OpenCode TUI plugin: write, edit, apply_patch and long bash commands render folded to their title line, click or ctrl+o to open them.

Readme

opencode-fold-diffs

Every write and edit dumps the whole file or the whole diff into your transcript, and stays there. So does every bash command, however long. This plugin folds those blocks down to their title line — ← Edit src/app.ts +12 −3 · click to expand — and opens them again on click, or ctrl+o for all of them at once.

opencode already does this for the tools it considers noisy: bash output collapses to 10 lines, generic tool output to 3, both with click-to-expand. The three tools that actually fill the scrollback are the ones it leaves alone. Upstream has been asked three times — #9089 (minimal diff display), #14511 (a toggle keybind, like Claude Code's ctrl+o), #19074 (collapse tool output) — and all three were closed without a setting. This is that setting, from outside.

What you see

Before:

← Edit src/session/index.ts
│  1  import { createMemo } from "solid-js"
│  2 -  const [expanded, setExpanded] = createSignal(false)
│  3 +  const [expanded, setExpanded] = createSignal(props.open)
│  … 40 more lines

After:

← Edit src/session/index.ts +12 −3 · click to expand

Bash commands fold the same way, to their first line. opencode trims what a command printed — ten lines, with click-to-expand — but never the command that printed it, so a heredoc'd throwaway script keeps its full height forever:

$ /repos/app/.venv/bin/python - <<'PY'          $ /repos/app/.venv/bin/python - <<'PY'
                                                from PIL import Image
Traceback (most recent call last):              import numpy as np
  File "<stdin>", line 7, in <module>           im = Image.open('spectrum.png')
ValueError: cannot reshape array of size…       … 8 more lines
                                                
        folded (the default)                    Traceback (most recent call last):
                                                  File "<stdin>", line 7, in <module>
                                                ValueError: cannot reshape array of size…

The output is untouched either way — you still see what happened, just not the script that did it.

Click the row to open it. ctrl+o folds or unfolds every block in the session, and sets what newly arriving blocks do — same as a verbose toggle.

Install

opencode plugin opencode-fold-diffs -g

That installs the package into your global OpenCode config and adds it to tui.json. Drop -g for the current project only. Restart OpenCode afterwards; plugins load at startup.

Without npm

mkdir -p ~/.config/opencode/tui-plugins
curl -fsSL https://raw.githubusercontent.com/tannerbruhn/opencode-fold-diffs/main/index.js \
  -o ~/.config/opencode/tui-plugins/fold-diffs.js

Then add it to ~/.config/opencode/tui.json:

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": ["./tui-plugins/fold-diffs.js"]
}

Do not put the file in ~/.config/opencode/plugin/. That directory is auto-discovered for server plugins and will load it the wrong way.

Options

"plugin": [["opencode-fold-diffs", { "lines": 3, "min_lines": 10, "key": "ctrl+f" }]]

| Option | Default | Meaning | |---|---|---| | lines | 0 | Lines of the body left showing when folded. 0 is the title only, and also tightens the block's padding so it occupies one row. Any positive number leaves a peek at the top. | | min_lines | 6 | Blocks with fewer changed lines than this are left alone — a two-line edit is already its own summary. | | stats | true | Append +12 −3 · click to expand to the title. | | folded | true | Whether blocks start folded. false gives you only the toggle. | | key | "ctrl+o" | Binding for fold/unfold-all. ctrl+o is unbound in opencode; Claude Code uses it for the same thing. Set to "" for none. | | bash | true | Fold long bash commands too. false leaves every bash block exactly as the host draws it. | | bash_lines | 1 | Rows of the command left showing when folded. 1 keeps the line that says what the thing was. Commands shorter than min_lines are never folded. |

What it does not touch

  • Permission dialogs. The diff you approve renders in full, always. The plugin only ever walks inside the transcript scrollbox, and the permission preview is not in it.
  • Diagnostics and errors. Only the children carrying a diff or a file body get folded, so an edit that introduced a type error still says so with the block closed.
  • Bash output, and the click that expands it. Only the command folds; the output keeps the host's ten-line collapse. opencode puts its own click handler on a bash block to expand that output, and opentui declares onMouseUp as a setter with no getter — so a handler cannot be read back and chained, and overwriting one destroys it. This plugin attaches to the command text instead and calls stopPropagation(): clicking the command folds the command, clicking anywhere else in the block does exactly what it did before.
  • Todos, questions, and the generic fallback. They keep the host's own collapse behaviour. Matching is on the six BlockTool titles the file tools use (← Edit, # Wrote, ← Patched, # Created, # Deleted, # Moved), plus the $ a bash block prefixes its command with.

How it works, for anyone extending it

The TUI plugin API has no slot for message parts — sidebar_content, session_prompt_right, app, app_bottom and the home_* slots are the whole list — so a plugin cannot render a tool part itself. It has to reach the renderables the host already made:

  1. Find the transcript: the only scrollbox in the tree with stickyScroll && stickyStart === "bottom". The sidebar, dialogs, autocomplete and diff viewer all have scrollboxes; none of them are sticky.
  2. Find the blocks: a node whose first child's plainText starts with one of the six titles. Bash blocks carry no title at all — BlockTool renders one only when the tool ran in another workdir — so they are found by shape: the first child that has children of its own, whose own first child is the $ -prefixed command. Do not count children to find it; solid's <Show> leaves childless placeholders, so a bash block reports three children with no title present.
  3. Fold: maxHeight = 0 and overflow = "hidden" on the children carrying the bulk. Yoga accepts a zero max-height, so the body leaves layout instead of leaving a hole.
  4. Size a command by max(source lines, node.height). height is the laid-out row count, which catches a one-line command long enough to wrap, but it reads 0 for anything the virtualised transcript has not laid out — so the line count is the floor, not the other way round.
  5. Toggle: assign onMouseUp on the block. The solid adapter sets that as a plain property, so a plugin can set it the same way — it replaces BlockTool's own handler, which is why the copy-on-select guard is reimplemented here.

Classes are matched by duck-typing (typeof node.diff === "string", content + filetype for code) rather than instanceof, because the opentui classes are minified in the shipped binary and their names are not stable.

Blocks are re-scanned on message.part.updated and message.updated, plus a 2 s sweep that catches a session opened from history, whose parts land before any event this plugin sees.

Status

Written against opencode 1.18.28. The tree-walking, block matching, fold/unfold and toggle logic run green against a mock renderer tree (node --test test/), and every renderable property it touches was checked against the shipped binary: maxHeight and overflow are yoga setters, onMouseUp is a setter with no getter, plainText is a getter on text renderables, and height is a getter that reads 0 until the transcript lays a node out.

Bash folding was additionally checked in a real terminal against a real session: a ten-line heredoc laid out at one row with its traceback still fully visible, and ctrl+o restored the body. The rest of this table is still worth a pass on first run, since none of it is what a mock can prove:

| Case | Expected | |---|---| | edit completes | Folds to the title with +n −n | | write completes | Folds to the title with n lines | | apply_patch over 3 files | Each file's block folds on its own | | Click a folded block | Opens; click again to close | | Select text across a block | Copy-on-select still works, no toggle | | ctrl+o | Folds/unfolds all, and sets the default for new blocks | | Edit with diagnostics | Diagnostics stay visible while folded | | Permission dialog | Full diff, untouched | | A long bash command | Folds to its first line; the output stays as the host left it | | Click a folded command | Opens just that command | | Click a bash block's output | Still expands the output, as it did before | | A short or still-running command | Left alone |

If the title never grows its +12 −3 suffix, solid is holding that text node and the plugin has stopped trying to write it; everything else still works. Set "stats": false to skip it.

License

MIT