jtwebman/jpm

A fast, small package manager for the npm registry, written in Rust

Rust

0

394 commits

updated Oct 15, 2026

See the code

See what people are saying

SourceMessageScoreDate

What it took to trust a package manager Claude wrote · jpm (r/ClaudeAI)

This is the story of how I made a very small 2 MB, fast, and secure Node.js package manager using Claude Code and Opus 5.5 model in a short time in Rust. Claude built the first version in a afternoon but it wasn't that good. Then I had Claude run for 5 days in a loop hardening it. Had it download…

3

Oct 17, 2026

What it took to trust a package manager Claude wrote

1

Oct 16, 2026

Show HN: jpm – a JavaScript package manager in Rust, every line by Claude Code

6

Oct 4, 2026

README

jpm

A fast, small, secure-by-default package manager for JavaScript, written in Rust.

curl -fsSL https://getjpm.sh | sh                  # macOS and Linux
irm https://getjpm.sh/install.ps1 | iex              # Windows

Then jpm install in any npm, pnpm, yarn or bun project: it reads your lockfile and keeps its versions. One ~2 MB binary, benchmarks, and 166 real projects installing on Linux, macOS and Windows. More at getjpm.sh.

I didn't write a line of jpm. Claude Code, running Claude Opus 5.5, wrote every one of them, including its own TLS and crypto: the two things every engineer knows you never write yourself.

I've been a professional software engineer for 27 years, mostly three-tier business software: C# until 2012, then Elixir and Node.js. The last time I wrote low-level code was in C, as a kid. I'm not the engineer you'd pick to write a package manager. That's the point.

How it started

I was watching an episode of the Syntax podcast when they held up upm as a package manager that was faster and smaller than the rest. Fast, yes. But small? I called foul: it's small because it runs on Node.js. They were also asking the AI questions everyone is asking right now. Can it build real software, or just demos? Should engineers be worried, or excited? Most people believe AI can one-shot anything. It can. The result just usually isn't very good.

So I asked my own questions: what if we ported upm to Rust and made it faster and smaller for real? And what would it take to turn an AI's one-shot into something you'd trust in CI? On September 28, 2026, at 3:38 in the afternoon, the first commit landed: Port upm to Rust as jpm. By that evening it had its own HTTP client, JSON reader, crypto and TLS 1.3.

That was the easy part. The afternoon was the one-shot. The next days were the part nobody posts about:

  • hundreds of bugs fixed;
  • a security review;
  • install scripts locked down;
  • reading upm's, pnpm's, bun's and aube's source to understand how they did things fast;
  • profiling until the numbers moved.

What directing looked like

I made maybe a hundred calls, asking things like:

  • What should the security defaults be?
  • Should we follow npm here, or pnpm?
  • What if we tried this?

Sometimes the answer was "that doesn't feel right", and sometimes "don't do that".

Twice Claude pushed back: when I wanted our own TLS, and our own HTTP stack. I insisted, on one condition: test it like we didn't trust it. Writing it ourselves meant we could leave out everything a general-purpose library has to carry, like logging, options and special cases. We needed one thing: a fast, safe GET. So it came out smaller and faster.

Once, I was wrong. I pushed for HTTP/2. We built our own HTTP/2 client and benchmarked it on GitHub's runners and my own machine. It used more CPU and was slower in some cases, so we deleted it. The numbers decided, not me.

Why you can trust code nobody typed

Because none of it is trusted on its word. Every "it works" in jpm is checked against someone else's tests:

  • Crypto: Google's Project Wycheproof crypto vectors and the RFCs' test vectors.
  • npm: node-semver's, npm-package-arg's and hosted-git-info's own test cases, and npm arborist's lockfiles.
  • pnpm: its registry-mock scenarios, diffed against what pnpm itself installs.
  • yarn: berry's acceptance scenarios, the "dragon tests" included.
  • bun: its install tests and lockfiles.
  • Real projects: 166 large ones, with npm, pnpm, yarn and bun lockfiles, on Linux, macOS and Windows. All 166 install on all three, four with a setting their own dependencies need: each one installed, again as a no-op, from its lockfile alone, from nothing, and verified (the corpus).

None of the speed is mine either. It came from reading the code that great engineers shared with the world (upm, pnpm, bun and aube) and asking how they did it.

