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

@agent-ops/synadia-agent-shim

v1.1.0

Published

Synadia Agent Protocol v0.3 shim — wraps agent CLIs (claude-code, codex, pi, gemini) and exposes them on a NATS bus.

Readme

synadia-agent-shim

A Go shim that wraps an agent CLI (claude-code, codex, pi, gemini, or any custom adapter) and exposes it on a NATS bus using the Synadia Agent Protocol v0.3.

Operators publish a prompt on agents.prompt.<token>.<owner>.<pane>; the shim translates it into the CLI's native invocation, streams chunks back, and emits heartbeats + status per spec. Control-plane verbs (interrupt, redirect) are routed via orch.signal.>.

Extracted from danmestas/orch; see docs/proposals/0001-extract-synadia-agent-shim.md for the rationale.

Install

As a binary (npm)

npm install -g @agent-ops/synadia-agent-shim

The postinstall script fetches the matching release binary for your OS/arch and places it at vendor/synadia-agent-shim. Two wrapper scripts are exposed on $PATH:

  • synadia-agent-shim — canonical
  • orch-agent-shim — backwards-compat alias for one orch major release

As a Go library

go get github.com/danmestas/synadia-agent-shim/shim
go get github.com/danmestas/synadia-agent-shim/adapter/echo

Usage (CLI)

synadia-agent-shim --agent claude-code --locator tmux:%37
synadia-agent-shim --agent claude-code --locator cmux:surface:30
synadia-agent-shim --agent claude-code --locator zmx:engineer-a
synadia-agent-shim --agent claude-code --pane %37     # deprecated alias for --locator tmux:%37

Resolution order (most explicit wins):

| Setting | Source | | --- | --- | | NATS URL | --nats$NATS_URL~/.sesh/hub.nats.urlnats://127.0.0.1:4222 | | Owner | --owner$ORCH_OWNER$USER/etc/passwd lookup | | Session | --session$SESH_SESSION → omitted from metadata | | Instance ID | --instance-id → omitted (no slug-keyed subjects) | | CWD | --cwdtmux display-message -p '#{pane_current_path}' | | Locator | --locator--pane (deprecated; infers tmux:) → autodetect via $CMUX_SURFACE_ID / $ZMX_SESSION / $TMUX_PANE |

The shim exits when the bound pane dies (SIGCHLD from the parent shell). orch-spawn backstops this by wait-ing on a sentinel pid. The pane-watchdog (tmux display-message poll) currently only runs under the tmux engine; cmux and zmx manage surface lifetime themselves.

Engine support matrix

The shim dispatches the inbound-prompt send-verb based on the persistence engine it's running under. The engine is detected from env vars at startup, or set explicitly via --locator.

| Engine | Detection (env) | Locator form | Send verb | Interrupt verb | | --- | --- | --- | --- | --- | | tmux | $TMUX_PANE (preferred) or $TMUX | tmux:%37 | tmux send-keys -l -t %37 <text> + tmux send-keys -t %37 Enter | tmux send-keys -t %37 C-c | | cmux | $CMUX_SURFACE_ID | cmux:surface:30 or cmux:<UUID> | cmux send --surface <ref> -- <text>\n | cmux send-key --surface <ref> ctrl+c | | zmx | $ZMX_SESSION | zmx:engineer-a | zmx send <session> <text>\r | zmx send <session> $'\x03' |

Detection precedence: cmux → zmx → tmux (most-specific first; cmux and zmx pane environments sometimes also expose $TMUX, so engine-specific markers win).

Heartbeats and $SRV.INFO.agents metadata publish both the new engine and locator fields alongside the back-compat pane_id:

{
  "metadata": {
    "agent": "claude-code",
    "owner": "tester",
    "pane_id": "surface:30",
    "engine": "cmux",
    "locator": "cmux:surface:30"
  }
}

pane_id will be retired once downstream registry consumers (orch-registry) adopt locator. The dual surface mirrors the --instance-id dual-publish window.

--pane deprecation

--pane VALUE continues to work and is interpreted as --locator tmux:VALUE, with a one-line stderr deprecation notice on startup. It will be removed in the next shim release (see CHANGELOG.md). Callers should migrate to --locator.

--instance-id

