I've got a new CLI tool half-written and no name for it. So before I got any further, I did the thing you're supposed to do: check if a good, short name is actually available before you build your identity around it.
I picked ten words. Short, real English words, the kind that sound like a project name without trying too hard: pulse, grid, flow, spark, nova, orbit, forge, relay, pilot, atlas. Then I checked each one against npm, PyPI and crates.io — the three registries my tool would plausibly need a name on eventually, even though it only ships to one today.
Ten words, three registries, thirty lookups.
All thirty came back taken.
Not just taken — abandoned
That was the annoying part but not the interesting part. The interesting part is what was sitting on those names.
pilot on npm is one version, published in 2011, described as "a small library used in the creation of Ace editor." atlas on npm has three published versions, and the description field is a literal unfilled template: <p> </p><p align="center">[Insert sweet logo here]</p> — somebody scaffolded a project, published it to reserve the name, and never came back to write the README. orbit and forge on crates.io each have exactly one version, 0.0.1 and 0.1.0. These aren't popular libraries I lost to. They're ten-plus-year-old ghosts, and the name is still gone.
npm's own policy is explicit that this isn't supposed to happen — publishing a package purely to reserve a name for later is against their terms of use. In practice, nobody's coming to clean it up. A dead package from 2011 and a maintained one from last month occupy the namespace identically as far as npm install is concerned.
The fix that actually worked
Frustrated, I tried the obvious next move: two-word names. Same ten words, paired up — novaforge, orbitpilot, relayflow, sparkatlas, gridpulse, forgeorbit, atlasnova, pulsegrid, pulseflow, novarelay.
Thirty checks again. This time, 26 of 30 came back free. Eight of the ten compound names are completely open on npm, PyPI and crates.io. Only two — pulsegrid and pulseflow — are taken, and only on npm and PyPI; both are still free on crates.io.
Going from "single common word" to "two common words mashed together" took the collision rate from 100% to about 13%. That's a bigger effect than I expected from such a small change, and it's the actual, practical takeaway if you're naming something today: stop trying for the one perfect word. It's very likely gone, on every registry, and has been since 2011-2014.
Where I'd push back on this
Ten words is an anecdote, not a survey. I picked words that sound like project names — short, punchy, vaguely techy — which is exactly the category most likely to be squatted, so my 100% collision rate is probably an upper bound, not a typical rate for "any random word." A dictionary-sampled word (teapot, xylophone) would likely fare a lot better.
I also can't tell you when most of these got squatted, only that it was a long time ago and nobody's released a second version since. That's suggestive of abandonment, not proof — a one-version package with zero updates in 14 years is still, technically, active in the sense that npm install returns it.
And this only checked existence, not health. Some of these old squats might still get downloaded occasionally by something that depends on them transitively, which package-availability tools generally won't tell you either.
Why this is worth checking before you build, not after
This isn't just a branding annoyance anymore. There's a live thread this year about attackers registering package names that AI coding assistants tend to hallucinate — so a coding agent that "remembers" a plausible-sounding package that never existed can get pointed straight at something someone else just claimed on purpose. Checking whether a name is real, and who holds it, isn't just about your own branding anymore.
I ended up running all thirty lookups by hand with curl, which is fine for one project name. For anything past a handful of candidates — or if you want it as one normalized shape instead of three different JSON schemas — that's exactly what Package Registry Scraper does: feed it a list of candidate names, get back version/license/repo/dates from npm, PyPI and crates.io in one consistent row per package, so a null result actually stands out.
Full endpoint reference — including the crates.io sparse-index trick, since crates.io's own search API isn't the fastest way to check a single exact name — is in the cheatsheet repo.
What's the oldest, most obviously-abandoned squatted package name you've ever run into — and did you fight for it, or just pick something else?

Top comments (0)