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

@popovych.co/witness

v0.14.0

Published

Evidence-gated spec-driven development pipeline for AI coding agents: brainstorm to PR in six stages, where specs are state, plans are motion, and no transition passes without evidence. Drives from Claude Code or Pi.

Readme

witness

npm ci license node

Spec-driven development for AI coding agents, where nothing advances without evidence.

witness takes a change from brainstorm to merged PR through a six-stage pipeline with five evidence-gated transitions, driven from Claude Code or Pi. Specs are state (what must be true), plans are motion (what we're changing); the CLI is the sole writer of both, and every transition leaves evidence in an append-only journal.

The name is the thesis: an agent claiming "done" is not evidence. A red→green test transition the CLI watched happen is. witness is the thing that watched.

Why

Agents are confident narrators of work they did not do. witness removes the narration from the critical path:

  • Evidence, then human. No stage advances on an agent's say-so. Deterministic checks run first; reviewer verdicts are spawned and captured by the CLI, never relayed through the agent's own transcript.
  • Specs are state, plans are motion. Specs describe what must be true and outlive the change; plans describe one change and die with it. Never mixed, never reversed.
  • The CLI is the sole writer. Agents propose through a validating write path; a guard hook blocks direct edits to canon. Malformed state is unrepresentable, not merely discouraged.
  • Red→green is witnessed, not claimed. Every added test must be observed failing, then passing, with both shas journaled. A test that never failed is refused as vacuous.
  • Append-only journal. Every check, verdict and human decision lands in .witness/journal/*.jsonl — git-diffable, resumable, never compacted.
  • Resumable by construction. Kill any stage mid-run and re-run it; position is derived from frontmatter plus world state, never from session memory.

Status: all four slices landed — state core, deterministic evidence, gates & motion, plugin + calibration. Reviewer calibration is the remaining pre-1.0 work (docs/graduation.md).

Prerequisite

witness gate spawns the Claude Code CLI headlessly for every reviewer, on every harness (DESIGN.md row 87, decision 12). Install and authenticate claude on any machine that runs gates, whatever drives the pipeline. witness check probes for it.

Quickstart

npx @popovych.co/witness init --agent claude-code   # scaffold + install the engine, guard and dashboard
npx @popovych.co/witness recap --file recap.json    # birth an effort from a confirmed scope recap
npx @popovych.co/witness write auth-refresh --effort auth-hardening --meta m.json --body b.md
npx @popovych.co/witness                            # dashboard: where you are, the one next action

Installed globally (npm i -g @popovych.co/witness) the binary is witness.

Install per harness

witness is two halves: six skills, distributed through the skills ecosystem installer, and the engine + guard + dashboard, which no skills installer can place — witness init --agent <name> writes those and commits them.

Claude Code — one step, the native path:

/plugin marketplace add popovych-co/witness    # skills, engine, guard and dashboard together

Pi (and any other agent the installer supports):

npx skills@latest add https://registry.npmjs.org/@popovych.co/witness/-/witness-<version>.tgz
#   choose your agent, then choose GLOBAL scope — see below
npx @popovych.co/witness init --agent pi

Install skills at global scope, not project scope. Pi resolves project skills at <cwd>/.pi/skills with no upward walk, and the implement stage runs with its cwd inside .witness/worktrees/<plan-id> — a directory the installer never touched. A project-scope install therefore loses every skill in the stage that does the most work. Global (~/.pi/agent/skills) is cwd-independent. witness check warns when six skills are installed where a worktree cannot see them, and states which harnesses have none.

A tarball URL is version-pinned, so skills update cannot resolve forward: re-run add with the new version URL to upgrade.

Upgrading: skills first, then init --agent

Every surface that invokes witness pins the CLI — the engine prompt and all six skills carry npx -y @popovych.co/witness@<version> — so a repo installed at an older release only ever runs that release, which compares its payload against itself and reports clean. The freeze is self-concealing, and a repo frozen at 0.6.0 or earlier cannot detect it, because the detection ships in a CLI that repo never invokes. Unstick it from outside, in this order:

npx skills@latest add https://registry.npmjs.org/@popovych.co/witness/-/witness-<new-version>.tgz
npx -y @popovych.co/witness@latest init --agent <name>   # restamps the engine, guard and dashboard

Skills first: their fresh pins are what invoke a CLI new enough to see the outdated payload. Claude Code users on the marketplace plugin get both halves from /plugin marketplace add and need no second step.

From 0.7.0 onward the order stops mattering: witness check asks the registry what the published latest is and reports both halves of the skew — a CLI behind latest (cli-behind) and any visible skill pinning something older (skills-behind). The query is best-effort and silent on failure, so an offline machine reports nothing rather than a complaint about the network.

witness init --agent <name> overwrites payload files it did not write and names what it replaced (payload-overwritten); the previous content is one git revert away, because witness commits the payload. It refuses the whole run if a payload path carries an uncommitted change (payload-dirty) or if the CLI you are running is older than the payload already installed (cli-behind-payload).

From 0.10.0 onward init installs into every home of the repository — the primary root and each live .witness/worktrees/<plan-id> — because a worktree is a branch checkout, so its payload is a different file on a different timeline. A worktree cut before an upgrade used to keep the old pin forever, and the old pin is what selects the CLI that runs there. Every home is preflighted before any is written, so a dirty payload in one refuses the whole run rather than leaving the set half-upgraded, and witness check now reports payload-stale per home and names the stale one.

The same release makes the bound structural: every journal entry records the CLI that wrote it, and a CLI older than anything the repository's state has seen refuses every verb with cli-behind-state rather than answering from rules the repository has moved past. witness floor --show reports the bound. If you are deliberately rolling back — a bad release, say — lower it first with witness floor --set <version> --note <why>; the decision is journaled, and floor is the one verb that still runs under a bound it fails.

Support tiers

| Tier | Agents | What they get | | --- | --- | --- | | Supported | Claude Code, Pi | skills, /witness engine, canon guard, session dashboard | | Skills only | the other agents the installer supports | the six skills; no engine, no guard, no dashboard — the Witness-State trailer audit remains the guarantee (DESIGN.md row 31) |

Verified against pi 0.83.0 and skills 1.5.21. Re-verify on any major bump of either.

Configuration keys

| Key | Meaning | |---|---| | harness: claude-code \| pi | the judge — which harness runs this repo's gate reviewers, is measured by calibrate, and is probed by check. Judgment resolves harness:PI_CODING_AGENTCLAUDECODEclaude-code; session lines (next's handoff, dispatch's relay, init --agent auto) resolve detection first, because those name the CLI you are about to type at. Committed, so it binds every teammate's gates; witness init --agent writes it once and never re-points it. Undeclared repos are judged by whichever agent's session is open — witness check and witness status say so | | gates.reviewerTimeoutMs | milliseconds per reviewer invocation (default 600000) | | drive.sessionTimeoutMs | milliseconds a drive-spawned session may run before SIGTERM (default 3600000) |

There is no provider: key. witness gate spawns the DECLARED harness's headless mode for every reviewer (Decisions 88, 105): claude-code renders bare Anthropic ids, pi renders provider/model[:thinking] with the provider witness knows it needs. The pi reviewer runs hermetic (--no-extensions --no-skills --no-context-files); machine extensions it must keep — e.g. an OAuth adapter that supplies your Anthropic auth — are declared in machine config, not env:

# .witness/config.local.yaml — machine facts, gitignored, never committed
reviewerExtensions:
  - /Users/you/.pi/agent/npm/node_modules/pi-claude-oauth-adapter
opener: xdg-open   # optional; nonstandard desktops only

Repo facts live in witness.config.yaml (committed); machine facts live in .witness/config.local.yaml (gitignored). Every key has exactly one home — a key in the wrong file refuses. There are no WITNESS_* env vars for configuration.

Verbs

| verb | does | | --- | --- | | init [--agent claude-code\|pi\|auto] | scaffold config, principles, journal — one trailer commit; --agent also installs that harness's engine, guard and dashboard (idempotent) | | recap [--amend] --file <json> | validate + persist a scope recap; births the effort journal | | write <id> --effort <e> --meta <json> --body <md> | validated manifest → spec/plan on disk + journal entry | | diff <spec-id> | delta since the last realized state (plan pin → empty) | | read <id> [--design] [--outline] [--lines <a>-<b>] | print a spec/plan/design from the primary root — the read route, since a worktree carries no canon copy; --outline names each anchor's line range for fat artifacts | | check | schema, graph, invariants, needs, trailer audit, probes | | index | id · summary · status · depends across the canon, then each spec's plans | | satisfy <id> --need <text\|n> | flip a manual need via the write path | | log <id> | render a journal stream | | gate <decompose\|plan\|implement\|ship\|design> <id> | run the reviewer gate; journals the round, stamps on pass | | decide <gate> <id> --approve\|--revise [--pin <policy>] | record the human decision on a stopped gate; --pin adds a standing content policy | | design <spec-id> --file <html>\|--open\|--reconfirm | register/show a ui spec's approved look | | start <plan-id> | create/re-attach the plan's worktree (.witness/worktrees/<id>) — code only: the canon dirs are excluded from it, so a plan cannot go stale in there | | next | the one next action across every effort | | drive [--flow <plan-id>] [--max-spawns <n>] | schedule green-path work through headless sessions; you appear only at judgment stops. TTY-only — agents are what drive spawns, never what spawns drive | | ship <plan-id> | lanes → ship gate → PR → CI watch | | test-evidence / verify-red | journal red/green criteria evidence from a worktree | | adopt <path> | absolve a finished hand-edit into the journal | | abandon <plan-id \| effort-slug> | wind a plan/effort down; reverts only specs that effort itself wrote | | dispatch-report <plan-id> --steps-assigned <n> --steps-completed <n> | journal a session slice's telemetry | | rename <old> <new> | id rename across canon, refs, journal | | clean | reap stale worktrees | | sync | pull --rebase + push state commits | | calibrate <model> | run the reviewer calibration battery | | recover [--complete\|--rollback] | resolve a crashed write transaction | | status | orientation: flows, blocked docs, reconcile rows, pending gates, calibration state | | (no verb) | the same screen as status |

Exit codes

0 ok · 1 findings · 2 refused (structured {field, rule, got, want} rows) · 3 blocked (lock/txn/untrusted cmd in non-TTY) · 9 test-only injected crash

State model

  • Frontmatter is position — the CLI derives "where are we" by scanning it; nothing else stores pipeline state.
  • The journal is history.witness/journal/<id>.jsonl, append-only, committed, never compacted.
  • Every state commit carries Witness-State: 1witness check audits that spec/plan diffs appear only in trailer-bearing commits.
  • Canon roots are configurablepaths: { specs: docs/specs, plans: docs/plans } in witness.config.yaml (defaults: specs/, plans/); scan, commit scoping, the guard hook, and criteria excludes all follow it. git mv existing docs when changing it.
  • Local, never committed: .witness/{lock,txn.json,allow.json,calibration.local.yaml}.

Development

pnpm install
pnpm test           # vitest, in-process CLI against throwaway git repos
pnpm run typecheck
pnpm run build
pnpm run release patch   # bump + stamp pins + commit + tag, in one act — see docs/RELEASING.md

Releasing is node scripts/release.mjs <major|minor|patch|x.y.z> followed by two pushes; the tag push is what publishes. The order is fixed because CI checks the tagged tree, not the intent — docs/RELEASING.md explains why and what to do if a tag was pushed early.

Run economics (operator notes)

Non-load-bearing knobs for the machine that hosts long implement runs — the design depends on none of them (DESIGN.md row 79):

  • Keep the host awake. A suspend longer than an hour mid-run expires the prompt cache; on wake the full agent context is re-written at cache-write price. On macOS: caffeinate -dims for the session, or plug in and disable sleep.
  • CLAUDE_CODE_AUTO_COMPACT_WINDOW (set at CLI launch) lowers the harness's auto-compaction threshold as belt-and-suspenders under the dispatch budget. It is documented for main sessions only — whether subagents honor it is unverified.
  • The designed mechanisms are the dispatch budget (implement.stepsPerDispatch), the loop-width protocol, and dispatch-report telemetry — see DESIGN.md rows 79–81.