Is jpm perfect? No. Neither is anything I've written by hand in 27 years, or anything any human has written. Perfect doesn't exist. There's good enough, there's great, and there's tested enough to know which one you have.

Where it stands

Wall time to install nuxt (591 packages). The best in each column is bold.

GitHub Actions, Linux (ubuntu-latest, 4 cores, median of 5):

managercoldwarm (cache restored)ci (no cache)repeat
jpm1.22 s206 ms734 ms2 ms
bun 1.41.28 s234 ms676 ms18 ms
aube 2.63.00 s186 ms896 ms7 ms
pnpm 12.81.72 s435 ms1.53 s11 ms
deno 2.97.64 s338 ms1.20 s28 ms
upm 1.33.52 s447 ms2.06 s44 ms
yarn 4.189.63 s3.13 s5.58 s1.02 s
npm 12.118.5 s4.69 s6.62 s794 ms

Windows 11, Defender on (i9-12900K, median of 3):

managercoldwarm (cache restored)ci (no cache)
jpm8.53 s1.45 s8.01 s
upm 1.37.40 s4.41 s6.80 s
npm 12.111.9 s4.84 s5.15 s
pnpm 12.89.14 s3.75 s8.81 s
aube 2.617.4 s491 ms16.0 s

macOS (M4 Max, median of 5):

managercoldwarm (cache restored)ci (no cache)repeat
jpm3.02 s594 ms2.81 s12 ms
bun 1.43.02 s472 ms2.92 s117 ms
aube 2.68.37 s335 ms6.61 s186 ms
pnpm 12.85.92 s900 ms6.22 s22 ms
deno 2.98.88 s697 ms4.35 s26 ms
upm 1.36.43 s3.04 s5.77 s60 ms
yarn 4.186.18 s2.71 s4.18 s462 ms
npm 12.19.23 s3.15 s3.65 s514 ms
  • Linux: across three projects, jpm is the fastest of eight managers in 9 of 12 cells, uses the least memory in 11 of 12, and the least disk in all three.
  • macOS: across three projects, jpm is the fastest of eight managers in 9 of 12 cells and uses the least memory in 11 of 12. A warm install is not the fastest yet: bun and aube beat it on nuxt.
  • Windows: jpm is the fastest on next, but not on nuxt yet. Defender scans every file an install writes, and it scans files written by node.exe (npm, upm) far more cheaply than files written by native tools like jpm, aube or pnpm.
  • The binary: about 2 MB. bun is about 80 MB, pnpm 60 MB and aube 150 MB.

Every table, with CPU, memory, disk and cache: docs/benchmarks.md.

Try it

curl -fsSL https://getjpm.sh | sh                  # macOS and Linux
irm https://getjpm.sh/install.ps1 | iex              # Windows

Then, in a project that uses npm, pnpm, yarn or bun:

jpm install          # reads your lockfile, writes jpm.lock with the same versions
jpm run build

jpm is secure by default:

  • A dependency's install scripts, the way most npm malware runs, don't run until you approve that package and version (jpm approve).
  • New versions are held back for a day.
  • A published package can't pull in git or tarball dependencies.
  • Every package is checked against its lockfile integrity before it is visible.

More: install, usage, migrating, configuration, install scripts, the lockfile, overrides and package extensions, patches, directory and git dependencies, runtimes, how it works, development.

Why "jpm"?

I wondered why the JavaScript package manager wasn't called the JavaScript Package Manager. Then I remembered JavaScript is a trademark. So: jpm.

The end, and your turn

I didn't write a line of jpm. I asked a lot of questions, said no a few times, was wrong at least once, and made it prove everything. Give the same idea to ten engineers and you'd get ten different package managers, some of them better than this one. What's changed is that the TLS stack you'd have talked yourself out of, because it was two weeks of work, is now an afternoon. And a few more days, once you've hardened it and chased out the bugs.

So: try jpm in your CI. Then go build the thing you didn't think you had time for.

License

MIT, Copyright (c) 2026 JT Turner. jpm started as a port of upm, Copyright (c) Pooya Parsa, also MIT. See LICENSE. THIRD_PARTY_NOTICES.md credits the code, crates and test data jpm builds on, and ships with every release.

bun
cli
javascript
linux
lockfile
macos
monorepo
nodejs
npm
package-manager
pnpm
rust
supply-chain-security
typescript
windows
workspaces
yarn

