Skip to content

Getting Started

Start from a Python project directory. uv still owns Python package metadata, dependency groups, lockfiles, and virtualenv sync.

What to expect

  • robo shell is the main command. It prepares the runtime, then opens your normal interactive shell with a [robo] prompt prefix.
  • On first use, robo shell may create flake.nix, robo.nix, and .robo-nix/. After that, robo.nix is yours to edit.
  • robo run [--profile <name>] [--sync] [--] <command> [args...] uses the same runtime preparation path for one command without keeping a shell open.
  • robo search <library> helps find Nix package candidates for missing shared libraries, such as libassimp.so. It only prints suggestions.
  • robo refresh clears robo-owned runtime state under .robo-nix/. In an active runtime shell, the shell updates at the next prompt.
  • robo update updates the project robo-nix flake input, reinstalls the robo CLI binary from that updated input, and clears runtime cache state. It does not update Python dependencies or robo.nix.
  • robo --help, robo --version, and robo -V are available as standard CLI utilities.
  • Active robo shell sessions refresh at the next prompt when runtime inputs change. This includes the selected runtime profile, flake.nix, flake.lock, .python-version, pyproject.toml, uv.lock, robo.nix, and local .nix files imported by robo.nix or the project flake.
  • Refreshing exports a re-evaluated shell environment. It does not run uv sync and does not rewrite robo.nix.
  • First-bootstrap inference reads direct dependencies, optional dependencies, dependency groups, local [tool.uv.sources] path dependencies, and package names from an existing uv.lock when available.
  • Every runtime attempt writes .robo-nix/last-run.json with redacted runtime facts, including typed host CUDA and graphics probe summaries. When setup fails, robo also writes .robo-nix/last-error.log with context you can paste into an issue.

1. Install robo

The installer installs the robo CLI through Nix profiles. If Nix is missing, it uses the Determinate Nix installer first.

bash
curl --proto '=https' --tlsv1.2 -fsSL https://raw.githubusercontent.com/ausbxuse/robo-nix/master/scripts/install.sh | sh

When testing from a local checkout:

bash
ROBO_NIX_FLAKE="path:$PWD" ./scripts/install.sh

Manual profile install from a local checkout:

bash
nix profile remove robo || true
nix profile add .#robo

Use .#robo instead of .# so the profile entry is named robo and future nix profile remove robo commands keep working.

Newly generated project flake.nix files point at github:ausbxuse/robo-nix/master by default, even when robo was installed from a local checkout. To test a project against local robo-nix source, set ROBO_NIX_DEFAULT_SOURCE_URL=path:/path/to/robo-nix before first bootstrap. After changing that override, rebootstrap the test project by removing generated runtime files such as flake.nix, flake.lock, robo.nix, and .robo-nix/, then running robo shell again.

Installer overrides:

  • ROBO_NIX_FLAKE changes the flake installed by the script.
  • ROBO_NIX_NIX_INSTALLER_URL changes the Nix installer URL used when Nix is not already installed.

2. Pin Python

bash
uv python pin <version>

robo reads .python-version and does not choose a default Python version. For example:

bash
uv python pin 3.11

3. Enter the runtime

bash
robo shell --sync

On first bootstrap, robo shell may create:

  • flake.nix: minimal Nix plumbing that delegates to robo-nix.
  • robo.nix: the project runtime manifest.
  • .gitignore: in Git worktrees, an entry for .robo-nix/ when missing.

With --sync, robo runs uv sync --locked in the prepared runtime before entering your default interactive shell with a [robo] prompt prefix. Set ROBO_NIX_SHELL only when you need to override shell selection.

4. Sync Python packages

bash
uv sync

You can also run uv sync manually inside the prepared shell. Native Python extensions can then see the runtime libraries and headers exposed by Nix. In profile-based projects, robo sets UV_PROJECT_ENVIRONMENT to a profile-specific virtualenv under .robo-nix/venvs/<profile>/, so different runtime profiles can stay installed side by side.

5. Adjust runtime components

After first bootstrap, edit robo.nix for project runtime choices such as native build tools, Linux headers, desktop graphics, Qt, or CUDA build tooling.

For example, a project using evdev and GLFW-style windows usually needs:

nix
{
  defaultProfile = "default";

  profiles = {
    default = {
      components = [
        "python-uv"
        "native-build"
        "linux-headers"
        "desktop-gl"
      ];

      pythonExtras = [];
      pythonGroups = [];

      extraPackages = pkgs: [
      ];

      extraRuntimeLibraries = pkgs: [
      ];

      hostGraphics = "auto";
    };
  };
}

Projects that contain multiple deployable surfaces can define more profiles in the same robo.nix:

nix
{
  defaultProfile = "workstation";

  profiles = {
    workstation = {
      components = [ "python-uv" "native-build" "linux-headers" "desktop-gl" ];
      pythonExtras = [ "workstation" ];
      pythonGroups = [ "dev" ];
      hostGraphics = "auto";
    };

    tianji-driver = {
      components = [ "python-uv" "native-build" "linux-headers" ];
      pythonExtras = [ "tianji-driver" ];
      pythonGroups = [];
      hostGraphics = null;
    };
  };
}

Use a non-default profile with:

bash
robo shell --profile tianji-driver --sync

If runtime inputs change while robo shell is open, the prompt hook refreshes the shell environment at the next prompt. Refreshing does not rewrite user-managed robo.nix.

If an error names a missing shared library, search for Nix package candidates:

bash
robo search libassimp.so

Use one command inside the runtime without staying in an interactive shell:

bash
robo run [--profile <name>] [--sync] [--] <command> [args...]

Use the optional -- when the command name starts with -. Any later -- belongs to the command being run. With --sync, robo runs uv sync --locked before launching the child command.

Clear local robo runtime state and rebuild the active shell environment at the next prompt:

bash
robo refresh

Update the version of robo-nix pinned by the project:

bash
robo update

This updates the robo-nix input in flake.lock, reinstalls the robo CLI binary from that updated input, and clears runtime cache state. The next robo shell or robo run uses the updated lock.

What robo does not do

robo does not create pyproject.toml, run uv sync unless --sync is explicitly requested, resolve Python packages, update project dependencies, or rewrite robo.nix after first creation.