Pixi: Reproducible Package Management for Robotics

13 hours ago 1

TL;DR: Developing Robots is hard; Pixi makes it easier by creating reproducible, cross-platform ROS development environments without Docker or Ubuntu lock-in.

Watch this YouTube playlist for a quick understanding, or talk to us at ROSCon2025!

Before I joined Prefix.dev, I struggled to create reproducible developer setups for different ROS projects. Back then, using conda (or micromamba) together with RoboStack was a lifesaver. It finally made managing those complex environments bearable.

Now, at Prefix.dev, I get to work on an even better solution. Pixi takes that idea further with automated builds and easy package distribution, so teammates can jump right into the same workflow, making ROS development simple and reproducible.

More and more projects in the Robotics space are catching on, and started using Pixi:

  • ros2/ros2: Using Pixi for Windows builds

  • VSLAM-LAB: Using Pixi for multiple highly complex environments in one project.

  • rerun.io: Using Pixi for reproducible development and examples

  • FreeCAD: Using Pixi for cross-platform development

The Biggest Challenges I encountered while working with ROS

  • Ubuntu lock-in: The ROS build and release process is heavily tied to specific Ubuntu distributions. Developers on macOS or Windows are often left behind or forced to use workarounds.

  • Distribution coupling: Each ROS distribution (like ROS Noetic, Humble, or Jazzy) is tightly linked to a specific Ubuntu release, limiting OS flexibility.

  • Global installs: Most ROS dependencies are installed system-wide, making it difficult to maintain multiple ROS workspaces or versions on one machine.

  • Multi-distro maintenance: Working on multiple robots or projects targeting different ROS distributions is painful to manage.

  • Docker: Many teams resort to using Docker to isolate environments, but this adds build overhead, slows down workflows, and caching is layer based instead of per package.

Pixi is a modern package manager built on top of the Conda ecosystem. It brings fast, reproducible, and cross-platform environments to robotics development.

With Pixi I can:

  • Install ROS on Linux, macOS, and Windows — without needing Docker or Ubuntu.

  • Create isolated environments that contain the exact dependencies for the robot or simulation.

  • Maintain multiple ROS distributions side-by-side on one machine.

  • Share environments easily using a simple pixi.toml file, ensuring your teammates or CI pipelines use the exact same setup.

In short, Pixi makes ROS development reproducible, portable, and accessible.

Aspect

Pixi-based

APT-based

Cross-platform

Reproducibility

Multiple ROS distros

Install location

Version pinning

CI/CD integration

Team Onboarding

Rollback/updates

Disk space

Works on any Linux-distro, macOS and Windows

Ubuntu-focused only

Locked environments, consistent builds

Depends on apt/pip repo state

Can install ROS 1 and 2 side-by-side in isolated envs

One ROS version per machine

Isolated

System-wide

Automatic, with lockfile

Hard

Native GitHub Action support, as easy as local

Recommended to use special Docker images

Share Git repo, run pixi shell

Read complex Wiki pages

Checkout a previous lockfile (pixi.lock)

Risky, no declarative way

Larger when multiple versions of the same package used on one machine.

Smallest, every package can only live once on a machine

Quick Start

Let’s walk through a simple example of setting up a ROS environment using Pixi.

# Install pixi on unix (if you haven’t already) curl -fsSL https://pixi.sh/install.sh | bash # Or with brew: brew install pixi # Or on Windows: winget install prefix-dev.pixi

Restart your terminal (to update the PATH) and create a new workspace:

pixi init ros-example cd ros-example # Add a channel with ROS packages, similar to adding apt sources pixi workspace channel add robostack-jazzy # Add a ROS package pixi add ros-jazzy-ros-core

Now you have an isolated ROS environment. You can start a shell in this environment and run ROS commands:

pixi shell ros2 # Will show available commands # Then you can exit the isolated environment exit

This works the same way on Linux, macOS, and Windows — no Docker, no system configuration.

Support for all major OSes

Pixi leverages the cross-platform nature of conda to provide ROS packages on Linux, macOS, and Windows. This means you can develop ROS applications on your preferred OS without worrying about compatibility issues.