jtwebman/jpm

A fast, small package manager for the npm registry, written in Rust

Rust

0

394 commits

updated Oct 15, 2026

See the code

See what people are saying

SourceMessageScoreDate

What it took to trust a package manager Claude wrote · jpm (r/ClaudeAI)

This is the story of how I made a very small 2 MB, fast, and secure Node.js package manager using Claude Code and Opus 5.5 model in a short time in Rust. Claude built the first version in a afternoon but it wasn't that good. Then I had Claude run for 5 days in a loop hardening it. Had it download…

3

Oct 17, 2026

What it took to trust a package manager Claude wrote

1

Oct 16, 2026

Show HN: jpm – a JavaScript package manager in Rust, every line by Claude Code

6

Oct 4, 2026

README

jpm

A fast, small, secure-by-default package manager for JavaScript, written in Rust.

curl -fsSL https://getjpm.sh | sh                  # macOS and Linux
irm https://getjpm.sh/install.ps1 | iex              # Windows

Then jpm install in any npm, pnpm, yarn or bun project: it reads your lockfile and keeps its versions. One ~2 MB binary, benchmarks, and 166 real projects installing on Linux, macOS and Windows. More at getjpm.sh.

I didn't write a line of jpm. Claude Code, running Claude Opus 5.5, wrote every one of them, including its own TLS and crypto: the two things every engineer knows you never write yourself.

I've been a professional software engineer for 27 years, mostly three-tier business software: C# until 2012, then Elixir and Node.js. The last time I wrote low-level code was in C, as a kid. I'm not the engineer you'd pick to write a package manager. That's the point.

How it started

I was watching an episode of the Syntax podcast when they held up upm as a package manager that was faster and smaller than the rest. Fast, yes. But small? I called foul: it's small because it runs on Node.js. They were also asking the AI questions everyone is asking right now. Can it build real software, or just demos? Should engineers be worried, or excited? Most people believe AI can one-shot anything. It can. The result just usually isn't very good.

So I asked my own questions: what if we ported upm to Rust and made it faster and smaller for real? And what would it take to turn an AI's one-shot into something you'd trust in CI? On September 28, 2026, at 3:38 in the afternoon, the first commit landed: Port upm to Rust as jpm. By that evening it had its own HTTP client, JSON reader, crypto and TLS 1.3.

That was the easy part. The afternoon was the one-shot. The next days were the part nobody posts about:

  • hundreds of bugs fixed;
  • a security review;
  • install scripts locked down;
  • reading upm's, pnpm's, bun's and aube's source to understand how they did things fast;
  • profiling until the numbers moved.

What directing looked like

I made maybe a hundred calls, asking things like:

  • What should the security defaults be?
  • Should we follow npm here, or pnpm?
  • What if we tried this?

Sometimes the answer was "that doesn't feel right", and sometimes "don't do that".

Twice Claude pushed back: when I wanted our own TLS, and our own HTTP stack. I insisted, on one condition: test it like we didn't trust it. Writing it ourselves meant we could leave out everything a general-purpose library has to carry, like logging, options and special cases. We needed one thing: a fast, safe GET. So it came out smaller and faster.

Once, I was wrong. I pushed for HTTP/2. We built our own HTTP/2 client and benchmarked it on GitHub's runners and my own machine. It used more CPU and was slower in some cases, so we deleted it. The numbers decided, not me.

Why you can trust code nobody typed

Because none of it is trusted on its word. Every "it works" in jpm is checked against someone else's tests:

  • Crypto: Google's Project Wycheproof crypto vectors and the RFCs' test vectors.
  • npm: node-semver's, npm-package-arg's and hosted-git-info's own test cases, and npm arborist's lockfiles.
  • pnpm: its registry-mock scenarios, diffed against what pnpm itself installs.
  • yarn: berry's acceptance scenarios, the "dragon tests" included.
  • bun: its install tests and lockfiles.
  • Real projects: 166 large ones, with npm, pnpm, yarn and bun lockfiles, on Linux, macOS and Windows. All 166 install on all three, four with a setting their own dependencies need: each one installed, again as a no-op, from its lockfile alone, from nothing, and verified (the corpus).

None of the speed is mine either. It came from reading the code that great engineers shared with the world (upm, pnpm, bun and aube) and asking how they did it.

