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-herdr-bridge

v0.3.0

Published

Aggregate opencode session state for Herdr so multi-session panes report accurately.

Readme

opencode-herdr-bridge

ci npm license

Corrects how Herdr sees opencode panes.

Problem

One opencode process can hold several root sessions (ctrl+x n). Herdr tracks state per pane, and the official opencode integration reports state from whichever session emits an event. When a background session finishes while you are working in another session, the pane flips to idle/done even though your session is still running.

Repro (herdr 0.9.1, opencode 1.18.31): session A running sleep 90, session B finishing in the same process, herdr agent list polled per second:

21:24:23 working seq=37 sess=…0M71Xe
21:24:25 idle    seq=38 sess=…HuH58V   <- B finished, pane reported idle
21:24:27 idle    seq=38 sess=…0M71Xe
21:24:28 working seq=39 sess=…0M71Xe   <- A was working the whole time

What this plugin does

It keeps a model of every root session in the pane and reports one aggregated state to Herdr:

  • blocked if any session is waiting on a permission or question
  • working if any session is working (or any child session is asking)
  • idle only when every session is idle

Session identity reported to Herdr follows the most recently active root session. State is only reported when the aggregate changes, so the socket stays quiet.

Beyond the aggregate state:

  • Zero-config label — the sidebar agent label becomes opencode ×3 for multi-session panes and opencode ×3 · waiting when a session needs input. No config edits required.
  • Sidebar tokens — optional $oc_sessions / $oc_attention tokens if you want counts in a custom row layout.
  • Session-aware notifications — when a session becomes blocked, Herdr shows a notification naming the session title (on by default, no sound).
  • Self-correcting — if the official integration overwrites the pane after a background session finishes, the bridge reads the pane back and restores the aggregate within ~150 ms, with a slow reconcile while work is active.

Configuration

Optional file at ~/.config/opencode/herdr-bridge.json:

{
  "notify": "blocked",
  "sound": "none",
  "display": true
}
  • notify: "off" | "blocked" (default) | "all" — all also notifies when any session finishes, whether or not it is the one you are viewing.
  • sound: "none" | "auto" (default) | "done" | "request" — auto uses the request sound for waiting sessions and the done sound for finished ones.
  • display: false disables the opencode ×N label.

Notifications are per session and name the session title, so a background session finishing or asking a question pings you while you work in another session.

Legacy env overrides still work: HERDR_BRIDGE_NOTIFY=1, HERDR_BRIDGE_SOUND, HERDR_BRIDGE_DISPLAY=0, plus HERDR_BRIDGE_DEBUG=1 for tracing.

Sidebar tokens (optional)

The zero-config label needs nothing. If you want counts in a custom row layout, the bridge also reports $oc_sessions (2 working · 1 waiting style) and $oc_attention (waiting while any session is blocked):

[ui.sidebar.agents]
rows = [
  ["state_icon", "machine", "workspace", "tab"],
  ["agent"],
  [{ token = "$oc_sessions", dim = true }, { token = "$oc_attention", fg = "#f9e2af", bold = true }],
]

Then herdr server reload-config. Full example in examples/herdr-sidebar.toml.

Install

npm install -g opencode-herdr-bridge

Or add it to opencode's plugin list in ~/.config/opencode/opencode.json:

{ "plugin": ["opencode-herdr-bridge@latest"] }

Or symlink the entry point directly:

git clone https://github.com/anaypurohit0907/herdr-opencode-bridge
ln -s "$(pwd)/herdr-opencode-bridge/src/index.js" \
      ~/.config/opencode/plugins/zz-herdr-opencode-bridge.js

The zz- prefix makes opencode load this plugin after the official herdr-agent-state.js integration, so its reports land last.

Restart opencode. The plugin is inert outside Herdr-managed panes.

Development

bun test

Set HERDR_BRIDGE_DEBUG=1 when launching opencode to append a trace to /tmp/opencode/herdr-opencode-bridge.log (events, aggregate changes, report results, and self-corrections).

All state logic lives in src/aggregate.js with no opencode imports, so it is unit-testable. src/index.js is a thin V1 server-plugin wrapper; src/socket.js speaks the newline-delimited JSON pane protocol.

Verification

Live run with session A inside sleep 90 and session B (sleep 20) finishing in the same process while A was viewed. herdr agent list polled once per second; the bridge log is HERDR_BRIDGE_DEBUG=1 output:

16:35:16 report state=working seq=…1002 ok=true 2 working
16:35:17 verify mismatch expected=working actual=idle -> correcting
16:35:19 verify mismatch expected=working actual=idle -> correcting
16:35:20 verify mismatch expected=working actual=idle -> correcting
16:36:50 report state=working seq=…1008 ok=true 1 working · 1 idle   <- B finished
16:36:55 report state=idle    seq=…1009 ok=true 2 idle               <- A finished

Pane state timeline (one sample per second): working held continuously for the 94 seconds covering B's finish. Before the bridge the same reproduction flashed idle for ~2 seconds at that moment (see herdrdev/herdr#4454).

Known cosmetic race: during the burst where a session is created while another is already working, the official reporter can still win one round and show idle for up to ~1 second before the correction pass restores working.

Background

Reported upstream as herdrdev/herdr#4454 and triaged bug / p2 / maintainer-needed. This plugin is the user-space fix for the same problem while the official integration decides its own semantics.

Roadmap

  • subscribe to herdr events.subscribe to correct drift event-driven instead of polling
  • TUI-side selection reporting (V2) so session identity follows the visible session

License

MIT