Add support for more platforms to your workspace with the following command:

pixi workspace platform add osx-arm64 linux-64 linux-aarch64 win-64

This would result in a pixi.toml which includes the following information:

[workspace] channels = ["conda-forge", "robostack-jazzy"] platforms = ["osx-arm64", "linux-64", "linux-aarch64", "win-64"] [dependencies] ros-jazzy-ros-core = ">=0.11.0,<0.12"

After adding these platforms, Pixi will ensure that all the dependencies you define are available for each specified OS architecture. Pixi will give you a helpful error message if something is missing.

Support for multiple distros

Defining multiple distros is normally done by switching OS, VM, or Docker image, with Pixi you can do it directly on your machine in one workspace using environments.

Replace the content of the pixi.toml with the following:

[workspace] channels = ["conda-forge"] platforms = ["osx-arm64", "linux-64", "win-64", "linux-aarch64"] [feature.jazzy] channels = ["robostack-jazzy"] [feature.jazzy.dependencies] ros-jazzy-ros-core = "*" ros-jazzy-turtlesim = "*" [feature.humble] channels = ["robostack-humble"] [feature.humble.dependencies] ros-humble-ros-core = "*" ros-humble-turtlesim = "*" [environments] jazzy = ["jazzy"] default = ["humble"]

Which will allow you to spawn a distro specific environment:

pixi shell --environment jazzy ros2 run turtlesim turtlesim_node exit

And in another terminal you can run the other distro:

pixi shell # '--environment default' is implied ros2 run turtlesim turtlesim_node exit

Now you should have two turtlesims running from a different distro.

Pixi works with features and environments where an environment can be built up from one or more features to create flexible and complex setups, all within a simple TOML file. This is better explained in the documentation.

Less gray hair from debugging CI!

These cross-platform, multi-environment setups make it incredibly easy to test against multiple versions of ROS on different platforms in CI, for example checkout this GitHub action workflow:

.github/workflows/test.yml

on: [push, pull_request] jobs: install: name: ${{ matrix.environment }} env on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] environment: [jazzy, humble] steps: - uses: actions/checkout@v4 - name: Setup Pixi environment uses: prefix-dev/[email protected] with: environments: ${{ matrix.environment }} - name: Test run: pixi run -e ${{ matrix.environment }} ros2 pkg list

No Docker needed, no Ubuntu lock-in, no flaky package installation!

Docker for deployment

While I've been showing how easy it is to get rid of Docker, this doesn't make them incompatible. Actually, quite the opposite!

Because with Pixi you have perfectly reproducible environments, you can just as easily recreate them in a docker image!

# Use our prebuild ubuntu image with pixi built in. FROM ghcr.io/prefix-dev/pixi:latest COPY . /app WORKDIR /app RUN pixi install # Create the shell-hook bash script to activate the environment RUN pixi shell-hook > /shell-hook.sh # extend the shell-hook script to run the command passed to the container RUN echo 'exec "$@"' >> /shell-hook.sh # set the entrypoint to the shell-hook script (activate the environment and run the command) # no more pixi needed in the prod container ENTRYPOINT ["/bin/bash", "/shell-hook.sh"]

This is a simplified version of the example in the pixi-docker repo, there is a lot more optimization you can do!

Using CUDA and ROS together

Pixi makes it easy to combine ROS with other complex dependencies like CUDA. You can specify the exact CUDA version you need alongside your ROS packages. For an in-detail workshop on how to use CUDA packages with Pixi you can follow this workshop we gave at SciPy2025.

Here is a simple configuration that ensures your ROS environment is set up with the correct CUDA version, making it easy to develop robotics applications that leverage GPU acceleration. The only thing users need is an NVIDIA GPU with drivers installed. Pixi will set up all the required CUDA packages (including the SDK).

[workspace] channels = ["conda-forge", "robostack-kilted"] platforms = ["linux-64"] [dependencies] ros-kilted-ros-core = ">=0.12.0,<0.13" ros-kilted-rviz2 = ">=15.0.6,<16" # CUDA dependencies cuda-version = ">=12.9,<13" cuda = ">=12.9.1,<13" # Add PyTorch pytorch-gpu = ">=2.7.1,<3" # Tell Pixi it should expect CUDA with a minimum version of 12 [system-requirements] cuda = "12"

