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

@baldurpan/create-ai-workflow

v0.20.1

Published

Overlay a tiered planning workflow — roadmap, plans, phase ledgers, verification gates — onto an existing repository, for coding agents.

Readme

@baldurpan/create-ai-workflow

Overlays a planning workflow onto an existing repository. It is not a scaffolder — despite the create- name, it expects a repo you already have, and it refuses to run where context/ exists.

npx @baldurpan/create-ai-workflow      # or: npm create @baldurpan/ai-workflow

You get a backlog, plan documents with phase ledgers, two verification gates, and nine commands that move work between them. Your coding agent runs the commands; you read and hand-edit the files.


The three tiers

/roadmap "idea"  ──▶  pending                  Tier 1 — the backlog
                        │                      context/roadmap.md, notes in context/drafts/
                  /feature-plan [--activate]    writes context/plans/<NAME>-PLAN.md, then STOPS
                        ▼
                  a plan exists                Tier 2 — one plan, with a phase status ledger
                        │
                  /feature-implement [--all]   activates, then runs phases: code → verify → review
                        ▼
                  /feature-close               ──▶ context/archive/ + a context/history.md row

Every boundary is crossed by an explicit command, never as a side-effect. Every command finds its own starting point — nothing has to be looked up first.

The commands

| Command | Does | |---|---| | /roadmap | prints the backlog, or appends one pending entry — capturing any material you supply as a draft | | /feature-plan | turns an entry into a plan document and stops. Planning is not activation | | /feature-implement | activates a planned feature and runs one phase through both gates — or phase after phase with --all, which stops at a blocked phase, a capped gate or a ledger that disagrees with the repo, and never at /feature-close | | /feature-status | read-only. Reconciles the ledger against the repo — sweeping every worktree where the project works that way — then names exactly one next action | | /feature-close | retires a feature: a history.md row, a git mv into archive/, a reviewed reference sweep, and the release note where release.md says one is owed | | /orchestrate | one ad-hoc, commit-sized change through the same gates — no entry, no ledger | | /prototype | a throwaway HTML/CSS mockup under prototypes/, to settle a layout question before a plan commits to it — no gates, no application code | | /onboard | fills in your own stubs, adopting what the repo already documented, indexing where it documents itself, running each verification command before writing it down, and asking per path what a change announces | | /tracking-migrate | moves an existing backlog, its drafts and its plans onto the substrate tracking.md names — one feature at a time, resumable, removing a file only once the issue that replaces it exists |

What makes it different

No document states its own status. There is no **Status:** header anywhere. Whether a feature is being worked is a marker in roadmap.md; whether it has a plan is whether its Doc field points into plans/; where a phase stands is the plan's own ledger. Those facts are orthogonal, so none of them can go stale against another.

Nothing is cached, parsed, or generated. An agent reads the hand-written ledger every time, so editing a row by hand changes the answer immediately. There is no build step in the loop and no generated "current state" file to disagree with its source.

One file names a command. context/verify.md holds this project's real lint, typecheck, build and test commands. No skill, agent prompt or role file carries a copy — a hardcoded stack rots the moment the project changes shape, and a second copy rots faster. /onboard runs each candidate and writes only the ones that exit 0.

Nothing commits, branches or pushes unless you said it could. context/git.md holds four independent answers — who commits, where work lands (the main working tree, a branch per feature, or a worktree per feature), whether the agent pushes and opens a pull request, and at what granularity — and every command that lands code reads it before closing out. Each ships as the most conservative option: the user commits, in the main working tree, pushing nothing. A tool installed into a repository it knows nothing about does not get to write that repository's history unasked.

They are four answers rather than three named modes because they are orthogonal — a worktree per feature does not imply a pull request, and a pull request does not imply a worktree — and two facts that cannot disagree is the same reason no document here states its own status. /onboard still asks them as three named shapes, because that is how people think about it.

Under the worktree answer, nothing tracks what is in flight. git worktree list is the answer, and /feature-status sweeps it: "in flight" is not a status, it is the observation that a worktree exists — the same move as "planned" is the observation that a document exists in plans/. A file recording it would be a cache of something git already knows, and it would be wrong in the one case you reach for it. Merging stays outside the workflow entirely: nothing here merges a pull request, deletes a branch, or removes a worktree.

