Pixi Global Manifest#
Feedback wanted
This document is work in progress, and community feedback is greatly appreciated. Please share your thoughts at our GitHub discussion.
Motivation#
pixi global is currently limited to imperatively managing CLI packages.
The next iteration of this feature should fulfill the following needs:
- Shareable global environments.
- Managing complex environments with multiple packages as dependencies
- Flexible exposure of executables
Design Considerations#
There are a few things we wanted to keep in mind in the design:
- User-friendliness: Pixi is a user focused tool that goes beyond developers. The feature should have good error reporting and helpful documentation from the start.
- Keep it simple: The CLI should be all you strictly need to interact with global environments.
- Unsurprising: Simple commands should behave similar to traditional package managers.
- Human Readable: Any file created by this feature should be human-readable and modifiable.
Manifest#
The global environments and exposed will be managed by a human-readable manifest.
This manifest will stick to conventions set by pixi.toml where possible.
Among other things it will be written in the TOML format, be named pixi-global.toml and be placed at ~/.pixi/manifests/pixi-global.toml.
The motivation for the location is discussed further below
# The name of the environment is `python`
[envs.python]
channels = ["conda-forge"]
# optional, defaults to your current OS
platform = "osx-64"
# It will expose python, python3 and python3.11, but not pip
[envs.python.dependencies]
python = "3.11.*"
pip = "*"
[envs.python.exposed]
python = "python"
python3 = "python3"
"python3.11" = "python3.11"
# The name of the environment is `python3-10`
[envs.python3-10]
channels = ["https://fast.prefix.dev/conda-forge"]
# It will expose python3.10
[envs.python3-10.dependencies]
python = "3.10.*"
[envs.python3-10.exposed]
"python3.10" = "python"
CLI#
Install one or more packages PACKAGE and expose their executables.
If --environment has been given, all packages will be installed in the same environment.
--expose can be given if --environment is given as well or if only a single PACKAGE will be installed.
The syntax for MAPPING is exposed_name=executable_name, so for example python3.10=python.
--platform sets the platform of the environment to PLATFORM
Multiple channels can be specified by using --channel multiple times.
By default, if no channel is provided, the default-channels key in the pixi configuration is used, which again defaults to "conda-forge".
pixi global install [--expose MAPPING] [--environment ENV] [--platform PLATFORM] [--no-activation] [--channel CHANNEL]... PACKAGE...
Remove environments ENV.
Update PACKAGE if --package is given. If not, all packages in environments ENV will be updated.
If the update leads to executables being removed, it will offer to remove the mappings.
If the user declines the update process will stop.
If the update leads to executables being added, it will offer for each binary individually to expose it.
--assume-yes will assume yes as answer for every question that would otherwise be asked interactively.
Updates all packages in all environments.
If the update leads to executables being removed, it will offer to remove the mappings.
If the user declines the update process will stop.
If the update leads to executables being added, it will offer for each binary individually to expose it.
--assume-yes will assume yes as answer for every question that would otherwise be asked interactively.
Add one or more packages PACKAGE into an existing environment ENV.
If environment ENV does not exist, it will return with an error.
Without --expose no binary will be exposed.
If you don't mention a spec like python=3.8.*, the spec will be unconstrained with *.
The syntax for MAPPING is exposed_name=executable_name, so for example python3.10=python.
Remove package PACKAGE from environment ENV.
If that was the last package remove the whole environment and print that information in the console.
If this leads to executables being removed, it will offer to remove the mappings.
If the user declines the remove process will stop.
Add one or more MAPPING for environment ENV which describe which executables are exposed.
The syntax for MAPPING is exposed_name=executable_name, so for example python3.10=python.
Remove one or more exposed BINARY from environment ENV
Ensure that the environments on the machine reflect the state in the manifest.
The manifest is the single source of truth.
Only if there's no manifest, will the data from existing environments be used to create a manifest.
pixi global sync is implied by most other pixi global commands.
List all environments, their specs and exposed executables
Set the channels CHANNEL for a certain environment ENV in the pixi global manifest.
Set the platform PLATFORM for a certain environment ENV in the pixi global manifest.
Simple workflow#
Create environment python, install package python=3.10.* and expose all executables of that package
Update all packages in environment python
Remove environment python
Create environment python and pip, install corresponding packages and expose all executables of that packages
Remove environments python and pip
Create environment python-pip, install python and pip in the same environment and expose all executables of these packages
Adding dependencies#
Create environment python, install package python and expose all executables of that package.
Then add package hypercorn to environment python but doesn't expose its executables.
Update package cryptography (a dependency of hypercorn) to 43.0.0 in environment python
Then remove hypercorn again.
Specifying which executables to expose#
Make a new environment python3-10 with package python=3.10 and expose the python executable as python3.10.
Now python3.10 is available.
Run the following in order to expose python from environment python3-10 as python3-10 instead.
pixi global expose remove --environment python3-10 python3.10
pixi global expose add --environment python3-10 "python3-10=python"
Now python3-10 is available, but python3.10 isn't anymore.
Syncing#
Most pixi global sub commands imply a pixi global sync.
- Users should be able to change the manifest by hand (creating or modifying (adding or removing))
- Users should be able to "export" their existing environments into the manifest, if non-existing.
- The manifest is always "in sync" after
install/remove/inject/other global command.
First time, clean computer.
Running the following creates manifest and ~/.pixi/envs/python.
Delete ~/.pixi and syncing, should add environment python again as described in the manifest
If there's no manifest, but existing environments, pixi will create a manifest that matches your current environments. It is to be decided whether the user should be asked if they want an empty manifest instead, or if it should always import the data from the environments.
If we remove the python environment from the manifest, running pixi global sync will also remove the ~/.pixi/envs/python environment from the file system.
Open Questions#
Should we version the manifest?#
Something like:
We still have to figure out which existing programs do something similar and how they benefit from it.
Multiple manifests#
We could go for one default manifest, but also parse other manifests in the same directory.
The only requirement to be parsed as manifest is a .toml extension
In order to modify those with the CLI one would have to add an option --manifest to select the correct one.
- pixi-global.toml: Default
- pixi-global-company-tools.toml
- pixi-global-from-my-dotfiles.toml
It is unclear whether the first implementation already needs to support this.
At the very least we should put the manifest into its own folder like ~/.pixi/global/manifests/pixi-global.toml
Discovery via config key#
In order to make it easier to manage manifests in version control, we could allow to set the manifest path via a key in the pixi configuration.
No activation#
The current pixi global install features --no-activation.
When this flag is set, CONDA_PREFIX and PATH will not be set when running the exposed executable.
This is useful when installing Python package managers or shells.
Assuming that this needs to be set per mapping, one way to expose this functionality would be to allow the following: