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

whippletree

v0.2.0

Published

A control plane for multiple coding agents

Readme

Whippletree

One load, many pullers, evenly hitched.

A control plane for multiple coding agents. It never reimplements agent logic — it spawns the real CLIs, streams their output into one normalized event schema, records it, and reports.

0.2.0 — early. You can type a prompt in a browser, watch an agent work, and get a result. Stuck detection, timeouts, retries and budgets land in 0.3.0 — until then, do not leave a run unattended. Pre-1.0 versions may break at any minor bump.

Install

npm i -g whippletree

What works today

wtree start

The whole system in one local process: a supervisor, a SQLite database, and a web UI on 127.0.0.1. Nothing leaves the machine except the agent CLIs' own calls to their model APIs.

$ wtree start
Created ~/.whippletree
  whippletree.db       (schema v1)
  config.json          (port 4900, no auth)
  agents/general.yaml  (one read-only claude agent, bed = /Users/you/repo)
  mind/core.md         (your standing context goes here)

Whippletree 0.2.0 — listening on http://127.0.0.1:4900
Opening browser…
[preflight] checking adapters…
[preflight] 2 adapters usable, 1 agent ready

Type a prompt, pick an agent, and watch the run. The event log streams live, the tool timeline shows where the time actually went, and the result card is the agent's final message. Close the tab mid-run and nothing breaks — the page replays from the database when you come back.

| Command | | |---|---| | wtree start | Supervisor and UI, in the foreground. Runs init first if it has to | | wtree start --daemon | The same thing, detached, logging to ~/.whippletree/logs | | wtree stop / status / open | What you would expect | | wtree init | Create ~/.whippletree. Idempotent, and never touches an existing database |

--port <n> overrides the configured port. A port already in use is not an error if a Whippletree is answering on it — that is the thing you wanted, so it opens the browser and exits 0.

Mode is decided from what you asked

You describe the task; Whippletree works out whether it needs to write.

Fix the null check in server.ts     → write       "fix" asks for something on disk to change
What does the config file set?      → read-only   this is phrased as a question
Explain how to fix the parser       → read-only   "fix" appears, but this is phrased as a question
Plan the migration to Yii2          → read-only   "plan" asks for a plan, not a change

The resolved mode and its reason appear in the composer before you dispatch, and the picker is still there when you want to overrule it.

None of this is a security boundary. The agent's permissions, set in its YAML, is the only gate. An inferred write is clamped down to what the agent allows — nobody asked for write, so failing the task on a guess would be the wrong way round. An explicit write on a read-only agent is refused outright, because overriding a permission you wrote down would make the file pointless.

The bed is picked, not typed

The working directory comes from a folder picker that walks the real filesystem. A browser cannot supply an absolute path on its own — a folder input yields a relative name and the File System Access API yields an opaque handle — so the picker asks the local server, which can actually see the disk. Git repos are marked, and the beds your agents already use are one click away.

Agents are files

# ~/.whippletree/agents/reviewer.yaml — the filename is the id
display_name: Reviewer
adapter: claude
bed: /Users/you/repo
permissions: read-only
system_prompt: |
  Answer the task directly and stop.

Identity, prompt, and permissions live in version control, not in the database, so git log shows exactly when an agent's behaviour changed. The database keeps a copy, refreshed on every start. One malformed file reports itself and the rest of the roster still loads.

enabled and available stay separate: the first is your intent from the YAML, the second is runtime fact from the adapter probe. An agent switched off because Codex was missing switches itself back on the moment you install Codex.

wtree doctor

Answers "is my agent tooling actually set up correctly on this machine" — useful on its own whether or not you ever run the rest of Whippletree.

$ wtree doctor
claude   ✓  2.1.231    /opt/homebrew/bin/claude  authenticated (subscription)
codex    ✗  not found on PATH
         → npm i -g @openai/codex, then: codex login
cursor   –  deferred in this build

1 of 2 adapters usable. Single-adapter mode is fully supported.

It checks three things per adapter, because presence alone is not enough — an outdated binary is worse than a missing one, since it fails at dispatch time with a confusing parse error instead of at startup with a clear message:

  1. Installed — resolved on PATH, including the .cmd shim on Windows.
  2. New enough — both CLIs' JSON event streams are version-gated.
  3. Authenticated — a real one-token round trip, not a config file read.

| Flag | | |---|---| | --refresh | Ignore the cached probe and re-check | | --skip-auth-probe | Skip the auth round trip; reports auth as unknown, never as failure | | --json | Machine-readable report |