Documentation is part of the change. A plan starts by finding where the project explains itself — context/stack.md holds that index, /onboard fills it by sweeping the tree and asking what is published elsewhere — and every plan carries a §7 naming what the feature makes untrue there. Each row is assigned to a phase, and its path goes on that phase's Files: line, so the README lands with the rename rather than after it. Docs are the one output with no gate behind them: nothing fails when a page keeps describing a flag that no longer exists.

What a change announces is a written answer, not an inference. context/release.md holds it, and it ships saying nothing here announces a change — true of every repository, so an existing install behaves exactly as it did. /onboard asks it per path, because a repository can publish one artifact, deploy another and say nothing about a third: each path gets who it announces to, when a change to it deserves a note, and what a bump of it means. The deserves a note when column is where "an internal refactor to the app gets no note" is written down once instead of being re-argued on every pull request.

It is the one answer that cannot be false. verify.md can say no lint step and be accurate — a project with no linter chose that. "A change is announced by writing a note" is a lie in a repository where nothing records one, which is the same defect as a done row whose files do not exist. So /onboard writes the true answer or the true answer plus a named gap, never a mechanism that is not on disk — and it refuses to generate a release job, because accumulating notes is uniform right up to the step that needs credentials and branch protections. Nothing in this workflow bumps a version, tags, publishes, releases or deploys, and the stub has a section that says so rather than leaving it implied.

And the last answer in that file is the event, which is one event and not one per artifact kind. Notes accumulate on feature merges; the merge of the pull request that consumed them — versions moved, changelogs written — is what publishes a package and deploys an app, per path, on the condition that that path's own version moved in it. A feature's merge lands a note and ships nothing, so no command reports work as released, deployed or live because it landed. Two failures the file makes someone write down rather than discover: a deployed app that is never versioned has nothing for a deploy to key on, and a deploy wired to every merge of the base branch is not gated at all — it ships whatever notes happen to be pending, other people's unreleased work included. And what that merge leaves behind is the same for every path it ships: a tag and a release. The record belongs to the event rather than to the kind of artifact — a deployed app earns both exactly as a published package does, which is the half a repository that only deploys will otherwise never get, since the command that publishes is also the one that tags. /onboard reports that second one as the defect it is and rewires nothing.

No skill names a release tool either. A repository with no package.json answers with a hand-maintained ## Unreleased section, or a fragment directory, or nothing — and not one line of the commands changes. They ask record a note per release.md; that file says what records one here.

A defect the gate found has one home, and it is the ledger. Every item a review returns is blocking or it is not — there is no severity scale. A blocking one is fixed by the loopback, or the phase closes blocked with the reason in its Note, or it is an issue, because it turned out to be work that outlives the phase. A non-blocking one goes in the run's report and dies with the session, unless it needs code changes — in which case it is work, and work already has a home.

Nothing accumulates, so nothing has to be swept. Earlier versions kept a context/findings.md, which was a second status vocabulary (P0P3) laid across the one the ledger already had, kept in sync by discipline. One repository reached 1097 lines of defects nothing could close — their gates belonged to phases that no longer existed — and the file grew past what a tool reads in one go, so the gate that asks is anything blocking this phase was answering from a file that came back truncated. A phase has four states and they are the four in the Status column. An update tells an install carrying the old file that nothing reads it any more, and leaves it alone: it is yours.

Where the backlog and the ledgers live is an answer too. context/tracking.md holds it, and it ships saying in the working treeroadmap.md for the backlog, a document under plans/ per feature, a history.md row when one retires. The second answer puts the same three tiers in GitHub issues: a feature is an issue, its plan is that issue's body with the phase ledger as a table inside it, and a closed issue is the archive, with its plan, its whole discussion and its pull request at an id nothing had to rewrite.

That answer exists for one reason — several agents working several features at once. A worktree carries only what its ref holds, so a plan on one branch is invisible to every other tree, and there is no shared place to claim a feature. A tracker sits outside every tree. Under it roadmap.md, history.md, archive/, drafts/ and plans/ stop existing, and so does the merge=union workaround they needed.

No skill names GitHub. The commands ask for the fact they need — is this feature being worked, where does this phase stand — and tracking.md alone says how this project answers it. That is what keeps a different tracker a rewrite of one file rather than of every command.

