The topic 5 package managers that work on Windows, Mac, and Linux is currently the subject of lively discussion — readers and analysts are keeping a close eye on developments.
This is taking place in a dynamic environment: companies’ decisions and competitors’ reactions can quickly change the picture.
There is a moment that every person who uses more than one computer eventually reaches. You sit down at a new machine, or a freshly wiped one, and you realize that the next few hours of your life will be spent visiting the same websites, clicking the same “Next” buttons, and resenting every installer that wants to add a toolbar to your browser. It does not have to go this way.
Package managers have been solving this problem on Linux for decades, but the assumption that they belong exclusively to that world has become outdated. Several package managers now work across Windows, macOS, and Linux, and the good ones let you describe what you want installed and then just get out of the way. “Cross-platform” is doing real work here, though. For some tools, that means native binaries on all three systems; for others, it means tapping into a full Linux environment on Windows via the Windows Subsystem for Linux (WSL). Let’s look at what “works on all three” actually means in practice.
Some software refuses to die, even when the distro that birthed it does.
For Mac users, whether you want to install software from the command line or manage graphical apps, Homebrew is still the default package manager I would point to first. Folks use it regularly for utilities, developer tools, and local test servers because it eliminates the usual installation friction found in macOS. It originally started as a way to patch the gaps Apple leaves in the native command line, but it has grown into a cross-platform giant.
On Linux, Homebrew shines because it installs packages in its own sandbox (/home/linuxbrew/) rather than modifying your core system files. This is ideal for developers who want isolated user-space package management without cluttering their main distribution paths. On macOS, it goes a step further with Homebrew Cask, which lets you spin up full graphical applications (like Google Chrome or VS Code) straight from the terminal alongside traditional command-line scripts.
The elephant in the room is Windows. Homebrew does not run natively on Windows. If you want to use it on a PC, you must execute it inside the Windows Subsystem for Linux (WSL). While that makes it a phenomenal tool for a developer moving seamlessly between macOS and a WSL terminal, it will not replace native Windows managers like Scoop or Microsoft’s built-in winget for host applications.

Nix has never struck me as a tool obsessed with convenience. It is obsessed with correctness, and that is what makes it so interesting. Instead of scattering files across global system folders, Nix stores every package in its own unique, immutable directory. Upgrades are atomic, and if something breaks, you can roll back instead of manually repairing your environment. That design pays off once you start thinking about environments as things you can describe rather than manually rebuild. You can declare your entire setup in a text file, commit it to GitHub, and reproduce it on another machine with a level of precision that most package managers do not even attempt.
Nix officially supports Linux and macOS. On Windows, you will need to set up modern WSL 2, which puts it in the same boat as Homebrew. It is very useful for terminal and development workflows, but it will not manage native Windows apps like the Windows Package Manager (winget) or Scoop.
The scale is also enormous. Nixpkgs contains more than 120,000 packages, making it one of the largest software repositories available. The hurdle is learning how Nix thinks. It does not lean on familiar YAML files or ordinary shell scripts; it uses its own declarative language. Nix Flakes make the experience more manageable by adding reproducible environments with lockfiles, and they have become the community’s preferred approach.
The oddity is that Flakes are now the community standard while still carrying an official “experimental” label upstream, which can make the documentation inconsistent in places. I would not let that scare me off, though, if reproducibility is what you are after.
Conda works as both a package manager and an environment manager, and it runs natively across Windows, macOS, and Linux. Although it is closely associated with Python and data science, it is not limited to Python packages. Conda can also manage non-Python software, which makes it quite useful for scientific and technical workflows that depend on external C libraries, Fortran components, native drivers, or other compiled dependencies. You can build isolated environments that bundle these complex dependencies together using a simple conda create command.
If you install the full Anaconda distribution on your machine, you get a massive, comprehensive suite of scientific software preconfigured out of the box. Unlike language-specific tools, Conda natively supports compiled binaries across all three major operating systems, making it an incredibly reliable solution for cross-platform workflows. The major trade-off is runtime performance; standard Conda can be notoriously slow to resolve complex dependency graphs during installations.

There is also a licensing wrinkle worth knowing before you install anything. Anaconda requires paid licensing for some commercial use cases, so the cleaner free route today is Miniforge. It sets up Conda with the community-run conda-forge channel by default, giving you access to a massive ecosystem that now spans more than 28,500 feedstocks and over 33,000 individual packages.
If you write contemporary JavaScript, npm is almost impossible to avoid. As the default package manager for Node.js, it fetches open-source libraries and manages project dependencies by tracking them inside a local package.json file.
Beyond code libraries, npm is exceptionally handy for running command-line tools. It runs entirely natively across Windows, macOS, and Linux. Because Node.js abstracts the operating system, npm packages generally run cross-platform without modification, though packages with native C++ bindings will automatically compile locally using your system’s build tools upon installation.
In the past, developers often used npm install -g to install command-line utilities globally. However, modern workflows lean heavily on npx, which lets you run tools on demand without permanently adding them to your system path.
The main drawback here is the infamous dependency sprawl. Even a modest project can drag in a startling number of dependencies, and node_modules has a way of becoming its own little metropolis of nested files. That creates real maintenance pressure, especially around security, because your app may depend on far more code than you personally chose. Npm helps with its built-in audit tool, which flags known vulnerabilities and suggests fixes, but the broader reality remains that ease in the JavaScript world often comes with a very crowded dependency tree.
Python developers rely on pip to fetch and manage third-party libraries from the massive Python Package Index (PyPI). Unlike Conda, pip does not manage standalone software binaries or hardware drivers; it is strictly a language-specific package installer. It runs entirely natively on Windows, macOS, and Linux. However, using pip globally can easily break system-level utilities, which is why learning how to effectively create and manage your Python virtual environments is an absolute necessity.
In fact, modern Linux distributions heavily enforce this via PEP 668, locking down the system Python environment and throwing a hard error if you try to run a global installation. On Windows, pip defaults to standard, unprivileged directories inside your local user profile (AppData) to sidestep admin-level permission blockages.
Because Python code abstracts hardware, pip packages are highly portable, though specific modules with compiled extensions will require a local compiler to build during setup. If you want a taste of where this ecosystem is going, look at uv — a blazing-fast, Rust-based pip alternative that handles virtual environments and installations up to 100 times faster than traditional Python setups.
There is no single winner here because the tools are not competing for the same job. The most important thing to accept before you commit to any of these is that “works on all three platforms” rarely means identical experiences across all three. It usually means the same core concept, with footnotes about Windows. Reading those footnotes before you adopt a tool is half the job. The other half is just running the installation command.