Skip to content

Getting Started#

Every Pixi workspace is described by a Pixi manifest. In this simple example we have a single task start which runs a Python file and two dependencies, cowpy and python.

pixi.toml
[workspace]
channels = ["conda-forge"]
name = "hello-world"
platforms = ["linux-64", "osx-arm64", "win-64"]

[tasks]
start = "python hello.py"

[dependencies]
cowpy = "1.1.*"
python = "3.13.*"

channels describes where our dependencies come from and platforms which platforms we support. However, you might wonder why we need to specify the platforms if Pixi could just extract this information from your operating system. That is because every dependency in your environment is stored in the lockfile called pixi.lock. This ensures that even if you run your workspace on a different platform, the environment will contain exactly the dependencies that were solved on your machine. This is one of the core features that makes Pixi reproducible. Learn more about lock files in this chapter.

Multiple environments#

We already have a quite powerful setup which is sufficient for many use cases. However, certain things are hard to do with the way things are set up right now. What if I wanted to check if my script works with multiple versions of Python? There cannot be multiple versions of the same package in one environment. Luckily, Pixi is able to manage multiple environments!

Environments are composed of features, so let's create a py312 and py313 features each with python set to a different version. Then we will add those features to environments of the same name.

pixi.toml
[workspace]
channels = ["conda-forge"]
name = "hello-world"
platforms = ["linux-64", "osx-arm64", "win-64"]

[tasks]
start = "python hello.py"

[dependencies]
cowpy = "1.1.*"

[feature.py312.dependencies]
python = "3.12.*"

[feature.py313.dependencies]
python = "3.13.*"

[environments]
py312 = ["py312"]
py313 = ["py313"]

Pixi does two things behind the scenes which might not be immediately obvious. First, it automatically creates both a feature and environment called default. [dependencies] and [tasks] belong to that feature. Second, it adds the default feature to each environment unless you explicitly opt-out. That means you can read the manifest as if it were declared like this:

[workspace]
channels = ["conda-forge"]
name = "hello-world"
platforms = ["linux-64", "osx-arm64", "win-64"]

[feature.default.tasks]
start = 'python hello.py'

[feature.default.dependencies]
cowpy = "1.1.*"

[feature.py312.dependencies]
python = "3.12.*"

[feature.py313.dependencies]
python = "3.13.*"

[environments]
default = ["default"]
py312 = ["default", "py312"]
py313 = ["default", "py313"]

Let's adapt the Python script so that it displays the current Python version:

hello.py
from sys import version_info as vi
from cowpy.cow import Cowacter

python_version = f"Python {vi.major}.{vi.minor}"
message = Cowacter().milk(f"Hello from {python_version}!")
print(message)

The task start is available in both py312 and py313, so we can test the script like this to test against Python 3.12:

pixi run --environment=py312 start
 _________________________
< Hello from Python 3.12! >
 -------------------------
     \   ^__^
      \  (oo)\_______
         (__)\       )\/\
           ||----w |
           ||     ||

And we can run this command to try it with Python 3.13:

pixi run --environment=py312 start
 _________________________
< Hello from Python 3.12! >
 -------------------------
     \   ^__^
      \  (oo)\_______
         (__)\       )\/\
           ||----w |
           ||     ||

Going further#

There is still much more that Pixi has to offer. Check out the topics on the sidebar on the left to learn more.

And don't forget to join our Discord to join our community of Pixi enthusiasts!