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

@nvergez/orchestrator

v0.6.1

Published

Slack-driven orchestrator-dispatcher daemon: one Claude Code session per Slack thread, delegating work to Orca worktree agents.

Readme

orchestrator

npm version CI

A Slack-driven orchestrator-dispatcher daemon: one Claude Code session per Slack thread, delegating work to Orca worktree agents. Mention the bot in a channel, describe what you want, and it routes the request to the right repo, dispatches a worker agent in its own worktree, supervises it (questions and escalations relayed back into the thread), and reports the result. Small-team by design: one workspace, the channels you configure, and a shared allow-list of authorized users — anyone else gets one polite refusal.

How it works

The daemon is a single long-lived Node process. It connects to Slack over Socket Mode (no inbound URL) and gives a Claude Code agent a Slack presence — each thread gets its own persistent session, resumable across restarts. The orchestrator never writes code itself: it interprets requests, delegates to Orca worktree agents on an allow-listed set of repos, watches their structured messages (done / blocked / question), and relays anything that needs a human back into the thread. State (sessions, delegations, pending gates) lives in a local SQLite database, so a restart loses nothing.

The full architecture deep-dive is in docs/spec.md.

Prerequisites

  • Linux with systemd user services. On other platforms (or without systemd) run orc in the foreground under your own supervisor — see docs/operations.md.
  • Node.js ≥ 22.18.
  • Orca — the orca CLI installed and the runtime running on the same machine. Hard prerequisite: the daemon delegates all work to Orca worktree agents.
  • A Claude subscription with the Claude Code CLI. Run claude setup-token to mint the long-lived sk-ant-… OAuth token the daemon authenticates with. The daemon is subscription-billed — API-key billing is not supported (CLAUDE_CODE_OAUTH_TOKEN is hard-required). The token acts as your account: treat it like a password, and expect daemon usage to share your subscription's rate limits.
  • A Slack workspace where you can create an app. Walkthrough with a ready-to-paste manifest: docs/setup-slack.md.

Install

npm install -g @nvergez/orchestrator   # 1
orc init                               # 2
$EDITOR ~/.config/orchestrator/env ~/.config/orchestrator/routing-hints.json  # 3
orc doctor                             # 4
orc service install                    # 5
sudo loginctl enable-linger $USER      # 6 — once
  1. Installs the daemon and the orc CLI.
  2. Creates ~/.config/orchestrator/ and scaffolds the two config files (never overwrites existing ones).
  3. Fill in your tokens and Slack IDs in env (see docs/setup-slack.md) and your delegable repos in routing-hints.json.
  4. Checks the whole setup read-only — env vars, hints file, state dir, node version, orca reachability. A non-zero exit means fix before continuing.
  5. Generates and starts the systemd user unit orchestrator.service.
  6. One-time, and the only step needing sudo: without linger, systemd stops your user services at logout and does not start them at boot — required for reboot survival.

CLI

| Command | What it does | |---|---| | orc | Run the daemon in the foreground (reads config from the environment) | | orc dashboard | Run the dashboard sidecar in the foreground — the read-only web view of live state | | orc --version | Print the version and exit | | orc init | Scaffold ~/.config/orchestrator/{env,routing-hints.json} | | orc doctor | Read-only diagnosis of the whole setup; non-zero exit on any failure | | orc update | Update to the latest release — install, unit regeneration and restart, as one step | | orc service install | Generate, enable and start both systemd user units (re-run after node upgrades) | | orc service uninstall | Stop, disable and remove both systemd user units |

Updating

orc update

One command runs the whole ritual: check the registry, install the new version, regenerate the systemd unit, restart the service. The restart is the step that actually swaps the running code — which is why it is one indivisible command and not three you might truncate. Already at the latest version is a no-op; without a systemd unit only the package is updated and it tells you to restart your daemon yourself.

A breaking release (major version jump — pre-1.0, the first one graduates to 1.0.0) is refused with a pointer to the release notes; re-run as orc update --yes once you have read them.

Changelog = GitHub Releases only. To get notified: Watch → Custom → Releases on the repo.

Operating

systemctl --user status orchestrator     # running?
journalctl --user -u orchestrator -f     # follow the logs

The Dashboard — a read-only web page answering "what is the orchestrator doing right now?" (open sessions, in-flight delegations, pending gates, stall alerts) — is served by a sidecar unit on 127.0.0.1:8787. It installs with orc service install and exposes nothing beyond the machine; reach it over Tailscale or an SSH tunnel your own way.

Runbook — service management, the dashboard, orc doctor triage, non-systemd operation, config/state reference, uninstall: docs/operations.md.

Development

git clone https://github.com/nvergez/orchestrator && cd orchestrator
npm ci
npm test && npm run typecheck && npm run lint

Dev loops

Three composite commands, named by the world they put you in (each is a concurrently composition — when one process dies, the whole loop dies loud):

| Command | Runs | Database | | --- | --- | --- | | npm run dev:all | daemon + sidecar + Vite | .dev/orchestrator.db | | npm run dev:dashboard | sidecar + Vite | the real one (XDG, or ORCHESTRATOR_DB_PATH) | | npm run dev:dashboard:demo | seed, then sidecar + Vite | .dev/demo.db, reseeded fresh every run |

npm run dev:all boots the daemon from .env and fails immediately with the missing-variable list without one. A dev instance coexists with an installed service by isolation (ADR 0003): its own Slack app, its own database, its own port. Create a second Slack app for dev (same manifest as docs/setup-slack.md, Socket Mode, its own channel) and put its tokens in .env — the daemon refuses to boot while the service is active on this machine and .env holds the service's SLACK_APP_TOKEN or points at its database. The dev defaults isolate the rest: the sidecar listens on 8788 (the service's on 8787; DASHBOARD_PORT overrides — set it in the shell, not .env: the loop exports one value to both the sidecar and the Vite proxy, and a .env entry could only reach the sidecar), and the dev databases live under the git-ignored .dev/.

npm run dev:dashboard:demo needs no daemon, no Slack app, no Orca: it writes demo state through the real stores — a live session, in-flight and failed delegations, a decision gate, an escalation, a stall — so every dashboard section renders from a bare checkout. Timestamps sit relative to now; reseed any time with npm run seed:demo. The demo database path is fixed (the seed ignores ORCHESTRATOR_DB_PATH, so ambient daemon env can never aim the reseed at a real database), and it is a different file from dev:all's — a demo run never clobbers dev-daemon state.

Dev over a tailnet: WEB_DEV_HOST="$(tailscale ip -4)" npm run dev:all binds Vite past loopback (*.ts.net Host headers are pre-allowed — bind the tailnet IP, never 0.0.0.0, on a box with a public interface). By default nothing binds beyond loopback, and the sidecar never does: the browser reaches Vite, and Vite proxies /api locally (ADR 0002).

The dashboard frontend lives in the web/ npm workspace (React + Vite), built into dist/web by npm run build:web and shipped pre-built in the npm tarball — the published package carries zero frontend dependencies.

PRs are squash-merged and the PR title must follow Conventional Commits — merged titles drive version bumps (fix: → patch, feat: → minor, breaking → major; anything else counts for nothing). Merging alone does not release: a release happens when a merged PR carries the release label (or via a manual workflow dispatch), and it ships everything merged since the last tag.

License

MIT