Changing where tracking lives is two commands, not one. /onboard sets the answer; /tracking-migrate carries what already exists onto it. A repository whose answer says tracker while its entries are still in roadmap.md reads as an empty backlog to every command — so /onboard refuses to write that state, and names the migration instead. The migration finishes one feature before starting the next and removes a file only after the issue replacing it exists, which makes a run that fails partway a resumable state rather than a repository in neither substrate. history.md and archive/ are never converted in either direction: fabricated closed issues for work shipped months ago are an audit trail that looks real and is not.

What gets installed

context/
  README.md  workflow.md  plan-template.md  plan-template.notes.md  roles/  standards/     tool-owned
  stack.md  verify.md  executors.md  git.md  tracking.md  release.md                       yours
  roadmap.md  history.md                                                                   yours
  drafts/  plans/  archive/                                                                yours
  .state/manifest.json
.claude/skills/<nine>/SKILL.md    .claude/agents/*.agent.md                                tool-owned
.agents/skills/<nine>/SKILL.md    the same nine bodies, for hosts that read that tree       tool-owned
AGENTS.md   a delimited block, merged into whatever is already there
CLAUDE.md   a single @AGENTS.md line, and only when the file does not exist

Nothing is committed. Review the diff yourself.

Onto a repository that already documents itself, the installer only appends — your existing AGENTS.md prose is left exactly where it is. /onboard reconciles the two afterwards: it classifies each existing claim into stack.md, verify.md, git.md, tracking.md, release.md or executors.md, asks wherever a destination is unclear or the old text contradicts the installed workflow, and prunes the source only once the replacement is written and shown.

The ownership boundary is a data structure, not a rule

context/.state/manifest.json lists every tool-owned file with its hash. update walks that manifest — and a project-owned file is not in it, so no code path reaches it. Anything else you add under context/ (decisions.md, glossary.md, ops-notes.md) survives by the same property, with no feature required to protect it.

npx @baldurpan/create-ai-workflow update --dry-run   # print the plan, change nothing
npx @baldurpan/create-ai-workflow update             # conflicts stop it; nothing is written
npx @baldurpan/create-ai-workflow update --force     # back up edited files (.bak) and take ours

| On disk | update does | |---|---| | matches the manifest | replaces silently | | differs | reports a conflict; --force backs up and replaces | | missing | restores | | not in the manifest | nothing — it cannot reach it |

Run /onboard after an update. That last row is the whole reason: a new version's tool-owned files can expect something of a project-owned one — a section of context/stack.md that every plan now reads, a context/git.md older than the file itself — and the updater is forbidden to write either. So it ends by naming each gap and stops:

Next
  ! context/stack.md has no "Documentation" section — this version's stub has one
  ! context/git.md is missing — a stub is project-owned, so update cannot write one
  Run /onboard in your agent. It is re-runnable, and it is the only thing that
  reaches these files — the commands above now read them.

It is a note, not a failure — the exit code is the conflict count's to set. A tool that failed an update over the shape of a file it may not touch would be calling someone else's business its own breakage.

Standards

context/standards/ ships a vendored default, and context/standards/README.md holds a conditional-loading table that agents actually traverse — the skills say "consult the conditional loading table", and that is how standards get loaded per task.

A wrong set is not inert, because it is loaded unprompted on every task. Swap it:

npx @baldurpan/create-ai-workflow standards add <git-url>

That command refuses to install a tree the skills cannot navigate: the source's README must carry a usable conditional-loading table, or you are offered a generated one (--generate-index). Whatever lands is project-owned from that point — it drops out of the manifest, so update never clobbers it. Editing the bundled tree in place has the same effect.

release-init

context/release.md is the one stub whose answer can be false: a change is announced by writing a note is a lie in a repository where nothing records one, so /onboard Step 9 refuses to write it and names the gap instead. This is the command that closes the gap.

npx @baldurpan/create-ai-workflow release-init [--private-packages version|ignore] [--dry-run]

It sets up a note-per-change mechanism — .changeset/, the devDependency, and three scripts named changeset:add, changeset:prepare-release and changeset:status — then tells you to run /onboard, which records what it found. prepare-release prepares one; nothing here publishes one. It does not write context/release.md. One writer per file: the installer installs, /onboard answers, the same way standards add does not write stack.md.

What it sets up is a gate, and the gate is not only for publishing. The event it makes available is the merge of the pull request where changeset:prepare-release ran, and that one merge is what ships a published package and a deployed app alike — each on the condition that its own version moved in it. That is why the question below is the one thing this command will not guess, and why .changeset/README.md says a feature's merge ships nothing.

The same answer decides what that merge leaves behind. Versioning a deployed app and tagging it are one decision: the tag is the record of which commit went live, and a release page is built from it. Answer version and both are on. A repository that only deploys still runs the publish command to get them — it publishes nothing where every package is private and cuts tags only, which is the one thing about this mechanism that nobody deduces, so the command says it on its way out.

It is the only command here that names a vendor, and the only one that touches package.json. That is deliberate and it is a boundary, not an exception. The rule that no template may name a release tool is a rule about templates/ — that prose is inherited by every install, including the Go and Python ones, so a skill named after a JavaScript tool would be nonsense in half of them. A subcommand is a program you choose to run, and it refuses where it does not apply. Two tests hold the line from both sides.

The answer it will not guess is whether a private package here is deployed. The tool's default is not to version private packages, so a deployable app recorded as private accumulates notes, never bumps, and anything that deploys on a version change silently does nothing forever — or gets wired to every merge instead, which is worse. It asks on a terminal and refuses without one, naming the flag — the one number in the setup that is expensive to get wrong.

It writes files and runs nothing: no npm install, no git anything, no CI workflow — neither the publish nor the deploy, which are one gap rather than two. Accumulating notes and versioning them is uniform; the last step plus its credentials depends on branch protections, registry auth and who is allowed to press the button, and a generated workflow there does damage. The scripts are what yours would call, and the event either job keys on is the merge described above.

check

npx @baldurpan/create-ai-workflow check

Reports structural breakage: an illegal status word, a Depends on naming a phase that does not exist or a cycle, two entries marked active, a second phase table, a **Status:** header, a plan no entry points at, a dead Doc or history link, and a backlog left in roadmap.md after tracking.md was switched to the tracker — entries that are still well-formed and no longer read by anything.

It never writes — there is no --fix, because the moment it can repair a ledger, a program's edit competes with a hand edit. Nothing depends on it: no skill calls it and no git hook installs it. Delete it and every workflow answer is unchanged. It reads roadmap.md, plans/ and history.md — never archive/, because validating retired records against current rules is how validators earn a reputation for crying wolf. Every message quotes the rule it enforces, so a false positive points at the document that is out of step.

Scope

Both skill trees ship. Claude Code reads .claude/skills/; Codex reads .agents/skills/ and never looks at the other one. They get the same nine bodies — the only difference is one frontmatter line, disable-model-invocation: true, which is Claude Code's key and means nothing elsewhere. The bodies are written runtime-neutral, with no runtime primitive named in any of them, and a test enforces it.

Duplication is the cost, and it is contained by construction rather than by discipline: one canonical source lives in the package, both trees are written at install, both are hashed in the manifest, and neither is ever hand-edited. Editing one is a conflict, not a divergence.

AGENTS.md is the content home, so Cursor, Copilot and Gemini CLI get the command block for free without a tree of their own. An install made before the second tree existed gains it on the next update, listed as add in the plan.

No host's review command is named anywhere in the package. Which coder or reviewer serves Gate 2 is a per-machine fact that hosts change underneath you, so /onboard asks and writes the chosen invocation into context/executors.md. What ships is the contract — a review happens, every item in it is blocking or it is not, and a FAIL is looped back on — not the command.

Each executor has three answers: in-host, in-host but isolated in a subagent, or offloaded to an external CLI. The middle one is written as "a subagent if your runtime provides one" — described by what it does, never by naming a runtime primitive — so a host without the mechanism reads it and falls back to the first. For the coder it buys a caller that keeps the ledger and the gates while the implementation's file reads stay elsewhere; for the reviewer it buys the cheapest real independence there is, a reader that never saw the code being written. The gates do not move either way: they run in the caller, on the diff, because an executor that reports its own success has reported nothing.

Requires Node 20.10 or newer. One context/ per repository.

Licence

The tool is MIT.

context/standards/ is vendored from baldurpan/ai-engineering-standards at the ref recorded in context/standards/.source. That repository carries no licence file, so the terms under which the vendored content may be redistributed are unsettled — it is bundled here on the author's own authority and nothing more. If you are installing this into a repository where that matters, run standards add <git-url> and point it at a tree whose terms you know.