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

create-agent-rig

v0.4.0

Published

Scaffold a new project with an agent operating system (rules, gates, hooks) and a runnable code skeleton

Readme

create-agent-rig

Scaffold a project that ships with an agent operating system — rules, gates, and hooks that hold the architecture mechanically, not by prose.

npx create-agent-rig my-app                        # choose a target interactively
npx create-agent-rig my-app --target node-service  # or name it up front

Two coherent targets — aws-serverless (the default) and node-service. On a terminal the CLI prompts; in CI it wants --target explicitly. --no-git skips the initial baseline commit; --no-color (and NO_COLOR) plainens the output.

Already have a repo? Install just the process layer into it — no architecture assumptions, no skeleton:

npx create-agent-rig init            # rules, gates, stop rules into the current repo
npx create-agent-rig init --dry-run  # print the plan, write nothing

init drops in the autonomy tiers, stop rules, workflow, and the enforcement hooks — wired, in a .claude/settings.json that names exactly the hooks it installed — plus a CLAUDE.md that describes that rig rather than the generated monorepo. It refuses to clobber an existing CLAUDE.md; if the repo already has a .claude/settings.json, it keeps it and prints the entries to merge, because a hook nothing calls is not enforcement.

Two things it deliberately leaves to you, and says so in the installed CLAUDE.md: the Definition-of-Done gate has no dod-checks.json (it cannot know your commands), and the elevated-path list names only what every repo has.

Upgrading a rig you already have

A release changes files, and init only ever adds — so bringing an existing rig forward is its own command:

npx create-agent-rig@latest upgrade --dry-run  # print the plan, write nothing
npx create-agent-rig@latest upgrade            # print the plan, then ask before writing
npx create-agent-rig@latest upgrade --yes      # the answer up front (required off a terminal)

It replaces the files the rig installed and you have not touched, installs what the release added, and reports everything else — no three-way merge, no patching. Silently merging your edits into the documents an agent loop obeys is how a rig quietly stops meaning what you think it means; a conflict report is how it does not. Each conflict names the file, why it was kept, and the path to the new version so you can diff it yourself.

How it knows: create and init write .claude/.rig-manifest.json — the rig version plus a hash per installed file. Commit it; without it in the repository the command is blind on CI and on a colleague's machine. Rigs installed before 0.4.0 have no manifest, so the package also carries the hashes of every tagged release (0.3.0 onward — 0.1.0 and 0.2.0 shipped untagged, and a rig from those reports every file as yours) and recognises a file matching one of them.

.claude/settings.json is never replaced — it is where your own hooks live, so the new wiring is printed for you to merge.

A file you deleted stays deleted. The rules invite you to delete the ones whose invariant your project does not have, so an upgrade that quietly restored them would be undoing your work. With a manifest that is direct — it names the file, the disk does not have it, and the manifest is evidence, not a command. Without one, the shipped table answers instead: a file that was in every release it covers was there to be removed. The single case nothing can tell apart is a file a later release added, which your rig never had — that one is installed, and --dry-run lists it before anything is written.

What you get

A system of boundaries, each held by tooling. An agent (or a human using one) cannot talk its way past them — each guard is a pre-write scan that stops the normal path cold (review and tests back it; the claim is stated exactly, never inflated). The hooks live in .claude/hooks/ and are wired in .claude/settings.json:

  • guard-core-purity — refuses any edit that puts I/O, clock, randomness, environment access, or a non-allowlisted import into the pure domain core;
  • guard-web-boundary — refuses db/service imports from the frontend; the web talks to the backend over HTTP only;
  • block-no-verify — refuses bypassing pre-commit checks (and knows the difference between using the --no-verify/-n flag and merely mentioning it in a message);
  • guard-bash — refuses the part of the "Never" tier a text scan can decide: a force-push or --delete naming a shared branch, a push that names the default branch, gh workflow run/gh api …/dispatches against a production workflow, and rm on a catastrophic target. It parses the command rather than pattern-matching it, so a commit message mentioning a forbidden flag is prose, not a bypass — and the file states exactly what it does not inspect (cdk deploy, find -delete, a bare git push, and more);
  • gate-stop-dod — refuses to end the session while a Definition-of-Done check is red; it fails open (a missing or corrupt config never makes the session unquittable) and never blocks twice in a row;
  • inject-rules — re-injects the autonomy rules at session start, so they survive compaction and resumes.

A brake that is a real file. touch ~/.claude/<project>-loop-STOP and no merge lands until it is removed — enforced at the tool layer, so it holds even if nothing reads the rule. Everything short of the merge stays allowed on purpose: finish the task, push the branch, open the PR, write the journal. Stopping cleanly must not mean losing work.

