{"slug": "show-hn-jpm-a-javascript-package-manager-in-rust-every-line-by-claude-code", "title": "Show HN: jpm – a JavaScript package manager in Rust, every line by Claude Code", "summary": "An engineer released jpm, a JavaScript package manager written in Rust in which every line was authored by Claude Code, claiming a cold nuxt install of 591 packages on GitHub CI in 1.22 seconds versus 1.28 seconds for bun 1.4.2 and 18.54 seconds for npm 12.1.0. jpm ships as a roughly 2 MB single binary, uses 34 MB of peak memory on a nuxt CI install against npm's 387 MB, and imports existing package-lock.json, pnpm-lock.yaml, yarn.lock and bun.lock files into its own jpm.lock without registry lookups. The project's own benchmarks show jpm fastest in 9 of 12 measured cells, with npm and yarn keeping smaller CI caches because they store compressed tarballs while jpm keeps files unpacked.", "body_md": "Every line written by Claude Code. Directed by one engineer. Checked against everyone else's tests.\n\n~2 MBone binary, no runtime to install\n\n1.22 scold nuxt install on GitHub CI\n\n34 MBmemory used to install nuxt on GitHub CI\n\nSpeed\n\nFast where your CI spends its time\n\nThree real projects, four install phases, eight package managers, against the live npm registry. On GitHub CI jpm is the fastest in 9 of 12 cells; the other three are shown as measured.\n\nMachine\n\nGitHub CI, LinuxmacOS, M4 MaxWindows 11\n\nPhase\n\ncoldwarmcirepeat\n\nProject\n\nnitronuxtnext\n\nNo cache, no lockfile, no node_modules.\n\nRepeat installs were not measured on Windows.\n\nInstall wall time, shorter is fasterGitHub CI, Linux · nuxt · 591 packages\n\njpm1.22 s\n\nbun1.28 s\n\npnpm1.72 s\n\naube3.00 s\n\nupm3.52 s\n\ndeno7.64 s\n\nyarn9.63 s\n\nnpm18.54 s\n\nGitHub CI, Linux, cold, nuxt · 591 packages\n\nPackage manager\n\nWall time\n\njpm\n\n1.22 s\n\nbun 1.4.2\n\n1.28 s\n\npnpm 12.8.1\n\n1.72 s\n\naube 2.6.0\n\n3.00 s\n\nupm 1.3.1\n\n3.52 s\n\ndeno 2.9.6\n\n7.64 s\n\nyarn 4.18.1\n\n9.63 s\n\nnpm 12.1.0\n\n18.54 s\n\njpm is the fastest here, 15× faster than npm.\n\nDefender 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 and pnpm. On Windows jpm is the fastest on next, not yet on nuxt.\n\nWall time, medians: ubuntu-latest with 4 cores (5 runs), macOS on an M4 Max (5 runs) and Windows 11 with Defender on (3 runs), 2026-09-30 and 2026-10-01. Full tables, with CPU time, in docs/benchmarks.md.\n\nGet started\n\nSwitch in one command\n\nRun jpm install in your project. jpm imports the lockfile you have into its own jpm.lock, with the same versions.\n\npackage-lock.json and npm-shrinkwrap.json (npm 7+), pnpm-lock.yaml (pnpm 9+) and bun.lock are carried over as they are: the same versions and the same tree, with no registry lookups.\n\nyarn.lock, from yarn 1 or yarn 2 and later, keeps every version yarn picked. jpm asks the registry only for what yarn.lock doesn't record: peers, platforms and bins.\n\nYour old lockfile is left untouched. Delete it when you're ready.\n\nCI keeps working during the switch: jpm ci and jpm install --frozen-lockfile install from the old lockfile as it is until jpm.lock is committed.\n\nIt also reads workspaces, pnpm-workspace.yaml, catalogs, overrides and resolutions, and patches.\n\nOlder formats, out-of-date lockfiles and the rest: docs/migrating.md.\n\nnpmpackage-lock.json\n\npnpmpnpm-lock.yaml\n\nyarnyarn.lock\n\nbunbun.lock\n\njpmjpm.lock\n\n```\njpm-lock 2\npackage @babel/[email protected]\n  integrity sha512-…\n  dep @babel/generator 7.29.8\nbash\n$ cd your-project\n$ jpm install   # reads package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock → writes jpm.lock\n```\n\nLean\n\nSmall enough to forget it's there\n\nOne binary with nothing behind it, an install that holds little in memory, and a store that keeps each file once.\n\nNot every number goes jpm's way: npm and yarn keep compressed tarballs, so their caches are smaller. jpm keeps its files unpacked, ready to link.\n\nGitHub CI, Linux, 2026-09-30. Binary sizes are the README's round figures.\n\nBinary size, approximate\n\njpm~2 MB\n\npnpm~60 MB\n\nbun~80 MB\n\naube~150 MB\n\nBinary size, approximate\n\njpm\n\n~2 MB\n\npnpm\n\n~60 MB\n\nbun\n\n~80 MB\n\naube\n\n~150 MB\n\nPeak memory, nuxt ci install\n\njpm34 MB\n\nbun89 MB\n\npnpm184 MB\n\nnpm387 MB\n\nPeak memory, nuxt ci install\n\njpm\n\n34 MB\n\nbun\n\n89 MB\n\npnpm\n\n184 MB\n\nnpm\n\n387 MB\n\nDisk after a cold nuxt install, node_modules and store\n\njpm244 MB\n\nbun261 MB\n\npnpm290 MB\n\nnpm443 MB\n\nDisk after a cold nuxt install, node_modules and store\n\njpm\n\n244 MB\n\nbun\n\n261 MB\n\npnpm\n\n290 MB\n\nnpm\n\n443 MB\n\nCI cache after a cold next install\n\nnpm194 MB\n\nyarn328 MB\n\njpm347 MB\n\npnpm433 MB\n\nbun466 MB\n\nCI cache after a cold next install\n\nnpm\n\n194 MB\n\nyarn\n\n328 MB\n\njpm\n\n347 MB\n\npnpm\n\n433 MB\n\nbun\n\n466 MB\n\nStorage\n\nEach file stored once. Each package built once.\n\njpm keeps one store per machine and builds each package's directory once, for every project that uses it. Installing again is mostly making links.\n\nA content-addressed store\n\nEach tarball is checked against its integrity, then unpacked once into ~/.jpm/store. Every file is kept once, by its hash, read-only.\n\nA global virtual store\n\nEach package is built once as an entry: name@version, plus a short digest of its dependency graph when it has dependencies. Its files are hardlinked from the store, and its dependencies are linked beside it, so it can import only what it declared.\n\nYour node_modules\n\nA project's node_modules links to those entries. A warm install makes only these few links: 4 ms for nitro on GitHub CI.\n\nEvery other project\n\nThe next project on the machine links to the same entries. When nothing changed, a repeat install checks a few links and is done in 1–2 ms.\n\nPause the animation\n\nNext.js and Nuxt: inside the project\n\nNext's Turbopack compiles nothing outside the project, and Nuxt imports packages it doesn't declare. For a project that depends on next or nuxt, jpm builds the entries in node_modules/.jpm instead, still hardlinked from the store.\n\nThe safe setting is the one you get without asking. Loosening one is your call, made in your own settings, not a package's or a cloned repository's.\n\nInstall scripts wait for you\n\nA dependency's install scripts, the way most npm malware runs, don't run until you jpm approve that package and version. A new version waits for approval again.\n\nNew versions wait a day\n\nA version published in the last day isn't picked (min-release-age), even when a package deep in the tree pins it exactly, so a hijacked release can't ride in on a pin.\n\nNo surprise sources\n\nA published package can't pull in git or tarball dependencies, or paths outside itself. Only your project and its workspaces choose where code comes from.\n\nChecked before it's visible\n\nEvery package is checked against its lockfile integrity before any of its files are visible to your project.\n\nNo secrets in the lockfile\n\nCredentials never land in jpm.lock: tokens stay in your .npmrc, and a git URL carrying a password is refused.\n\nA cloned repo can't lower the bar\n\nA project's own .npmrc can't turn off TLS checks, swap the CA or proxy, or loosen the release age. jpm ignores those there and names them in a warning.\n\nIts own TLS, no OpenSSL\n\njpm speaks TLS with its own code, tested against Project Wycheproof and the RFCs' vectors, and checks certificates against Mozilla's roots and your system's.\n\nRuntimes checked by signature\n\nA Node.js runtime a package asks for is checked against the release's SHASUMS256.txt, trusted only once its signature matches Node's release keys.\n\nLess to attack\n\nOne ~2 MB binary, with no runtime and no dependency tree of its own to install: less code between you and the registry.\n\nWritten by Claude Code. Checked by everyone else's tests.\n\nIt started with an episode of the Syntax podcast that held up upm as faster and smaller than the rest. Small, because it runs on Node.js. So: what if it were ported to Rust and made small for real? And what would it take to turn an AI's one-shot into something you'd trust in CI?\n\nClaude Code, running Claude Opus 5.5, wrote every line, its own TLS and crypto included. JT Turner, an engineer of 27 years, made the calls. When Claude pushed back on writing our own TLS, the condition was: test it like we didn't trust it. So every \"it works\" is checked against someone else's tests: Wycheproof, the RFCs, and the suites of npm, pnpm, yarn and bun.\n\nThe numbers decide. An HTTP/2 client was built, benchmarked on GitHub's runners and a desktop, found slower and hungrier for CPU, and deleted.\n\nIs jpm perfect? No. Perfect doesn't exist. There's good enough, there's great, and there's tested enough to know which one you have.\n\nLoading the counts…install scripts handed out since getjpm.sh launched\n\nLoading the counts…downloads of the jpm binary from GitHub\n\nWhat this counts\n\nEach time getjpm.sh hands out an install script, it adds one to a count kept for that script, the path asked for and the day. Nothing else is recorded: no IP address, no browser details, no cookies, no identifiers. We can't tell who you are or tell one person from another, and a download isn't always an install. The binary count is GitHub's own tally of downloads of jpm's release files. Both numbers refresh about once an hour.", "url": "https://wpnews.pro/news/show-hn-jpm-a-javascript-package-manager-in-rust-every-line-by-claude-code", "canonical_source": "https://getjpm.sh/", "published_at": "2026-10-04 00:11:58+00:00", "updated_at": "2026-10-04 00:36:33.723897+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents"], "entities": ["jpm", "Claude Code", "npm", "bun", "pnpm", "yarn", "Rust", "GitHub CI"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-jpm-a-javascript-package-manager-in-rust-every-line-by-claude-code", "markdown": "https://wpnews.pro/news/show-hn-jpm-a-javascript-package-manager-in-rust-every-line-by-claude-code.md", "text": "https://wpnews.pro/news/show-hn-jpm-a-javascript-package-manager-in-rust-every-line-by-claude-code.txt", "jsonld": "https://wpnews.pro/news/show-hn-jpm-a-javascript-package-manager-in-rust-every-line-by-claude-code.jsonld"}}