--instance-id <slug> attaches a human-readable worker identity to the shim. Subject-safe charset [a-zA-Z0-9._-], length 1-128 — invalid slugs are rejected at startup so a typo fails loud, not at first publish.

When set, the shim:

  1. Adds instance_id: "<slug>" to $SRV.INFO.agents metadata alongside the existing pane_id. Discovery tools can filter by either; pane_id stays so pane-watchdog and tmux send-keys consumers keep working.
  2. Registers a SECOND prompt + status endpoint on the slug-keyed subjects:
    • agents.prompt.<token>.<owner>.<slug>
    • agents.status.<token>.<owner>.<slug>
  3. Publishes heartbeats on the slug-keyed subject too:
    • agents.hb.<token>.<owner>.<slug>

Dual-publish is gated by env var ORCH_SLUG_DUAL_PUBLISH:

| Value | Behavior (with --instance-id set) | | --- | --- | | unset / 1 | legacy pct<N> track + slug track both live (default — safe during rollout) | | 0 | slug track only; legacy pct<N> subjects have no subscriber |

When --instance-id is not set, the shim runs as before — only the legacy pct<N>-keyed track is registered, regardless of the env var.

The dual-publish window is intended to last two releases; the legacy pct<N> track will be retired in a follow-up issue. Track the deprecation in CHANGELOG.md.

Usage (Go SDK)

package main

import (
    "context"
    "log"

    "github.com/danmestas/synadia-agent-shim/adapter/echo"
    "github.com/danmestas/synadia-agent-shim/shim"
)

func main() {
    cfg := shim.Config{
        Agent:   "echo",
        Pane:    "%1",
        Owner:   "you",
        NATSURL: shim.ReadNATSURL(""),
        Adapter: echo.New(),
        // SubjectPrefix defaults to "agents".
        // SignalPrefix defaults to "orch.signal".
    }
    if err := shim.Run(context.Background(), cfg); err != nil {
        log.Fatal(err)
    }
}

Non-orch consumers can retarget the namespace:

cfg.SubjectPrefix = "dagnats"      // dagnats.prompt.*, dagnats.status.*, ...
cfg.SignalPrefix  = "dagnats.signal"

Writing a custom adapter

See docs/adapter-sdk.md. Minimal contract:

type Adapter interface {
    Start(ctx context.Context) error
    OnPrompt(ctx context.Context, prompt string) error
    Events() <-chan Chunk
    Close() error
}

Adapters that need imperative interrupt (TUI harnesses that don't honour ctx.Done()) implement the optional Aborter interface — the shim type-asserts and calls Abort on orch.signal.interrupt arrival.

Built-in adapters

Versioning

  • shim v1.0.0 = current behavior at extraction time from orch
  • Each Synadia spec version bump → shim major version bump
  • Adapter API additions → minor version bump
  • Bug fixes → patch

The Adapter and Config shapes are frozen at v1.

Releasing

Releases are tag-driven. Pushing an annotated tag vX.Y.Z triggers .github/workflows/release.yml:

  1. goreleaser builds platform archives + creates the GitHub Release.
  2. publish-npm syncs package.json version from the tag, then runs npm publish --access public.

To cut a release:

git tag vX.Y.Z
git push --tags

One-time operator setup: set the NPM_TOKEN secret in the repo's GitHub settings (Settings → Secrets → Actions) with an npm automation token that has publish access to @agent-ops/synadia-agent-shim. PRs run npm publish --dry-run in CI to catch packaging breakage before a tag is pushed.

Wire surface

  • Service name: <SubjectPrefix> (default agents), per Synadia §3.1
  • Prompt subject: <SubjectPrefix>.prompt.<token>.<owner>.<session-or-pane>
  • Status subject: <SubjectPrefix>.status.<token>.<owner>.<session-or-pane>
  • Heartbeat: <SubjectPrefix>.hb.<token>.<owner>.<session-or-pane> every 30s
  • Signal: <SignalPrefix>.<verb>.<token>.<owner>.<pane> (orch#133)

Envelope headers: W3C traceparent + Sesh-Task-Id / Sesh-Attempt when set. See docs/architecture.md for the full layout.

License

Apache-2.0. See LICENSE.