Is jpm perfect? No. Neither is anything I've written by hand in 27 years, or anything any human has written. Perfect doesn't exist. There's good enough, there's great, and there's tested enough to know which one you have.

Where it stands

Wall time to install nuxt (591 packages). The best in each column is bold.

GitHub Actions, Linux (ubuntu-latest, 4 cores, median of 5):

managercoldwarm (cache restored)ci (no cache)repeat
jpm1.22 s206 ms734 ms2 ms
bun 1.41.28 s234 ms676 ms18 ms
aube 2.63.00 s186 ms896 ms7 ms
pnpm 12.81.72 s435 ms1.53 s11 ms
deno 2.97.64 s338 ms1.20 s28 ms
upm 1.33.52 s447 ms2.06 s44 ms
yarn 4.189.63 s3.13 s5.58 s1.02 s
npm 12.118.5 s4.69 s6.62 s794 ms

Windows 11, Defender on (i9-12900K, median of 3):

managercoldwarm (cache restored)ci (no cache)
jpm8.53 s1.45 s8.01 s
upm 1.37.40 s4.41 s6.80 s
npm 12.111.9 s4.84 s5.15 s
pnpm 12.89.14 s3.75 s8.81 s
aube 2.617.4 s491 ms16.0 s

macOS (M4 Max, median of 5):

managercoldwarm (cache restored)ci (no cache)repeat
jpm3.02 s594 ms2.81 s12 ms
bun 1.43.02 s472 ms2.92 s117 ms
aube 2.68.37 s335 ms6.61 s186 ms
pnpm 12.85.92 s900 ms6.22 s22 ms
deno 2.98.88 s697 ms4.35 s26 ms
upm 1.36.43 s3.04 s5.77 s60 ms
yarn 4.186.18 s2.71 s4.18 s462 ms
npm 12.19.23 s3.15 s3.65 s514 ms
  • Linux: across three projects, jpm is the fastest of eight managers in 9 of 12 cells, uses the least memory in 11 of 12, and the least disk in all three.
  • macOS: across three projects, jpm is the fastest of eight managers in 9 of 12 cells and uses the least memory in 11 of 12. A warm install is not the fastest yet: bun and aube beat it on nuxt.
  • Windows: jpm is the fastest on next, but not on nuxt yet. Defender scans every file an install writes, and it scans files written by node.exe (npm, upm) far more cheaply than files written by native tools like jpm, aube or pnpm.
  • The binary: about 2 MB. bun is about 80 MB, pnpm 60 MB and aube 150 MB.

Every table, with CPU, memory, disk and cache: docs/benchmarks.md.

Try it

curl -fsSL https://getjpm.sh | sh                  # macOS and Linux
irm https://getjpm.sh/install.ps1 | iex              # Windows

Then, in a project that uses npm, pnpm, yarn or bun:

jpm install          # reads your lockfile, writes jpm.lock with the same versions
jpm run build

jpm is secure by default:

  • A dependency's install scripts, the way most npm malware runs, don't run until you approve that package and version (jpm approve).
  • New versions are held back for a day.
  • A published package can't pull in git or tarball dependencies.
  • Every package is checked against its lockfile integrity before it is visible.

More: install, usage, migrating, configuration, install scripts, the lockfile, overrides and package extensions, patches, directory and git dependencies, runtimes, how it works, development.

Why "jpm"?

I wondered why the JavaScript package manager wasn't called the JavaScript Package Manager. Then I remembered JavaScript is a trademark. So: jpm.

The end, and your turn

I didn't write a line of jpm. I asked a lot of questions, said no a few times, was wrong at least once, and made it prove everything. Give the same idea to ten engineers and you'd get ten different package managers, some of them better than this one. What's changed is that the TLS stack you'd have talked yourself out of, because it was two weeks of work, is now an afternoon. And a few more days, once you've hardened it and chased out the bugs.

So: try jpm in your CI. Then go build the thing you didn't think you had time for.

License

MIT, Copyright (c) 2026 JT Turner. jpm started as a port of upm, Copyright (c) Pooya Parsa, also MIT. See LICENSE. THIRD_PARTY_NOTICES.md credits the code, crates and test data jpm builds on, and ships with every release.

bun
cli
javascript
linux
lockfile
macos
monorepo
nodejs
npm
package-manager
pnpm
rust
supply-chain-security
typescript
windows
workspaces
yarn