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

@deliciousmonster/harper-binary-kit

v0.1.0-next.4

Published

Ship a native binary from a Harper component: one platform package per host, staged, verified, published, and resolved back at runtime

Readme

harper-binary-kit

Ship a native binary from a Harper component. One npm package per host carries that host's binaries, the component depends on them optionally so npm installs only the matching one, and at runtime the component asks the installed package where its binary landed rather than computing a path.

That last sentence is the whole design, and both halves live here: stage writes the module that answers, and resolve is what calls it. They are one package because separately they agree with themselves.

Plain ESM, node: builtins only, no build step. Node 22.18+ or 24+.

Install

npm install @deliciousmonster/harper-binary-kit          # the runtime half
npm install -D @deliciousmonster/harper-binary-kit       # and the CLI, if the same repo builds

Declare

binary-kit.config.js at the repo root is the single declaration every step reads:

export default {
	scope: '@acme/agent-binary',
	targets: ['linux-x86_64', 'linux-arm64', 'macos-arm64', 'windows-x86_64'],
	variants: [
		{ suffix: '' },
		{
			suffix: '-probe',
			optional: true,
			carries: 'It carries the probe and 42 MB of precompiled objects, which most nodes never load.',
			// A plain string is carried everywhere this variant publishes. Name targets when only some carry
			// it: the same binary can reach the kernel a different way per platform, and a directory two of
			// three have nothing for would refuse to stage them.
			extraDirs: [{ dir: 'share/probe', onlyOn: ['linux-x86_64', 'linux-arm64'] }],
		},
	],
	binaries: [
		{ shipsAs: 'agent', symbol: 'CONNECTIONS_CHECK' },
		{ shipsAs: 'trace-agent' },
		{ shipsAs: 'probe', variant: '-probe', onlyOn: ['linux-x86_64', 'linux-arm64'] },
	],
	floors: { 'linux-x86_64': { GLIBC: '2.36', GLIBCXX: '3.4.30' } },
	manifest: { license: 'Apache-2.0', repository: { type: 'git', url: '…' } },
	readme: (pkg) => `# ${pkg.name}\n\n…where these bytes came from…`,
};

Building is yours. Leave the binaries at build/<target>/bin and anything shipped beside them under build/<target>/, and the kit takes it from there. A build step that would rather ask than hardcode those paths imports them:

import { buildTree } from '@deliciousmonster/harper-binary-kit/layout';

const { bin, share } = buildTree(process.cwd(), 'linux-x86_64');

Four processes meet at those paths on four separate runners, so a build that recomputes them is a convention with two owners.

Resolve, at runtime

import { createBinaryResolver } from '@deliciousmonster/harper-binary-kit/resolve';

const resolver = createBinaryResolver({
	packageName: '@acme/agent-binary',
	packageRoot: `${import.meta.dirname}/..`,
	variants: [{ suffix: '' }, { suffix: '-probe', optional: true, carries: '…' }],
	// From YOUR module: a bare specifier resolves against the file the `import` is written in, so a resolver
	// importing from inside this package would look for your platform packages beside this one.
	load: (name) => import(name),
});

const path = await resolver.resolveBinary({ shipsAs: 'agent', title: 'the agent' });

Each variant is asked in order, then a dev checkout's own build/<target>/bin. A binary that resolves to the wrong file is refused rather than returned: a platform package published before a second binary existed answers every request with the first one, and that path exists on disk.

Release, in CI

harper-binary-kit stage      # build trees -> npm/<name>/, manifest, index.js, README
harper-binary-kit floor linux-x86_64   # symbol versions against the image the binaries ship to
harper-binary-kit verify     # what npm WOULD pack, per package
harper-binary-kit publish    # every package, attempting all of them, then read the registry back
harper-binary-kit latest     # point latest at this release, forward only
harper-binary-kit deps       # what optionalDependencies should say, for `npm version`
harper-binary-kit names      # every package name, for a workflow that needs the list

.github/workflows/release.yml is a reusable workflow that calls these in order. Its matrix comes from targets, so the list a package publishes and the list CI builds cannot disagree.

What each step is defending against

Every one of these shipped before the step existed.

stage refuses a package whose binary the build did not produce, and refuses an --only that matches nothing. Both used to report success: --only <name> filtered against the current host's platform, so on a developer's machine of another platform it staged nothing and printed "created successfully".

floor reads the symbol versions a binary needs against what the target image provides. A build on a newer runner produces a binary that will not load at all on the image it ships to, the failure is at exec time on the customer's node, and every test on the runner that built it passes.

verify asks npm what it would pack rather than reading the directory. files, .npmignore and npm's own lists all apply at pack time, so a package can look correct in a checkout and ship without the binary it exists for. A declared symbol catches the one defect a file listing cannot see: a binary present, correctly named, the right size, and compiled without the thing it is for.

publish attempts every package and collects the failures rather than stopping at the first. npm answers a publish to a name with no trusted publisher with 404 rather than 403, so "not configured" and "not there" read identically and trying is the only way to find out. Then it reads the registry back, at the version endpoint: npm publish exiting 0 is not the package being there, and the packument lags its own writes by long enough to send somebody chasing a partial release that never happened.

latest moves the tag forward only. npm assigns latest on a package's first publish and never again, so a package released only under a prerelease tag freezes at whatever version created the name — and latest is what npmjs.com shows and what a bare npm install gets.

Development

npm test is node --test, no build. npm run typecheck is tsc --noEmit.

test/unit/contract.test.js is the one to read first: every case stages a real package into a temp directory and resolves a binary back out of it, because a resolver driven by a hand-written fake proves nothing about the module the staging actually writes.