thinking about the niche #orogene fits into, in a world with stuff like bun/deno/etc, and honestly I think the right thing to optimize for isn't node apps, but webdev that happens to use node tooling?

I feel like that space has been kinda stagnant for a while. NPM/pnpm/yarn are all kinda basically the same thing, and the few experiments that have happened have kinda flopped straight on their face (like uhhh... PnP/Berry).

Ok so... here's a weird thing I'm planning on doing with #orogene:

instead of package.json, you'll have an oro.kdl that looks like this:

package {
name "my-pkg"
version "1.2.3"
description "My cool package"
scripts {
build "webpack" depends-on="lint"
lint "eslint"
dependencies {
lodash "workspace:*"

workspace {
members "./packages/*"
dependencies {
lodash "^1.2.3"

options {
registry ""

Orogene then auto-generates package.json files as needed so that node &co can consume them.

What do y'all think? See also if you're not already aware. I literally created this language for this purpose!

Just re-rendered the benchmarks for #orogene and we're looking pretty good 😎

Cold Cache Comparison

Orogene is the fastest out of yarn/pnpm/npm/bun, by a lot: the install took less than 10 seconds.
Warm Cache Comparison

Orogene and bun are neck-to-neck, at ~500ms installation time, with all the other package managers taking between 5 and 25 seconds

What do y'all think of this as the behavior of an #orogene oro build command?

tl;dr: apply doesn't run toplevel install scripts, and you need an additional build command, which also runs build scripts, to do that.

The idea is that apply can always be fast and implicit and only deals with your dependencies.

Just tagged #orogene v0.3.26. Along with a couple of fixes, this vastly improves contextual information when IO errors happen, and makes it so parallel install script execution actually happens in dependency order (it used to be fully-parallel/random). This latter one was a doozy to implement lol.

You can install it from npm or use it through npx now!: npx oro --version


Thanks to @isntitvacant, #orogene now has a logo! and it's really cool! Thanks everyone for voting on it, and thanks to everyone who made submissions with their ideas!

I've added this logo to the site/favicon/readme/etc. I'm really stoked about it, I love it sm.

A floating mountain with snowy peaks, surrounded by levitating purple rings that are presumably holding them up.

Full docs are available for the #orogene telemetry stuff over here:

I did my best to make sure this stuff is transparent, anonymous, and respectful. There’s no trickery to try and get you to opt in, and it’s easy to opt out even in a per-project or even per-command basis.

Let me know how y’all feel about this approach!

New #orogene release is out! This one, plus 0.3.24, include various fixes, as well as the new telemetry stuff. I’d love to hear what y’all think of the onboarding/communication about that.

You can try orogene with npx!: npx oro -h

meh. This telemetry code pushed #orogene's binary size from 12.9mb to 13.9mb, and I'm kinda unhappy about it, but that difference will be much smaller when the binary's compressed, and it's only 1mb...

should I sell my soul and turn #orogene into a startup that starts upselling services and inevitably crashes and burns?

A VC approached me recently about turning #orogene into a startup and hoooly shit I'm glad I got inoculated against that shit because I'm staying tf away from VC money lol

In the interest of getting this moving, could y’all please check out and vote on whatever you like better for an #orogene logo?

And if you have an idea you want to post, feel free to add it!

How would you feel about fully anonymous, no-trickery opt-in, short-lived, openly-viewable telemetry for #orogene? Would the very presence of that code taint it for you?

It would definitely be super useful to track down errors and understand perf.

Oh hey. I managed to get orogene down to an under 4mb executable. That's pretty nice, I think?

That's smaller than Yarn, and about 1/3 the size of PNPM. And you don't even need to install an external runtime, since everything is statically compiled. (the Node.js binary alone is 87mb)


I really really hate peerDependencies and I feel like my deep-seated hatred is maybe a little incongruent with how bad they are.

They're there to solve a problem, but they feel like the wrong solution. I'd rather not support them, but they're also a reality of the ecosystem, so I'm kinda at a loss as to what I should actually do.

What do you prefer to see happen with peerDependencies?


oh and one more goody: all #orogene error codes are now documented, and will even render a link to the more detailed docs, which are all hosted on itself!

On terminals that support link rendering, the error code itself will be a link, and the long URL shown here won't even show up!

❯ cargo run -- rm ./lodash
    Finished dev [unoptimized + debuginfo] target(s) in 0.41s
     Running `C:\Users\micro\src\orogene\target\debug\oro.exe rm ./lodash`
 WARN A debug log was written to ./oro-cache\_logs\oro-debug-2023-04-18-00-14-16.912-0.log
Error: oro::remove::invalid_package_name (

  × ./lodash is not a valid package name. Only package names should be passed to `oro remove`, but you passed either a non-NPM package specifier
  │ or an invalid package name.
  help: Use the package name as it appears in your package.json instead.

New release of #orogene is ready!

This one has a LOT of goodies: oro add, oro rm, and oro reapply are now all there, along with a --locked flag for preventing lockfile modifications if that's your style.

Also fixed a pretty annoying resolver bug that I thought would force me to rewrite the resolver, but a relatively small fix got it working! Hopefully it fully solved the problem idk.

Oh and uhh... you can install orogene through NPM now! Even with npx! Give it a shot with npx oro ping (or npx orogene ping. Both packages are fine).

output of `npx oro ping` showing orogene installed through NPM, pinging the registry.

Can I get some feedback? What do y'all think of this message? This happens when you're doing oro apply when in --locked mode, but dependencies have somehow changed (due to additions/removals). This doesn't/shouldn't happen if you have a lockfile and your package.json is unmodified.


INFO 🔍 Resolved lodash@3 to lodash@^3.10.1.
 INFO 📝 Updated package.json with 1 new dependency.
ERROR A debug log was written to ./oro-cache\_logs\oro-debug-2023-04-17-18-43-55.602-0.log
Error: node_maintainer::lockfile_mismatch

  × Locked mode was requested, but newly-resolved dependencies differ from current lockfile.
  help: Did you modify package.json by hand?

I also spent some time documenting how the overall node_modules/ workflow works for #orogene, which I'd love feedback on, if anyone wants to check it out:

This describes the process of building and managing node_modules/, along with various knobs for adjusting the behavior that orogene exposes (or will expose).

I'm pretty happy with it, overall! It's a little different, but I think much better for UX/DX.

Updated #orogene's #oranda-based site a bit, now with a whole page of benchmarks!

Don't mind me, just enjoying how fast and memory-light everything is.

.oO(I want to get a logo for #orogene)

idk. maybe I'll commission someone for it?

I think it could use a logo by now!

I'm seriously considering splitting oro add and oro apply into two very different operations in #orogene

oro add would ONLY add your dependency to package.json and write your package-lock.kdl with your new desired tree.
oro apply would then have to be executed to make sure node_modules/ has everything written into it.

I'm not sure I like the idea of oro add just being a second installer command...

Based on the above, whose terminology do you like best? #orogene

Trying to figure out what to call workspace stuff in #orogene led me down an annoying rabbit hole where I learned that basically no one uses the same terminology for workspaces and its elements and it's ridiculous.

Annoyingly, there's a lot of inconsistencies as to what's called "workspaces", and what the host project is called:

    Cargo refers to the host project as a workspace, and its children as members, but they're referred to on the CLI with the -p/--package flag.
    PNPM has a pnpm-workspace.yaml file with a packages: field, and uses -r/--recursive to run certain commands across all workspace packages. It uses the -w/--workspace flag to refer to the host/root project.
    NPM uses a "workspaces": {...} field and seems to refer to the host project as a "root project" or "project root". The -w/--workspace flag, as opposed to in NPM, refers to the individual packages, not the root project.
    Yarn also uses a "workspaces": {...} field, which is probably the source of NPM's naming, but refers to the host project as a "worktree". It does not seem to have any configuration for either recursive execution (like PNPM) or package targeting (like Cargo or NPM).

So basically everyone is horrible and there's no right answer.

Just tagged #orogene v0.3.19, with the shiny new by-default isolated/pnpm-style linker! It also renames "restore" (nee "install") to "apply", after the conversations on here.

Check it out!

Got pnpm-style symlinked/isolated node_modules working in #orogene! :)

You can switch back to the "classic" hoisted linker by using the --hoisted flag.

the results of an `ls -l node_modules/` command. It shows some @-prefixed directories, followed by many symlinks which point into specific directories inside `.oro-store`

One last round! #orogene

#orogene's "single command that prunes extraneous packages, extracts missing packages, and links all the .bin files" should be called...

In other news, I have an important design goal with #orogene and how it "installs" stuff:

There's no "oro install" command! Orogene calls the operation "restore".

Why? Because there should be exactly one way to build out your node_modules/, and that way should always be idempotent, and I take that idempotency very very seriously.

That means a few things:

You have to use a separate command to add/remove dependencies.
Install scripts will only be run once for any given "extraction"
If you change any relevant flags/configs, the tree will be rebuilt as far as needed (for example, if you change your configured registry, we'll reinstall anything that doesn't match the original package hash)
package.json is the "source of truth" as far as compatibility goes, and if you update package.json, the lockfile (and node_modules), will be updated to match it, as needed.

I'm sure there's other stuff I can do on this front, but that's what I've come up with so far. My Big Plan is to make orogene so idempotent, and so fast, that you can even attach it to a git hook for branch switches and it'll just keep your node_modules in sync almost magically (if you're into that sort of thing).

👀 you know, I thought it would be a massive pain that would involve rewriting the resolver to do, but I'm pretty sure #orogene can do a pnpm-style symlink+hard link install/restore without much more effort? I think I'm gonna prototype it and see what it looks like...

Got array and nested configs working both through CLI and in he oro.kdl config file! These are equivalent and will be processed the same way, with different priorities (CLI takes priority over config files) #orogene

The #kdl is kind of automagically reinterpreted into an object/array/literal-style data structure (as opposed to nodes), and it works great.

options {
    cache "./oro-cache"
    scoped-registries {
        @foo ""
        @npmcli ""
oro view --cache ./oro-cache --scoped-registry @foo= --scoped-registry @npmcli=

If anyone wants an easy contribution to #orogene, I just put up this issue, for adding proxy/NO_PROXY support to the http client:

New #orogene prerelease is out! This one includes a pretty big overhaul of how configuration works, including support for —no- for negation, and config files are now #kdl based!

haha oh god that was a lot of work, but I finally got two really nice things working for #orogene, using clap:

--no-<option> negations for all defined options, including setting Option<T> to None, so it works on more than just bools
Automatic fallback to config file(s) when an option isn't specified in the CLI args, BUT, falling back to defaults defined in clap if the option is not present in the config file either.

That was... hard.

Just tagged v0.3.15 of the #orogene early pre-release, which now includes node_modules/.bin linking and lifecycle script execution (modulo node-g*p, which I don't intend to support directly).

You can give it a whirl if you want! You can pick up a copy over here:

orogene restore running two lifecycle scripts in parallel, printing out incrementing message lines along witḣ activity spinners

finally got this working! stdout/stderr printing in progress bar for concurrent lifecycle scripts. :)

Anyway that's basically the last of it to get lifecycle scripts working reasonably well!

What do you think? Does it look good?


orogene output showing it running lifecycle scripts and printing the latest line as they execute concurrently.

I want to get off Mr Bone's Shell Escaping Wild Ride now, thanks.

Seriously, it's been a couple of days and I can't seem to get this right. I think it's about time I move to the mountains and become a hermit.


every time I think I'm done with getting lifecycle/run-scripts working on #orogene, I uncover yet another level of magic/preprocessing/escaping that I either didn't know about, or had completely forgotten about (or has gotten fancier since I last looked).

So many layers D:

Just released #orogene 0.3.11, which is fairly small. Mostly just emoji-related fixes, and a lot of docs (which are now available at

Grab it here!

Welp. These took a while to generate, but now I have a script that can (slowly) update them for me in the future. Sometimes you need to see the difference #orogene can make!

#rust #rustlang

Warm Cache Comparison

benchmarks between 5 different package managers, represented as a bar chart.

bun and orogene are practically slivers compared to the others, with orogene just slightly eking out bun, both with sub-secontd times, and NPM taking the longest by far, at roughly 22 seconds.
Resolution + Cold Cache Comparison

benchmarks between 5 different package managers, represented as a bar chart.

bun and orogene are noticeably lower than the others, with bun being roughly twice as fast as orogene (8 seconds vs 16 seconds), and Yarn taking way longer than anyone else, at over a minute.
Cold Cache Comparison

benchmarks between 5 different package managers, represented as a bar chart.

bun and orogene are noticeably lower than the others, with bun being roughly twice as fast as orogene (4 seconds vs 8 seconds), and Yarn taking way longer than anyone else, at just over 45 seconds.

Spent some time writing a nice for #orogene so it should be even easier to figure out how to contribute!

I also went ahead and added some memory usage benchmarks:

Package Manager 	no lockfile, no cache 	lockfile, cold cache 	lockfile, warm cache 	existing node_modules
orogene 	266.8 mb 	155.2 mb 	38.6 mb 	35.5 mb
bun 	2,708.7 mb 	792.1 mb 	34.5 mb 	25.8 mb
pnpm 	950.9 mb 	638.4 mb 	260.1 mb 	168.7 mb
npm 	1,048.9 mb 	448.2 mb 	833.7 mb 	121.7 mb
yarn 	751.1 mb 	334.4 mb 	251.9 mb 	129.3 mb
Wes Todd
3 months ago

@zkat Oh I don''t mean it from a purity point of view. I mean lik community building, ability for users to go one level deeper easily, dogfooding type things.

I have not followed your work on #orogene lately, but IIRC it is a package manager? When you give those times do you mean for the dev work or the program to run?

@zkat Fun to read about your progress on #orogene

Will it interop with package-lock.json?

htmlNaN + CSS-Infinity
7 months ago

@zkat Congratulations! And thanks for all the good work. Isn't #orogene the Project with the decentralized npm alternative?