Two sweeps meant to run outside any session — nothing schedules them for you; that is deliberate, because a check a run performs on itself is one a hurried run skips. detect-missed-gate finds merges that crossed an elevated path with no recorded reviewer verdict; reconcile-external-prs accounts for work that reached the default branch outside the queue. They exist because the one failure a run cannot report is its own missed gate — the run that skipped it is exactly the run that will not mention it.

A queue behind an adapter. The loop driver selects through .claude/scripts/queue/: a pure core (filters in order, blocker resolution, the elevated-tier ration, stop conditions) with adapters for PLAN.md (the default, working before a project has a remote), GitHub Issues, and Jira. Two rules are load-bearing and tested from both directions — blockers resolve from links, never labels, and the agent never files its own work items.

Around all of it: autonomy tiers (what an agent does alone / after review / never), stop rules (three strikes, flaky ≠ retry, session staleness), subagent gates (test-writer, code-reviewer, security-scanner, prose-reviewer, and cdk-diff-reviewer on the AWS target), skills (pr-ship pre-merge gate; loop queue driver; worktree-task for concurrent sessions; new-invariant, a generator for the invariant→hook→test pattern; post-deploy-verify and ro-debug on the AWS target), and a one-page CLAUDE.md map a fresh session orients by.

The hooks are examples, not laws. .claude/rules/invariants.md states the pattern behind each one — a stated invariant, a mechanical check, a test for the check — so you can delete the ones whose invariant your project does not have and spend the slot on one it does. An inherited rule nobody chose is worse than an empty rule file: the empty one is visibly incomplete, the inherited one is invisibly wrong.

The skeleton around it is real and runnable — pure core shared by server and browser (one schema validates on both sides of the wire), a mandatory usecase layer (payload → handler → usecase → model), a queue with DLQ discipline, tests at every layer.

Targets

| Target | One line | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | aws-serverless | DynamoDB single-table, SQS + DLQ + CloudWatch alarm, three Lambdas (POST/GET /notes behind an HTTP API, plus an SQS worker), static web on S3 + CloudFront, CDK with least-privilege IAM grants | | node-service | node:http server that also serves the built web bundle, atomic JSON-file store behind the same model boundary, spool-directory queue + DLQ, worker process |

Coherent alternatives, not a parameterized abstraction. Flexibility is subtraction: the generated project is yours — delete what you don't need.

What it deliberately does not do

No authentication. No design system or UI kit. No state manager. No i18n, analytics, or error tracking. No third cloud. No component-testing apparatus.

Each of these is application surface, not an architecture proof — and every addition is permanent maintenance in every target. The frontend is plain on purpose: scaffolding gets replaced without friction; a finished-looking UI gets fought. If you need one of these, add it — the project is yours.

The 2-minute demo

./demo.sh   # from a clone of this repo

generates the node-service target → the generated project's own gates pass → an attempted core-purity violation is refused live by the hook → the service runs, a smoke request travels every layer, the worker drains the queue, the DLQ stays empty:

== 3/4 an agent tries to put I/O and clock access into the pure core… ==
BLOCKED — packages/core is a pure module and this change breaks its purity:
  - imports "node:fs/promises" — the core may import only its own modules and: zod
  - reads the clock — take a timestamp as an argument
Move the impure part behind the usecase layer or into an adapter.
…and the guard-core-purity hook REFUSED the edit at the tool layer (exit 2). ✔

Requirements

  • Node ≥ 20 (pnpm recommended for the generated workspace). The CLI itself carries zero runtime dependencies — the npx github:…, tarball, and published-package paths all work.

How it stays honest

Every template is a real project, installed with a frozen lockfile and run in place on every push. Every e2e run generates a project cold and runs the generated project's own checks (install → lint → typecheck → test, plus cdk synth on the AWS target); the pack-path and git-path installs are both under test, because that is exactly where scaffolders break. A grep-test keeps the universal rules free of any provider mention; the hook-blocking behavior itself is under test; and a weekly lockfile-free run resolves each template's dependencies fresh to catch upstream breakage early. This repo dogfoods its own rulebook — CLAUDE.md and .claude/ are composed from the templates, and drift fails the suite.

And the enforcement layer is adversarially reviewed, not just tested. The Bash guard went through four review rounds with ten reviewers, who executed it rather than read it. They found a PR body that could forge its own reviewer verdict, a queue write that deleted the wrong line, and three ways to make the guard crash into permitting everything. Each round's findings — including the ones introduced by the previous round's fix — are in the git history and in CHANGELOG.md. The rule that came out of it is now part of what ships: a guard that fails open must do provably bounded work, because fail-open turns every line of its own work into a potential bypass.

Development (from a clone — PLAN.md and demo.sh live in the repository, not in the published tarball): pnpm test (full), pnpm test:unit (fast loop), pnpm template:check (templates in place). The plan of record is PLAN.md; release notes and the release checklist ship in CHANGELOG.md.