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

@intentic/registry

v1.227.0

Published

The extension-registry file format, a git repo of sha-pinned pointers, shared by the daemon, the site gallery and the scanner

Downloads

5,518

Readme

@intentic/registry

The extension-registry file format: what a registry repo contains, how its two files join, and the order the result is shown in. Published to npm, and depended on by three otherwise-unrelated consumers, which is the whole reason it is a package: the daemon that clones a registry, the site that builds the public gallery, and the scanner that writes the files. One zod schema instead of three that drift.

See Publish & registries for the author-facing version of everything below, and Verification & trust for what each trust state claims.

The shape of it

intentic hosts no extension code, builds none, and signs none. A registry is a git repo of pointers: each entry names somebody else's repository at a commit, and installing follows that pointer from the owner's sandbox straight to the author's git host. Listing costs a pull request; delisting removes a pointer and deletes nothing.

The file is .claude-plugin/marketplace.json, Claude Code's plugin-marketplace format, deliberately. kind and trust are intentic's own fields and Claude Code ignores what it doesn't recognise, so one repo lists a team's agent plugins and its intentic extensions together.

Two files, and why

| File | Written by | Holds | | --- | --- | --- | | .claude-plugin/marketplace.json | humans + protected admission workflow | every decision: what is listed, the exact source, trust level, and source-bound security record | | .claude-plugin/registry.generated.json | the nightly scanner | only facts read back off the source host: stars, last push |

Keeping the derived data out of the curated file is load-bearing, not tidiness. Star counts in the hand-edited file would make every nightly refresh a merge conflict against every open listing pull request, and would bury the decision under churn in the review diff. A registry with no generated file is a registry with no stars, which renders fine: most registries are a dozen internal extensions in a private repo and run no scanner.

resolveRegistry joins them by entry name into RegistryEntry, which is also the daemon's browse wire shape, so the app's list and the website's gallery are the same rows in the same order.

Trust, and what each state claims

In the official registry, listed means the exact source passed the deterministic scan and intentic agent audit, but no human source review is claimed. verified means a human also read that same source. blocked means known-malicious or known-broken, with the required reason alongside. A verified row without a securityReview, a review copied from another repository/sha/subdirectory, or a blocked row without a reason does not parse.

securityReview records the repository, commit, subdirectory, both versioned policies, scanner and version, timestamp, Trivy workflow run and agent-gate run. The official resolver accepts only current Trivy and Intentic policies with that complete subject equal to the install pointer. A row missing either stays visible in the app with install disabled and is omitted from the public gallery; it cannot become an update offer either. This is the runtime backstop behind the registry's required PR check.

A blocked entry stays in the file. Deleting the row hides it from people browsing and tells the people who already installed it nothing, which is backwards: they are the ones at risk. Absent on a third-party registry resolves to listed, because a registry that doesn't use the field hasn't asserted anything. Third-party registries are their own admission boundary: their non-blocked rows remain installable without adopting intentic's gate or policy, and the app states when they carry no audit record.

Installed sandboxes read these states back on a daily comparison, so trust reaches the people past the browse moment too: a row turned blocked raises an advisory on the installed extension (and, by default, switches it off), and securityFix: true on an entry marks its pinned commit as fixing a security problem in earlier ones

  • the installed side promotes its update badge from ambient to loud, because there the OLD version is the dangerous one. Both are asserted by pull request, like trust, and are worth exactly that review.

Tier, and what premium buys into

tier is the listing's price: free (the default, and the whole story for most rows) or premium, the listing opts into the creator pool. A premium row needs an intentic membership, both surfaces badge it before the click, and installing it donates a published number of the member's credits to the publisher (once, deduped monthly: updates donate again at most monthly). No usage is metered or reported anywhere; the deliberate install is the whole signal. The economics live in The creator pool.

The mark

A row carries the two display tiers the manifest declares: logo (a simple-icons slug) and icon (a glyph from the app's own set): and the scanner copies whichever is set into the listing it proposes, exactly as it copies the version. A row with neither is drawn as the extension's initials.

They ride the curated file, which looks wrong for a copied value until you ask what the two files are for: the mark is part of how a listing presents itself, so it belongs in the row a human reviews and can correct. It also has to be here to be worth anything: the gallery and the app's browse list render this row and have no access to the manifest, because the whole point of browsing is that the code has not been cloned yet.

The order

compareEntries: verified first, then stars, then most-recently-pushed, then name. Stars are the obvious sort and the wrong one alone: every listing sits at nought to three of them for months, so a pure star sort is a random order wearing a merit badge, and it is the most purchasable number on GitHub. Recency is what actually does the ordering early on. Stars stay visible; they just don't get to be the ranking.

Identity

An entry's name is publisher.name from the manifest: extensionIdOf, the same identity the app installs under. It is derived, never declared by the registry, so a registry entry cannot rename or spoof an extension, and a repo that copies somebody else's manifest collides with their listing instead of shadowing it.

isShaPinned is the other half: an extension install requires a full 40-character commit sha, because extension code runs trusted in the owner's browser and a branch name is a promise the upstream can break with a force-push. A registry entry without one still lists and still reads; it just can't be installed in a click.

The sha is necessary but does not confine the code. A browser entry runs in the app's JavaScript realm with page, browser-storage and network access; server/process/agent/bin/environment contributions have their own execution surfaces. The manifest gates cooperative calls through the extension API, not arbitrary browser behavior. Deterministic scanning catches known dependency, secret and configuration findings; the agent audit exists because neither those signatures nor manifest validation can answer malicious intent.

Key files