Exits non-zero only when nothing is usable. One adapter is enough to run the system; zero is a hard stop.

wtree spike

Run one task and watch it normalize, live. This is the fastest way to check whether an adapter still behaves after either CLI ships an update.

$ wtree spike claude "Read note.txt and reply with its contents"
run.started       thread=9d8d1a5a-1fc4-4253-9059-e39bbbf638d0 model=claude-opus-5
assistant.text    I'll read the file first.
tool.started      Read {"file_path":"/tmp/bed/note.txt"}
tool.completed    Read
assistant.text    hello from the bed
run.ended         done in=4 out=136 $0.1179

--bed <dir> sets the working directory, --write leaves read-only mode, and --raw prints the full normalized event objects instead of one-line summaries.

Design commitments

These hold from 0.1.0 onward, and the ones below are already load-bearing.

Neither CLI is a hard requirement. Whippletree ships with no agent inside it. One usable adapter runs the system; zero is a hard stop with a clear message and the exact install command. Nothing in the core may assume both exist.

Failure is a first-class state. Stuck, timed-out, and silently-exited runs have to be as visible as successful ones. Concretely today: an adapter whose auth check was skipped reports as unknown rather than broken, and a run whose CLI dies without a terminal event still produces run.ended rather than sitting there looking alive.

Spawned runs do not inherit your personal CLI setup. A supervisor that picks up whatever hooks you configured for interactive use is a supervisor whose results you cannot trust. See the spike findings for what that looked like in practice.

Agents are spawned as your user and authenticate exactly as they do interactively. claude login and codex login are the whole setup — no API key required, though one can be set per agent later for burst capacity.

The database is the source of truth, not the process table. Everything the supervisor knows is a row. On boot it reconciles: any run the database still believes is live did not survive, so it is closed out and its task goes back on the queue. A permanently-running row is worse than no status board, because it is the one state you learn to stop trusting.

The UI stays dumb. Its only write is a task row. It never spawns a process, never talks to an adapter, and holds no state the database does not have. Close the browser mid-run and the run continues.

It binds to 127.0.0.1 and nothing else. It can spawn arbitrary processes, so treat it like an open shell. Exposing it beyond the machine is a deliberate opt-in that does not exist yet.

Vocabulary

Fixed before the schema exists, so the database, the API, and the UI agree.

| Term | Meaning | |---|---| | Agent | A long-lived identity — name, adapter, model, bed, system prompt, permissions. Defined in version-controlled YAML, not in the database. | | Adapter | The integration with one agent CLI (claude, codex). Where all CLI-specific knowledge is allowed to live. | | Evener | The supervisor — the central bar that balances the pull. The one component that does no work itself. | | Run | One execution of an agent against one task. | | Task | A unit of work on the board, assigned to an agent. | | Bed | A workspace — a git repo or directory an agent is scoped to. |

One ambiguity to hold the line on: Agent is the configured identity, never the spawned process. The thing Whippletree actually launches is the CLI, reached through its adapter. Keeping those words apart is what makes "agent failed" and "adapter unavailable" mean different things.

The event schema

Every adapter normalizes onto one union, and nothing downstream knows which CLI produced an event:

run.started · run.ended · turn.started · turn.completed · turn.failed · assistant.text · assistant.thinking · tool.started · tool.completed · file.changed · usage · rate_limit · error

The raw adapter event is preserved on every one, so normalization can never lose fidelity. The full verified mapping for both CLIs, and the places where they genuinely differ, is in docs/spike-findings.md.

Development

npm install
npm run build
npm test          # 122 tests
npm start         # build, then wtree start

Normalizer tests assert against real event streams committed under test/fixtures/, captured from live runs rather than hand-written. When a CLI changes its output shape, those tests are what tell you.

The supervisor is tested against a scripted adapter rather than a real CLI, so dispatch, failure, kill, concurrency, and reconcile are deterministic. Set WHIPPLETREE_HOME to run against a throwaway directory.

Four runtime dependencies: better-sqlite3, fastify, yaml, semver, which. The UI has no build step — src/ui is three files the browser runs as-is.

Roadmap

| Version | What you can do with it | |---|---| | 0.1.0 | wtree doctor — check your agent CLIs | | 0.2.0 | Type a prompt in a browser, watch an agent work, get a result ← you are here | | 0.3.0 | Trust it unattended — stuck detection, timeouts, retries, budgets | | 0.4.0 | Two adapters, and propose mode with diff-and-approve | | 0.5.0 | Shared memory with a claims review gate | | 0.6.0 | Delegation, routing, cron and webhook triggers |

License

MIT