Automatic package.xml reading

ROS packages already declare dependencies in a package.xml. Pixi can use that metadata directly, so you don’t have to duplicate dependency definitions.

When using a Pixi package, you would normally specify a pixi.toml that configures the package.

Instead of needing the following pixi.toml file:

[package.build] backend = { name = "pixi-build-ros", version = "*" }

You can leave this out and use a package.xml as a source dependency in the root of your workspace.

This would be an example of how you would add everything you need from a ROS package:

[workspace] channels = ["robostack-jazzy", "conda-forge"] platforms = ["osx-arm64", "linux-64", "win-64", "linux-aarch64"] [dependencies] ros-jazzy-my-package = { path = "src/my_package/package.xml" } ros-jazzy-ros-core = ">=0.11.0,<0.12"

Running pixi install will now not only install ros-jazzy-ros-core but also my_package by building it for you. An example of this can be found in this GitHub Repository.

Developing on local packages (experimental!)

When developing a package you might not want Pixi to handle the build and installation, for instance you could want colcon to take care of that. We're experimenting with this through a proposal we made in this GitHub Issue. Feel free to discuss your own ideas in the issue.

Which proposes the addition of a [dev] table for the packages you want to only the development dependencies from, check this pixi.toml:

[workspace] channels = ["robostack-jazzy", "conda-forge"] platforms = ["osx-arm64", "linux-64", "win-64", "linux-aarch64"] preview = ["pixi-build"] [dependencies] ros-jazzy-desktop = "*" # Special new table [dev] ros-jazzy-my-package = { path = "src/my_package/package.xml" } [tasks] build = "colcon build --symlink-install" # Required to activate the ROS workspace after colcon build [target.unix.activation] scripts = ["install/setup.sh"] [target.win.activation] scripts = ["install/setup.bat"]

Then running pixi run build will do the following:

  • Fetch the dependencies from the package.xml in src/my_package

  • Install an environment that includes those dependencies + the ros-jazzy-desktop package.

  • Activate the isolated environment that was just installed.

  • Run colcon build --symlink-install in your workspace.

After that, you can do pixi shell again to access the installed workspace and run ros2 like you normally would.

Together with our friends from the RoboStack team, most notably Tobias Fischer and Silvio Traversaro, we're growing the amount of packages supported through the RoboStack channels. We can use your help!

You might experience missing packages, especially on Windows/macOS. Not all open-source ROS packages can compile to these platforms, yet, as it is not officially supported by the OSRF.

If you're missing a ROS package, you can add it to the vinca.yml of the corresponding ROS distribution:

Or checkout the contribution docs of RoboStack.

Missing non-ROS packages? You can also help out by adding them to the conda-forge channel. Follow the contribution docs of conda-forge.

When you encounter issues, we host an active community in our Discord channel which would love to help you out.

Our team heavily focuses on making the whole installation and building experience of packages more enjoyable, so expect frequent improvements.

Looking forward, we hope OSRF will officially support RoboStack channels as an alternative package source for ROS distributions. This would enable replacing the distro-locked style of installing ROS with a more flexible approach using Pixi, allowing developers to piece together environments highly focused on their needs instead of being bound by the limitations of apt and Ubuntu releases.

With Pixi, robotics developers can work across multiple ROS distributions and operating systems, without Docker, without Ubuntu lock-in, and with all dependencies managed in a single declarative file. All of this while also making the actual installation much faster and more reproducible!

At prefix.dev, we build the tools to make this possible, but we need your help to grow the ecosystem. Help us test, contribute packages, and spread the word. One day, we hope to see Pixi as a first-class citizen in the ROS community. Allowing developers to focus on building amazing robots, while not wrestling with package management.

Try Pixi out today and bring your ROS workflow to any machine, anywhere, with lighting speed! Happy robotics developing!

We offer companies and universities help with setting up your package management workflows to accelerate your teams' development efficiency! Contact us, send an email to [email protected] or join our Discord to discuss how we can help your team succeed.

Read Entire Article