This is episode ten of What Did I Just Install.
You type two words. pip install. And in the time it takes to draw a breath, code written by a stranger in another country is downloading, unpacking, and executing on your machine. You did not read it. You do not know who wrote it. You have no idea what it does beyond what the name on the box suggests. And you do this dozens of times a week without a second thought.
Every episode in this series has begun the same way. Someone typed an install command, and a package appeared. left-pad. requests. Express. Pillow. curl. SQLite. Svelte. ffmpeg. Redis. Nine stories about the people behind the packages, nine stories about what happens when a single maintainer burns out or a corporation changes the license or a stranger slips malware into the dependency tree. But we have never stopped to ask the more fundamental question. Who invented the install command? How did "download and run a stranger's code" become the default behavior of every programmer on earth? And what happens when the trust that holds the whole system together turns out to be a three-year lie?
This is the story of how package management was invented, how it spread from language to language, who pays for the infrastructure nobody thinks about, and why the most sophisticated cyberattack ever discovered targeted not a bank or a government, but a single exhausted open source maintainer of a compression library.
Before there were package managers, there was pain.
In the late nineteen eighties, if you wanted to share a piece of software with the world, you posted it to Usenet. Specifically, you posted it to a newsgroup called comp.sources.unix, moderated by a developer named Rich Salz, where contributors submitted source code that was then distributed across the global network of Usenet servers. Larry Wall distributed Perl itself this way, as shar files, short for shell archives, a format designed so that people on dialup modems could download the pieces one at a time without having to start over if the phone disconnected. You would reassemble the pieces into a tar archive, extract it, read the README, hope you had the right compiler, and try to build it.
If the software lived on an FTP server instead of Usenet, the process was only slightly better. You had to know which server carried it. There was no search engine for FTP sites. The big archives, sunsite.unc.edu in North Carolina, ftp.funet.fi in Finland, ftp.demon.co.uk in London, each had their own curator maintaining their own collection with their own directory structure. Finding a Perl module in nineteen ninety-three meant hearing about it on a mailing list, guessing which FTP site might carry it, navigating an unfamiliar directory tree, downloading a tarball, extracting it, running perl Makefile.PL, then make, then make test, then make install. And if that module depended on three other modules, you did the whole dance three more times. There was no dependency resolution. There was no way to search. There was no undo.
This was the world that programmers accepted as normal. Code sharing meant manual labor, tribal knowledge, and a tolerance for frustration that would seem alien to anyone who has grown up with npm install. And it might have stayed that way, except that a Finnish sysadmin got tired of organizing FTP mirrors.
On December second, nineteen ninety-three, a developer named Bill Middleton created a mailing list called perl-packrats. The members were the people who maintained the scattered FTP sites that hosted Perl code around the world. There were seven of them. Bill Middleton, Tom Christiansen, Henk Penning, Stephen Potter, Lee McLoughlin, Mark Coombs, and a Finnish research engineer named Jarkko Hietaniemi.
Hietaniemi worked at Nokia Research Center in Finland, but his relevant credential was that he managed the Unix infrastructure at the Finnish University and Research Network, known as FUNET, in Espoo. He had access to ftp.funet.fi, one of the biggest FTP mirrors in Europe, and he had already been using it to mirror Perl modules from sites around the world. He had heard about "some new language called Perl" while herding Unix servers, taught himself the language, and started collecting its scattered modules the way a librarian collects books from yard sales.
Four days after the mailing list was created, a member named Jared Rhine proposed something radical. Instead of each packrat maintaining their own ad hoc collection, why not create a unified archive with a standard directory structure? He had a model in mind. The TeX community had built something called CTAN, the Comprehensive TeX Archive Network, in nineteen ninety-two. Rhine proposed doing the same for Perl. On December tenth, nineteen ninety-three, he submitted a detailed proposal and introduced the name for the first time. CPAN. The Comprehensive Perl Archive Network.
Then nothing happened. For more than a year, the packrats discussed directory structures, naming conventions, and who would actually do the work. Nobody did it. Progress stalled in the way that open source projects often stall, where everyone agrees something should exist but nobody has the time to build it. Until February twelfth, nineteen ninety-five, when Jarkko Hietaniemi sent a message to the mailing list that would change the history of software.
Let's do this CPAN thing.
He proposed a directory structure. He said he was going to get on with it. And he did. Over the following months, Hietaniemi assembled the scattered collections from a dozen FTP sites into a single coherent archive on funet.fi. Meanwhile, a German developer named Andreas König was building the other half of the puzzle. On August fifteenth, König announced he was building an upload server where Perl authors could register an account and submit their modules directly. The next day, August sixteenth, nineteen ninety-five, König uploaded the first module to the new system, a distribution called Symdump. He also coined the name for the upload server. PAUSE, the Perl Authors Upload Server, with a nod to the idea that every author deserves some break.
Each author has deserved some pause.
On October twenty-sixth, nineteen ninety-five, Hietaniemi publicly announced CPAN to the Usenet group comp.lang.perl.announce. The Comprehensive Perl Archive Network was live. It had a master server in Finland, a mirror network that would eventually grow to over two hundred and fifty sites in sixty countries, a searchable index, and an installer, CPAN.pm, that let users type a command and have a module download, build, and install automatically. For the first time in the history of open source software, you could type a single command and get someone else's code on your machine without knowing which FTP site carried it, without manually resolving dependencies, without reading a README file to figure out the build process. CPAN was the first package registry. Every system that followed, RubyGems, PyPI, npm, Maven, NuGet, Cargo, Hex, Hackage, would trace its lineage back to what a Finnish sysadmin and a German hacker built in nineteen ninety-five.
The two of them met in person for the first time at O'Reilly's first Perl Conference in August nineteen ninety-seven. They had been building CPAN together for two years as strangers on a mailing list. By then, CPAN had six hundred ninety-four registered authors and thousands of modules. The White Camel Award committee would later write that most Perl programmers cite CPAN as one of the best features of Perl. It was not just a feature. It was the invention of a pattern that would reshape how all software is built.
Eight years later and five thousand miles south, the idea landed in a hotel bar in Texas. It was November two thousand three, RubyConf in Austin, and a group of Ruby developers were having the same conversation that every language community eventually has. Where is our CPAN?
Ruby's creator, Yukihiro Matsumoto, known universally as Matz, was in the room. David Alan Black, one of the organizers, put him on the spot about package management. Matz's response was characteristically direct.
If you build it, it will be included in Ruby core.
That was all the permission they needed. That night, five developers started coding what would become RubyGems. Jim Weirich, Rich Kilmer, David Black, Paul Brannan, and Chad Fowler. Fowler was the unlikely one. He had gone to school for music, played professional saxophone, and stumbled into programming through a side door. He would later found a record label dedicated to avant-garde jazz and free improvisation. But that night in Austin, the saxophonist was writing a package manager.
They released RubyGems on March fourteenth, two thousand four. Pi Day. It followed the CPAN model closely, a central registry where authors could upload and users could search and install, but adapted for Ruby's conventions and culture. It grew quickly. Nick Quaranto later built Gemcutter, a cleaner Rails-based hosting system that eventually became the official rubygems.org. The tool that Matz had challenged a room to build became, like CPAN before it, the thing people cited when asked why they used the language.
But the story of RubyGems has a shadow. Jim Weirich, the co-creator who also invented Rake, Ruby's build tool, died on February nineteenth, two thousand fourteen. He was fifty-eight. When the news spread, hundreds of developers left tributes as comments on his final GitHub commit, on a project called Wyriki. GitHub added a special memorial banner to the page. It became one of the most remarkable memorials the programming community has ever produced, a grief response channeled through the only medium these people shared, a version control system. The man who helped build the package manager was mourned through the tools he had helped make possible.
There was one problem that CPAN and RubyGems and every early package manager failed to solve. They could install code, but they could not guarantee that two different machines would get the same code. You ran gem install on your laptop and got version two point three. Your colleague ran the same command a week later and got version two point four. Your production server, deployed on a Friday, got version two point five. Each machine had a slightly different set of dependencies, and the bugs were ghosts, unreproducible, maddening, always someone else's problem.
The person who solved this is arguably the single most influential figure in the history of package management, and almost nobody outside the Ruby and Rust communities knows his name. Yehuda Katz was working on a web framework called Merb in two thousand eight when the dependency problem nearly broke him. Merb was composed of many interdependent gems, and keeping them all at compatible versions across development, testing, and production was a nightmare. He and his collaborator Carl Lerche built a tool called Bundler with a deceptively simple innovation. A lock file.
The idea was this. You declare the gems you want in a Gemfile. You run bundle install. Bundler resolves all the dependencies, picks compatible versions, downloads them, and then writes the exact result to a file called Gemfile.lock. From that moment forward, every machine that runs bundle install with that lock file gets exactly the same versions. Not similar versions. Not compatible versions. The same versions, down to the patch number. The lock file is a snapshot of a working dependency tree, and it travels with the code.
A lock file that could then be used to repeatably install the exact same gems on another machine at a later time.
Bundler one point zero shipped in August two thousand ten. Andre Arko joined as lead maintainer and stewarded the project for years. The lock file concept was not entirely new, CPAN had rudimentary pinning, but Bundler made it central to the workflow. It was the conceptual leap that every subsequent package manager would adopt. npm's package-lock.json. Yarn's yarn.lock. Go's go.sum. And most directly, Cargo's Cargo.lock.
Because Yehuda Katz did it again. In two thousand fourteen, he joined the Rust core team and, with the same Carl Lerche, designed Cargo, Rust's package manager and build system. They carried every lesson from Bundler into a language that was being designed from scratch, which meant they could avoid every mistake that bolt-on package managers had made. Cargo shipped with Rust from day one. It was not an afterthought bolted on years later, like pip for Python or npm for Node. It was part of the language. And it is widely considered the gold standard of package management, the thing that other ecosystems point to and say, that is what we should have built.
The Rust blog post announcing Cargo explicitly positioned it as following the tradition of successes like Bundler and npm. The same humans, solving the same problem, in the same order, for the third time. Katz is the thread that connects Ruby to Rust to JavaScript. His company, Tilde, even collaborated on Yarn with Facebook and Google. One person carrying the lessons from one ecosystem to the next, like a suitcase full of lockfiles.
Every language community that watched CPAN succeed had the same thought. We need one of those. For Python, the thought arrived in the late nineteen nineties, and the execution took approximately two decades of false starts, religious wars, and tools that were replaced by other tools that were replaced by other tools that were replaced by the tool you are probably using right now, which will itself be replaced within five years.
It started with a man in a brain imaging lab. In nineteen ninety-eight, Greg Ward was a research assistant and systems analyst at the McConnell Brain Imaging Centre at the Montreal Neurological Institute at McGill University, simultaneously working toward a master's degree in computer science. He scheduled a session at the seventh International Python Conference called "Building Extensions Considered Painful," and at that session, the Python community agreed on the basic shape of a distribution system. They called it distutils, for Distribution Utilities, decided on the command python setup.py, and agreed not to use Make because it would not work on Windows. Ward built distutils, and it was added to the Python standard library in Python one point six in the year two thousand.
But distutils was a build and install tool, not a registry. Python still had no place to find packages. The closest thing was the Vaults of Parnassus, a glorified link directory with the aesthetic of GeoCities, where package authors manually submitted links to their software hosted on personal websites and university FTP servers. It was, by all accounts, barely functional.
In two thousand two, an Australian developer and Python core contributor named Richard Jones authored PEP three oh one, proposing a central package index hosted at python.org. It launched in two thousand three under the name that Jones could not resist. The Cheese Shop, after the Monty Python sketch in which John Cleese enters a shop looking for cheese and is told, for every variety he names, that they do not have it. Have you in fact got any cheese here at all? Yes sir, says the shopkeeper. Then corrects himself. No. The parallel to Python's package situation, an index that claimed to be a repository but had nothing you could reliably install, was not lost on anyone. The community later renamed it to the Python Package Index, PyPI for short, though "Cheese Shop" persists in the folklore.
What followed was the most chaotic period in the history of any language's packaging ecosystem. In two thousand four, Phillip Eby created setuptools and easy-install, the first automated installer that could download and install packages from PyPI. It was revolutionary and controversial in equal measure. Setuptools introduced the egg format, a binary distribution that placed each library in its own folder and extended Python's module search path with dot-pth files until it became impossibly long. It enraged developers. Easy-install could install packages but could not uninstall them. And development was centralized around Eby personally, making it difficult for others to contribute.
In two thousand eight, Ian Bicking entered the picture. Bicking was already known for creating virtualenv, the tool that lets Python developers create isolated environments. On September twenty-third, he published a blog post titled "pyinstall: A New Hope," introducing a new installer. A month later, he renamed it. pip. A recursive acronym. pip installs packages.
pyinstall is dead, long live pip.
pip fixed the things that drove people mad about easy-install. It could uninstall packages. It supported requirements files for reproducible environments. It installed packages as flat directories you could actually inspect, not opaque eggs. It worked beautifully with Bicking's own virtualenv. And in two thousand fourteen, pip was bundled with Python three point four, making it the default installer for all new Python installations.
That same year, Bicking published a blog post titled "Saying Goodbye to Python." He had moved to Mozilla Labs years earlier, shifted to JavaScript, and realized he was no longer part of the Python community. The man who had built the tool that every Python developer uses every day had quietly moved on. pip's maintenance passed to the Python Packaging Authority, and the tool kept growing without its creator.
The chaos did not end with pip. The packaging ecosystem continued to fracture. Setuptools was forked into distribute. Distribute merged back into setuptools. The egg format was replaced by the wheel format. PEP five seventeen and five eighteen decoupled the build system from the installer. Poetry arrived. Then Pipenv. Then Hatch. Then PDM. Then Flit. Each one a different developer's attempt to finally get Python packaging right. As of two thousand twenty-five, the build system market share on PyPI is split between five competing tools, with setuptools still dominating the long tail through sheer inertia. No other language ecosystem has gone through this many iterations of the same problem. Python's packaging story is the exception that proves the rule, the ecosystem where the install command was never quite right, where every solution became someone else's problem to solve again.
Meanwhile, the Cheese Shop itself needed saving. Donald Stufft, who had spent years as the primary maintainer of both pip and PyPI, led a complete rewrite of the PyPI infrastructure called Warehouse, funded by a hundred and seventy thousand dollar grant from the Mozilla Open Source Support program. The new PyPI launched on April sixteenth, two thousand eighteen, replacing a codebase that had been held together with tape and goodwill since two thousand three. Nicole Harris redesigned the entire visual identity. Ee Durbin took over as Director of Infrastructure. For the first time in its history, the Python Package Index looked and behaved like a modern web application.
While Python was fighting itself over packaging, JavaScript was fighting a different war. We covered npm's origin in the left-pad episode, Isaac Schlueter building it in two thousand ten after watching packaging done both terribly and brilliantly in other ecosystems. But npm's story did not end at its creation. It was the beginning of the most turbulent decade in package management history.
The first problem was structural. Early npm used nested dependencies, where each package maintained its own node-modules folder containing its own dependencies, which had their own node-modules folders, recursively. Dependency trees could nest dozens of levels deep. On Windows, file paths exceeded the two hundred sixty character limit, making it impossible to even delete the node-modules directory with the file explorer. In two thousand fifteen, Rebecca Turner, npm's CLI programmer, spent eight months on a near-complete rewrite of the installer. npm three installed dependencies maximally flat, hoisting shared packages to the top level and only nesting when versions conflicted. It fixed the Windows problem but introduced a new one. The flat tree was non-deterministic. Two machines running the same install command could end up with different directory structures depending on the order packages were resolved.
Facebook discovered this the hard way. Their engineers could run npm install on their laptops just fine, but sandboxed continuous integration environments, which needed to be offline, could not. They tried three solutions. First, just running npm install. Unreliable. Second, checking node-modules into version control. A minor Babel update generated an eight hundred thousand line commit. React Native's sixty-eight declared dependencies expanded to one hundred twenty-one thousand three hundred fifty-eight files. Merging node-modules changes consumed entire days of engineer time. Third, zipping node-modules and uploading it to an internal CDN. This required constant internet and npm's shrinkwrap files produced unsorted JSON that needed custom sorting scripts.
The person who fixed it was a twenty-one-year-old in Facebook's London office. Sebastian McKenzie had already done something remarkable. In September two thousand fourteen, as a seventeen-year-old student at Wodonga Senior Secondary College in rural Australia, he had created Babel, the JavaScript transpiler that let developers use tomorrow's language features today. He renamed it from its original name, six-to-five, and it became one of the most critical tools in the JavaScript ecosystem. He moved to London, worked briefly at Cloudflare, then joined Facebook.
On January twenty-third, two thousand sixteen, McKenzie started building Yarn. The project became a collaboration with engineers at Exponent, Google, and Tilde, Yehuda Katz's company, because of course Katz was involved. Yarn launched publicly on October eleventh, two thousand sixteen, with three promises. Deterministic installs through a lockfile. Offline capability through a global cache. And speed. It was the lock file, the same innovation Katz had brought to Ruby with Bundler six years earlier, that finally hit the JavaScript ecosystem.
npm responded in two thousand seventeen with package-lock.json in version five, adopting the pattern Yarn had proven essential. But the JavaScript package manager wars were far from over. A developer named Zoltan Kochan, frustrated by thirty-minute install times and dozens of gigabytes consumed by node-modules in monorepos, created pnpm in two thousand sixteen. pnpm's innovation was content-addressable storage. Every package version is stored exactly once in a global store, and projects access it through hard links. If you have a hundred projects using the same dependency, npm stores a hundred copies. pnpm stores one. Typical disk savings are fifty to seventy percent.
Then came Bun, the strangest entry yet. Jarred Sumner, a self-taught developer who had dropped out of high school at sixteen to become the first employee at a smart lock startup, a Thiel Fellow, a Stripe engineer, built an entirely new JavaScript runtime in Zig, a language most JavaScript developers have never heard of, that happened to include a package manager so fast it made the others look broken. Bun was not just a package manager. It was a statement that the entire Node.js toolchain, runtime, bundler, transpiler, test runner, package manager, could be rebuilt from scratch and be faster at everything.
The JavaScript ecosystem now has four actively maintained package managers for the same language, five if you count Deno's built-in system. The node-modules meme endures. Sun. Neutron star. Black hole. node-modules. It is funny because it is true. It is also funny because every one of those package managers exists because the previous one did not solve the problem well enough, which is exactly what happened in Python, which is what happened in Ruby, which is what happened in Perl. The pattern repeats. The install command keeps getting reinvented. The dependency trees keep getting deeper.
Here is a number that should make you uncomfortable. Fastly, the content delivery network, donates a one hundred percent discount on PyPI's CDN bill. That bill would be more than one point eight million dollars per month. Every month. Google covers PyPI's cloud computing costs, approximately ten thousand dollars per month. AWS contributes another seven thousand in promotional credits. The total infrastructure cost of keeping the Python Package Index running exceeds one point eight million dollars per month, and almost all of it is donated.
PyPI serves more than sixty-six petabytes of traffic per month. That is sixty-six million gigabytes. Nearly two billion requests per day at peak. Three hundred billion downloads per year. And the entire operation is run by essentially two paid staff members at the Python Software Foundation, with the rest handled by volunteers and donated services. When the PSF published its two thousand twenty-four annual report, it showed negative net income of one point four million dollars. The organization that runs the store where every Python developer shops is losing money.
npm's infrastructure is no smaller. The registry serves around one hundred twenty-five billion requests at six petabytes per month. It was described by its own maintainers as a tremendous cost center where moving data around is not cheap. The single largest expense was reportedly the raft of required lawyers. npm, Inc. raised almost nineteen million dollars in venture capital before being acquired by GitHub, which is owned by Microsoft, which means the world's largest JavaScript package registry is now a line item on a hundred-billion-dollar corporation's balance sheet.
Ruby Central, the organization that runs rubygems.org, estimates its total operations at around five hundred thousand dollars per month, most of it underwritten by Shopify and the German Sovereign Tech Fund. Crates.io for Rust is owned by the Rust Foundation, with file hosting donated by AWS and CDN services by Fastly.
The pattern is the same everywhere. Package registries are critical infrastructure used by millions of developers and billions of devices, funded by a patchwork of corporate donations, foundation budgets, and volunteer labor. If Fastly decided tomorrow that its PyPI sponsorship was no longer a business priority, the Python ecosystem would face a one-point-eight-million-dollar monthly bill with no way to pay it. When npm, Inc. was running out of cash in two thousand nineteen, the JavaScript registry that half the internet depends on was months from potential shutdown. The store that everyone shops at is the store that nobody pays for, and the reason it still works is that a handful of companies have decided, for now, that keeping it running is worth the tax write-off.
In nineteen eighty-four, Ken Thompson, the co-creator of Unix and the C programming language, gave his Turing Award lecture at the Association for Computing Machinery's annual conference. He demonstrated something unsettling. He showed that a compiler could be modified to insert a backdoor into the Unix login command, and that the modification could propagate itself into future compilers, leaving no trace in the source code. His concluding line was a warning that the world would spend the next forty years failing to heed.
You can't trust code that you did not totally create yourself.
Forty years later, in a university town in Finland, a developer named Lasse Collin maintained a compression library called xz Utils. It was the kind of software that nobody thinks about and everybody uses. xz compression is built into the Linux kernel, into systemd, into the package managers of every major Linux distribution. Collin maintained it alone, in his spare time, as an unpaid hobby project. By two thousand twenty-two, he was struggling.
On June eighth, two thousand twenty-two, Collin posted a message to the xz-devel mailing list that would later be recognized as the moment the attack surface opened.
I haven't lost interest but my ability to care has been fairly limited mostly due to longterm mental health issues but also due to some other things. It's also good to keep in mind that this is an unpaid hobby project.
Starting in April two thousand twenty-two, sockpuppet accounts began pressuring Collin to add a co-maintainer. The messages were calibrated to exploit his disclosed vulnerability.
Over one month and no closer to being merged. Not a surprise. Progress will not happen until there is new maintainer. Submitting patches here has no purpose these days. It is important to be aware of your own limits. Why not pass on maintainership?
The accounts had names. Jigar Kumar. Dennis Ens. They were not real people. They were part of a social engineering campaign that had been running since at least February two thousand twenty-two, when another account, JiaT75, had started making legitimate contributions to xz Utils. Small fixes. Documentation improvements. Test files. The kind of work that builds trust gradually, one commit at a time.
By October two thousand twenty-two, Jia Tan had been added to the xz Utils GitHub organization. By December, full commit access. By March two thousand twenty-three, Jia Tan was releasing versions as lead maintainer. The patient infiltration had taken a year. The payload would take one more.
On February twenty-third, two thousand twenty-four, the backdoor was committed. It was hidden in test binary files, cut into pieces with junk data filling the gaps, present only in the packaged tarball and invisible in the source repository. The malicious code gave an attacker with a specific cryptographic key remote code execution through OpenSSH. The vulnerability received a CVE score of ten point zero. The maximum. It was the most sophisticated supply chain attack ever discovered, targeting not a bank or a government but a compression library maintained by one exhausted volunteer, and it nearly made it into every major Linux distribution on the planet.
The person who caught it was not a security researcher. Andres Freund, a Microsoft employee and PostgreSQL developer, was doing micro-benchmarking when he noticed that SSH logins were consuming an unexpected five hundred milliseconds of CPU time. Half a second. He profiled the SSH daemon and found CPU time being consumed in liblzma, the xz compression library, that could not be attributed to any known code path. He connected this to odd automated test failures he had noticed weeks earlier. On March twenty-ninth, two thousand twenty-four, he reported his findings.
It really required a lot of coincidences.
Half a second of unexplained latency, noticed by a developer who happened to be running the right benchmarks at the right time, stopped a three-year attack on the global software supply chain. If the backdoor had made it into stable releases of Debian, Ubuntu, Fedora, and Red Hat, it would have given the attacker access to most of the servers on the internet.
The entire system of package management, the invention that began with a Finnish sysadmin organizing FTP sites and grew into a global network of registries serving billions of downloads per day, rests on a foundation of trust. Trust that the person uploading the code is who they say they are. Trust that the maintainer is maintaining in good faith. Trust that the compression library your operating system depends on has not been compromised by a phantom who spent three years earning the right to commit code. Ken Thompson was right in nineteen eighty-four. You can't trust code that you did not totally create yourself. But the entire modern software ecosystem is built on exactly that trust, because the alternative, writing everything yourself, is not an option. Package management made software development possible at scale. It also created the largest attack surface in the history of computing.
There is a joke in the programming world that the answer to every performance problem is to rewrite it in Rust. In two thousand twenty-four, the joke came for package management.
Charlie Marsh studied computer science at Princeton, interned at Khan Academy, and worked as an engineer at a drug discovery company. In two thousand twenty-two, he created Ruff, a Python linter written in Rust, as a side project. It was orders of magnitude faster than existing tools. He founded a company called Astral, raised four million dollars in seed funding, and on February fifteenth, two thousand twenty-four, announced uv, a Python package installer and dependency resolver, also written in Rust. It was a drop-in replacement for pip. Astral's benchmarks showed it running eight to ten times faster than pip without caching and eighty to one hundred fifteen times faster with a warm cache.
The speed was real, but it was not just a Rust trick. uv benefited from infrastructure that had not existed when pip was built. PEP six fifty-eight, which went live on PyPI in May two thousand twenty-three, allowed installers to fetch package metadata without downloading entire packages, a critical prerequisite for fast dependency resolution. The ecosystem had finally laid the groundwork for a tool like uv to exist. Marsh and Astral built it, but they built it on two decades of incremental improvements to the Python packaging specifications.
The question that lingers around Astral is philosophical. Venture capital funding a package manager for a language whose entire ecosystem runs on volunteer labor and donated infrastructure. Astral raised four million dollars to make pip faster. The Python Software Foundation's total annual budget for running PyPI is roughly the same amount in donated services. What does it mean when the install command becomes a product?
It is not a new question. npm, Inc. was venture-funded too, and that ended with layoffs, executive turmoil, and an acquisition by Microsoft. But it is the question that will define the next era of package management. The Rust rewrite movement, uv for Python, Bun for JavaScript, is faster, undeniably. But it is also, for the first time, corporate from the start. CPAN was built by volunteers. PyPI was built by volunteers. npm started as one person's side project. The new tools are startups. The install command, invented by hobbyists, is becoming a business.
Thirty years ago, a Finnish sysadmin and a German developer organized some FTP sites and accidentally invented the install command. Today, pip install runs on every continent, including Antarctica. npm install runs on space station hardware. gem install, cargo add, brew install, apt-get install. The idea that Jarkko Hietaniemi set in motion when he typed "let's do this CPAN thing" on a mailing list in February nineteen ninety-five has become as fundamental to programming as the text editor or the compiler.
Every episode in this series exists because of that invention. left-pad was a crisis because npm made it possible to depend on eleven lines of code with no friction. requests became the most downloaded Python package because pip made installation invisible. ffmpeg powers this podcast because brew install put it on the machine that builds these episodes. The install command is the connective tissue of modern software, the two words that turn a name into running code, that turn a stranger's weekend project into your production dependency.
It is also, as we have seen, the two words that turn trust into vulnerability. The three-year infiltration of xz Utils was not a hack. It was a social engineering campaign that exploited the fact that package management depends on people, exhausted, underfunded, mentally struggling people, to maintain the code that the world runs on. Lasse Collin's disclosure of his mental health struggles was not a weakness. It was the honest reality of what it means to maintain critical infrastructure as an unpaid hobby. The attacker did not find a bug in the code. The attacker found a bug in the system, the assumption that trust, once earned through small commits and helpful patches, is permanent.
On your machine right now, pip's cache contains hundreds of packages. npm's node-modules directories hold thousands more. Homebrew has installed dozens of system tools. Each one was put there by the install command, the invention of trust, the two-word spell that summons a stranger's code onto your machine and hopes for the best. Jarkko Hietaniemi is a senior engineer at Apple now. Andreas König still maintains PAUSE. Jim Weirich's memorial lives on a GitHub commit page. Ian Bicking said goodbye to Python a decade ago. And every time you type pip install, you are standing on all of their shoulders, trusting that the system they built, and the strangers who contribute to it, will not let you down.
Most of the time, they don't.
Open a terminal and type pip list or npm list dash dash depth equals zero. That is every package installed in your current environment, every name you chose and every name that came along for the ride. Now pick one and look closer. Type pip show requests or npm info express. You will see the maintainer, the license, the homepage, and the list of dependencies. That is the trust chain this episode described. A name, a version, a person you have never met. Now try pip show pip itself. The tool that installs everything was installed by someone too. Jarkko Hietaniemi's invention goes all the way down.
That was episode ten.