Package manager
alongside npm · pnpm · yarn
npm-compatible resolution, a reviewable lockfile, and a hoisted node_modules hardlinked from one shared store.
$ opal install
A package manager today, with a runtime, bundler and test runner planned, in a single binary. Use opal install in an existing Node.js project: it installs what npm would, from one store shared by every project.
Install Opal v0.4.1
curl -fsSL https://opalx.dev/install.sh | bash
Linux x64 and arm64 (glibc 2.34 or newer), macOS x64 and Apple Silicon. Checked against the release's SHA256 checksums.
On Windows, Opal runs inside WSL2: open a WSL terminal and run the same command. Native Windows isn't supported yet.
Next.js 16.3.2 defaults · about 360 packages · Ryzen 5 5625U, Linux under WSL2 · install scripts off for every tool · median of 5 · measured 2026-10-06 with the v0.4.0 release binary · first installs and CI are slower than this; every scenario is in the grid below method
Installs tested on
opal install drops into an existing Node.js project. No runtime switch required.
alongside npm · pnpm · yarn
npm-compatible resolution, a reviewable lockfile, and a hoisted node_modules hardlinked from one shared store.
$ opal install
will replace node
JavaScript and TypeScript on V8, loading modules through the same resolver the package manager uses.
opal run · not built yet
will replace esbuild · webpack
Tree-shaking and minification over the shared graph, with outputs cached by the hash of their inputs.
opal build · not built yet
will replace jest · vitest
Test discovery through the shared graph, with assertions and a reporter, running on Opal's own runtime.
opal test · not built yet
A minute with Opal
Install, re-run, add a package, lock it down for CI, check the store, and upgrade. Every step below is a real command with real output — click one.
Real output from Opal v0.4.1 on a 364-package Next.js app, abridged and sped up. Hover to pause.
v0.4.1 Latest release · October 2026
v0.4.1 stops opal add and opal remove re-checking packages the lockfile already holds, names the commit a build came from, and installs, builds, and serves seven framework starters every night.
opal upgrade
opal --revision prints the version and the commit a build came frominstall.sh run as root no longer leaves the binary owned by uid 1001opal add fail until it is deletedTested, not claimed
A package manager that is fast and occasionally wrong is not fast. These are the properties Opal tests for, with the numbers from the test runs.
432/433
On a 364-package Next.js app, 432 of npm's 433 package versions are identical. The differences are documented, and a CI job fails if a new one appears.
332kills
Every write is atomic and the linker is a reconciler. In one soak, 332 SIGKILLs interrupted a running install; re-running converged on a clean tree every time. Against the real registry, 252 more did the same across express and a Next.js app, 90 of them with the v0.4.0 binary.
33MB
Peak memory installing express was 33 MB, against 160 MB for npm and 26 MB for bun: second lowest of the five. On a Next.js app it was third, 491 MB against bun's 216 MB and npm's 464 MB. Same run as the charts below.
1store
Packages are verified against the registry's integrity hash, stored once per machine, and hardlinked into each project. A second copy of a Next.js app added 10.5 MB on disk, against 463 MB with npm; bun and pnpm share files too, and added 8.3 and 13.7 MB.
opal install
A first install, CI with and without its cache, a reinstall, a no-op, adding one package, and what a second copy costs on disk, against npm, pnpm, yarn and bun at their defaults. Opal's losses are on the same page as its wins.
Measured 2026-10-06 on an AMD Ryzen 5 5625U (WSL limited to 8 of 12 threads, 16 GB, Linux under WSL2) with the v0.4.0 release binary, npm 12.0.2, pnpm 11.21.0, yarn 1.22.22 and bun 1.4.2. One machine and one session. A second machine ran the same binary: Opal stands on the same side of npm in every chart there, and on a Next.js reinstall it is level with bun where here it is ahead. Its tables are in the benchmark notes. Each tool added the package with its own add command; one of Opal's three Next.js rounds took 6.0s, which the median hides. The raw samples for these charts are in the repository.
Read before you switch
Worth knowing before you point Opal at a project. The first three are asserted by tests, so the suite says what doesn't work as plainly as what does.
node-gyp installs but isn't built, and opal install names it every time.git: and file: dependencies are refused. Dependencies come from a registry only. Both are planned for v0.5.0.update yet. opal add and opal remove change one dependency and keep the rest of the lockfile where it is; delete opal.lock to re-resolve everything. --peer, --global, and adding to a folder with no package.json are planned for v0.5.0. Commands that aren't built aren't in the binary.opal add with nothing cached asks the registry about every package. On a Next.js app that takes 5–7s, as on a machine that installed from a lockfile. With metadata cached, however old, an add takes about half a second.Install Opal, open a project you can reinstall, and run opal install. Your code and your package.json stay exactly as they are; Opal is pre-1.0, so its lockfile format can still change.
curl -fsSL https://opalx.dev/install.sh | bash
On Windows, Opal runs inside WSL2: open a WSL terminal and run the same command. Native Windows isn't supported yet.