Skip to content
Back to skills

Uv2nix

CSecurity

uv2nix Skill

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
developmentpythonrustgoshellbashsqlexpressfastapidjangoflask

Works with

  • cli
  • api

Security analysis

C67/100
  • criticalPipes output to a shell interpreter
  • mediumUses curl or wget to download content
  • criticalDownloads and executes remote scripts — classic supply chain attack
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 17, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill uv2nix --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Uv2nix?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Uv2nix
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-uv2nix/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-uv2nix)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: uv2nix
version: 1.0
description: uv2nix Skill
---

# uv2nix Skill

A specialized skill for converting Python projects using uv to Nix expressions, enabling declarative and reproducible
Python package management with Nix.

## Skill Overview

**Purpose**: Provide comprehensive support for using uv2nix to generate Nix derivations from uv workspaces, manage
Python dependencies, and integrate Python projects with Nix/NixOS.

**Invoke When**:

- Converting uv Python projects to Nix
- Creating Nix derivations for Python applications
- Managing Python dependencies with Nix
- Building reproducible Python environments
- Setting up development environments for Python projects
- Packaging Python tools for NixOS
- Working with Python workspaces and monorepos

## Core Capabilities

### 1. What is uv2nix?

**uv2nix** takes a uv workspace and generates Nix derivations dynamically using pure Nix code. It bridges the gap between
uv (Astral's fast Python package manager) and Nix.

**Key Benefits:**

- **Fast**: Leverages uv's Rust-based speed
- **Reproducible**: Nix ensures deterministic builds
- **Declarative**: Everything in configuration
- **Workspace Support**: Handles monorepos and multi-package projects
- **Modern**: Uses PEP-621 pyproject.toml standards

**Built on pyproject.nix:**

- Uses pyproject.nix infrastructure
- Supports PEP-621 compliant pyproject.toml
- Integrates with nixpkgs Python ecosystem

### 2. Prerequisites

#### Install uv (if not already installed)

```bash
# Via curl
curl -LsSf https://astral.sh/uv/install.sh | sh

# Via nix
nix-env -iA nixpkgs.uv

# Or in NixOS configuration
environment.systemPackages = [ pkgs.uv ];
```

#### Install uv2nix

```bash
# Via nix
nix-env -f '<nixpkgs>' -iA uv2nix

# Or from flake
nix profile install github:pyproject-nix/uv2nix

# Verify
uv2nix --version
```

#### On NixOS

```nix
# /etc/nixos/configuration.nix
{ pkgs, ... }:
{
  environment.systemPackages = with pkgs; [
    uv
    uv2nix
  ];
}
```

#### Via home-manager

```nix
home.packages = with pkgs; [
  uv
  uv2nix
];
```

### 3. Basic Usage

#### Initialize uv Project

```bash
# Create new Python project with uv
uv init my-python-app
cd my-python-app

# Add dependencies
uv add requests flask

# Generate lock file
uv lock

# Project structure:
# my-python-app/
# ├── pyproject.toml
# ├── uv.lock
# └── src/
#     └── my_python_app/
#         └── __init__.py
```

#### Generate Nix Expressions

```bash
# Generate Nix derivations from uv workspace
uv2nix

# This creates/updates:
# - default.nix (or checks flake.nix)
# - Nix expressions for the workspace
```

#### Build with Nix

```bash
# Build the package
nix-build

# Or with flakes
nix build

# Run the application
./result/bin/my-python-app
```

### 4. Project Structure

**pyproject.toml** - Project metadata:

```toml
[project]
name = "my-python-app"
version = "0.1.0"
description = "My Python application"
requires-python = ">=3.11"
dependencies = [
    "requests>=2.31.0",
    "flask>=3.0.0",
]

[project.scripts]
my-app = "my_python_app.main:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.uv]
dev-dependencies = [
    "pytest>=7.4.0",
    "black>=23.0.0",
    "ruff>=0.1.0",
]
```

**uv.lock** - Lock file with pinned versions:

```text
# Generated by uv
# Contains exact dependency versions
# Should be committed to version control
```

### 5. Workspace Support

#### Monorepo Structure

```bash
# Create workspace
mkdir my-workspace
cd my-workspace

# Initialize workspace
cat > pyproject.toml <<EOF
[tool.uv.workspace]
members = ["packages/*"]
EOF

# Create packages
mkdir -p packages/lib packages/app

# Package 1: Library
cd packages/lib
uv init
cat > pyproject.toml <<EOF
[project]
name = "my-lib"
version = "0.1.0"
EOF

# Package 2: Application
cd ../app
uv init
cat > pyproject.toml <<EOF
[project]
name = "my-app"
version = "0.1.0"
dependencies = ["my-lib"]
EOF

cd ../..
uv lock
```

#### Generate Nix for Workspace

```bash
# At workspace root
uv2nix

# Generates derivations for all workspace members
```

### 6. Flake Integration

#### flake.nix for Python Project

```nix
{
  description = "My Python application using uv2nix";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    pyproject-nix = {
      url = "github:pyproject-nix/pyproject.nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    uv2nix = {
      url = "github:pyproject-nix/uv2nix";
      inputs.nixpkgs.follows = "nixpkgs";
      inputs.pyproject-nix.follows = "pyproject-nix";
    };
  };

  outputs = { self, nixpkgs, pyproject-nix, uv2nix }:
    let
      forAllSystems = nixpkgs.lib.genAttrs [
        "x86_64-linux"
        "aarch64-linux"
        "x86_64-darwin"
        "aarch64-darwin"
      ];
    in
    {
      packages = forAllSystems (system:
        let
          pkgs = nixpkgs.legacyPackages.${system};

          # Load workspace
          workspace = uv2nix.lib.${system}.loadWorkspace { workspaceRoot = ./.; };

          # Create Python environment
          pythonSet = pkgs.callPackage pyproject-nix.build.packages {
            python = pkgs.python311;
          };

          # Build application
          app = pythonSet.mkPyprojectApplication {
            inherit workspace;
          };
        in
        {
          default = app;
          my-python-app = app;
        }
      );

      devShells = forAllSystems (system:
        let
          pkgs = nixpkgs.legacyPackages.${system};

          workspace = uv2nix.lib.${system}.loadWorkspace { workspaceRoot = ./.; };

          pythonEnv = pkgs.python311.withPackages (ps:
            uv2nix.lib.${system}.getWorkspacePackages workspace ps
          );
        in
        {
          default = pkgs.mkShell {
            packages = [
              pythonEnv
              pkgs.uv
            ];

            shellHook = ''
              echo "Python development environment"
              echo "Python: $(python --version)"
              echo "uv: $(uv --version)"
            '';
          };
        }
      );

      apps = forAllSystems (system: {
        default = {
          type = "app";
          program = "${self.packages.${system}.default}/bin/my-app";
        };
      });
    };
}
```

**Usage:**

```bash
# Build
nix build

# Run
nix run

# Development shell
nix develop

# Update dependencies
uv lock
nix flake lock --update-input uv2nix
```

### 7. Development Environment

#### Simple Shell

```nix
# shell.nix
{ pkgs ? import <nixpkgs> {} }:

let
  # Load uv2nix
  uv2nix = pkgs.callPackage (pkgs.fetchFromGitHub {
    owner = "pyproject-nix";
    repo = "uv2nix";
    rev = "main";
    sha256 = "...";
  }) {};

  workspace = uv2nix.lib.loadWorkspace { workspaceRoot = ./.; };

  pythonEnv = pkgs.python311.withPackages (ps:
    uv2nix.lib.getWorkspacePackages workspace ps
  );
in
pkgs.mkShell {
  packages = [
    pythonEnv
    pkgs.uv
    pkgs.ruff
    pkgs.black
  ];

  shellHook = ''
    echo "Python development environment ready"
    python --version
  '';
}
```

#### Enhanced Development Shell

```nix
{ pkgs ? import <nixpkgs> {} }:

let
  workspace = /* load workspace */;
  pythonEnv = /* create environment */;
in
pkgs.mkShell {
  packages = [
    pythonEnv
    pkgs.uv

    # Linting and formatting
    pkgs.ruff
    pkgs.black
    pkgs.mypy

    # Testing
    pkgs.python311Packages.pytest
    pkgs.python311Packages.pytest-cov

    # Development tools
    pkgs.python311Packages.ipython
    pkgs.python311Packages.ipdb
  ];

  shellHook = ''
    # Set up development environment
    export PYTHONPATH="$PWD/src:$PYTHONPATH"
    export UV_CACHE_DIR="$PWD/.uv-cache"

    # Create virtual environment if needed
    if [ ! -d .venv ]; then
      uv venv
    fi

    source .venv/bin/activate

    echo "🐍 Python development environment"
    echo "Python: $(python --version)"
    echo "uv: $(uv --version)"
    echo ""
    echo "Available commands:"
    echo "  uv add <package>  - Add dependency"
    echo "  uv lock           - Update lock file"
    echo "  pytest            - Run tests"
    echo "  ruff check .      - Lint code"
    echo "  black .           - Format code"
  '';
}
```

### 8. Building Applications

#### CLI Application

```toml
# pyproject.toml
[project]
name = "my-cli"
version = "1.0.0"
description = "My CLI tool"

[project.scripts]
my-cli = "my_cli.main:cli"

dependencies = [
    "click>=8.0.0",
    "rich>=13.0.0",
]
```

**Build with Nix:**

```nix
{ pkgs, workspace }:

pkgs.python311Packages.buildPythonApplication {
  pname = "my-cli";
  version = "1.0.0";

  src = ./.;

  propagatedBuildInputs = with pkgs.python311Packages; [
    click
    rich
  ];

  # From workspace
  pyproject = true;

  meta = {
    description = "My CLI tool";
    license = pkgs.lib.licenses.mit;
    mainProgram = "my-cli";
  };
}
```

#### Web Application (Flask)

```toml
[project]
name = "my-webapp"
version = "1.0.0"

dependencies = [
    "flask>=3.0.0",
    "gunicorn>=21.0.0",
]

[project.scripts]
my-webapp = "my_webapp.app:main"
```

**NixOS Service:**

```nix
{ config, lib, pkgs, ... }:

let
  myWebapp = /* build from uv2nix */;
in
{
  systemd.services.my-webapp = {
    description = "My Python Web Application";
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];

    serviceConfig = {
      ExecStart = "${myWebapp}/bin/gunicorn -b 0.0.0.0:8000 my_webapp.app:app";
      Restart = "on-failure";
      DynamicUser = true;

      # Security hardening
      ProtectSystem = "strict";
      NoNewPrivileges = true;
      PrivateTmp = true;
    };

    environment = {
      PYTHONUNBUFFERED = "1";
      FLASK_ENV = "production";
    };
  };

  networking.firewall.allowedTCPPorts = [ 8000 ];
}
```

### 9. Testing Integration

#### Test Configuration

```toml
# pyproject.toml
[tool.uv]
dev-dependencies = [
    "pytest>=7.4.0",
    "pytest-cov>=4.1.0",
    "pytest-asyncio>=0.21.0",
]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
```

#### Run Tests in Nix

```nix
{ pkgs, workspace }:

let
  pythonEnv = /* build environment with dev deps */;
in
pkgs.stdenv.mkDerivation {
  name = "my-app-tests";
  src = ./.;

  buildInputs = [ pythonEnv ];

  checkPhase = ''
    pytest tests/ -v --cov=src
  '';

  installPhase = ''
    mkdir -p $out
    echo "Tests passed" > $out/result
  '';
}
```

#### CI Integration

```yaml
# .github/workflows/test.yml
name: Test
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: cachix/install-nix-action@v22
      - uses: cachix/cachix-action@v12
        with:
          name: pyproject-nix
      - run: nix build .#checks.x86_64-linux.default
```

### 10. Overlay Creation

#### Custom Overlay

```nix
# overlay.nix
final: prev: {
  pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
    (python-final: python-prev: {
      my-package = python-final.buildPythonPackage {
        pname = "my-package";
        version = "1.0.0";
        src = ./.;

        propagatedBuildInputs = with python-final; [
          requests
          flask
        ];

        pyproject = true;
      };
    })
  ];
}
```

#### Use Overlay

```nix
{ pkgs ? import <nixpkgs> {
    overlays = [ (import ./overlay.nix) ];
  }
}:

{
  my-app = pkgs.python311Packages.my-package;
}
```

### 11. Common Patterns

#### Pattern 1: Simple Python Package

```bash
# Create project
uv init my-package
cd my-package

# Add dependencies
uv add requests click

# Lock dependencies
uv lock

# Generate Nix expressions
uv2nix

# Build
nix-build

# Install
nix-env -f default.nix -iA package
```

#### Pattern 2: Python Library

```toml
# pyproject.toml
[project]
name = "my-lib"
version = "0.1.0"
description = "My Python library"

dependencies = [
    "numpy>=1.24.0",
    "pandas>=2.0.0",
]

[build-system]
requires = ["setuptools>=68.0"]
build-backend = "setuptools.build_meta"
```

#### Pattern 3: Data Science Project

```bash
# Initialize with scientific packages
uv init data-analysis
cd data-analysis

uv add numpy pandas matplotlib scipy jupyter

# Lock
uv lock

# Generate Nix with development deps
```

```nix
# shell.nix for data science
{ pkgs ? import <nixpkgs> {} }:

let
  pythonEnv = pkgs.python311.withPackages (ps: with ps; [
    numpy
    pandas
    matplotlib
    scipy
    jupyter
    ipython
    scikit-learn
  ]);
in
pkgs.mkShell {
  packages = [
    pythonEnv
    pkgs.uv
  ];

  shellHook = ''
    jupyter notebook
  '';
}
```

#### Pattern 4: FastAPI Application

```toml
[project]
name = "my-api"
version = "1.0.0"

dependencies = [
    "fastapi>=0.104.0",
    "uvicorn[standard]>=0.24.0",
    "pydantic>=2.0.0",
]

[project.scripts]
my-api = "my_api.main:run"
```

**NixOS Service:**

```nix
systemd.services.my-api = {
  serviceConfig = {
    ExecStart = "${myApi}/bin/uvicorn my_api.main:app --host 0.0.0.0 --port 8000";
    DynamicUser = true;
  };
};
```

#### Pattern 5: Django Project

```bash
uv init my-django-app
cd my-django-app

uv add django psycopg2-binary gunicorn

# Lock
uv lock
```

```nix
# NixOS module
{ config, pkgs, ... }:

let
  djangoApp = /* build with uv2nix */;
in
{
  services.postgresql = {
    enable = true;
    ensureDatabases = [ "myapp" ];
  };

  systemd.services.django = {
    serviceConfig = {
      ExecStart = "${djangoApp}/bin/gunicorn myapp.wsgi:application";
      Environment = [
        "DJANGO_SETTINGS_MODULE=myapp.settings"
        "DATABASE_URL=postgresql:///myapp"
      ];
    };
  };
}
```

### 12. Dependency Management

#### Adding Dependencies

```bash
# Add runtime dependency
uv add requests

# Add with version constraint
uv add "flask>=3.0.0,<4.0.0"

# Add development dependency
uv add --dev pytest black ruff

# Add optional dependency group
uv add --group docs sphinx sphinx-rtd-theme

# Lock after changes
uv lock
```

#### Removing Dependencies

```bash
# Remove dependency
uv remove requests

# Lock
uv lock
```

#### Updating Dependencies

```bash
# Update all dependencies
uv lock --upgrade

# Update specific package
uv lock --upgrade-package requests

# Check outdated
uv pip list --outdated
```

### 13. NixOS Integration

#### System Package

```nix
# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

let
  myPythonApp = import /path/to/app {
    inherit pkgs;
  };
in
{
  environment.systemPackages = [
    myPythonApp
  ];
}
```

#### User Package (home-manager)

```nix
# home.nix
{ pkgs, ... }:

let
  myTool = import /path/to/tool {
    inherit pkgs;
  };
in
{
  home.packages = [
    myTool
  ];
}
```

#### Custom Module

```nix
# modules/my-python-service.nix
{ config, lib, pkgs, ... }:

with lib;

let
  cfg = config.services.my-python-service;

  myApp = import ../python-app {
    inherit pkgs;
  };
in
{
  options.services.my-python-service = {
    enable = mkEnableOption "My Python Service";

    port = mkOption {
      type = types.int;
      default = 8000;
    };

    workers = mkOption {
      type = types.int;
      default = 4;
    };
  };

  config = mkIf cfg.enable {
    systemd.services.my-python-service = {
      description = "My Python Service";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];

      serviceConfig = {
        ExecStart = ''
          ${myApp}/bin/gunicorn \
            -w ${toString cfg.workers} \
            -b 0.0.0.0:${toString cfg.port} \
            app:application
        '';
        Restart = "on-failure";
        DynamicUser = true;
      };
    };

    networking.firewall.allowedTCPPorts = [ cfg.port ];
  };
}
```

### 14. Troubleshooting

#### Issue 1: Lock File Out of Sync

**Problem**: Changes to pyproject.toml not reflected

**Solution:**

```bash
# Regenerate lock file
uv lock

# Force update
uv lock --upgrade

# Regenerate Nix expressions
uv2nix
```

#### Issue 2: Build Failures

**Problem**: Package fails to build with Nix

**Solution:**

```nix
# Add missing build dependencies
{ pkgs, ... }:

pkgs.python311Packages.buildPythonPackage {
  # ...

  nativeBuildInputs = with pkgs; [
    python311Packages.setuptools
    python311Packages.wheel
  ];

  buildInputs = with pkgs; [
    # System dependencies
    gcc
    pkg-config
    openssl
  ];
}
```

#### Issue 3: Import Errors

**Problem**: Module not found at runtime

**Solution:**

```nix
# Ensure proper Python path
{
  shellHook = ''
    export PYTHONPATH="$PWD/src:$PYTHONPATH"
  '';
}
```

#### Issue 4: Native Extensions

**Problem**: Package with C extensions fails

**Solution:**

```bash
# Ensure build tools in environment
```

```nix
buildInputs = with pkgs; [
  python311Packages.setuptools
  gcc
  python311.pkgs.cython
];
```

#### Issue 5: Workspace Resolution

**Problem**: Workspace packages not found

**Solution:**

```bash
# Ensure proper workspace structure
# pyproject.toml at root with:
[tool.uv.workspace]
members = ["packages/*"]

# Regenerate
uv lock
uv2nix
```

### 15. Best Practices

#### DO ✅

1. **Always commit lock files**

   ```bash
   git add uv.lock
   git commit -m "Lock dependencies"
   ```

2. **Use PEP-621 pyproject.toml**

   ```toml
   [project]
   name = "my-package"
   version = "0.1.0"
   requires-python = ">=3.11"
   ```

3. **Pin Python version**

   ```toml
   [project]
   requires-python = ">=3.11,<3.12"
   ```

4. **Version control Nix expressions**

   ```bash
   git add default.nix flake.nix
   ```

5. **Use development dependencies**

   ```bash
   uv add --dev pytest ruff black
   ```

6. **Test in clean environment**

   ```bash
   nix-build
   ./result/bin/my-app
   ```

7. **Document dependencies**

   ```toml
   [project]
   dependencies = [
       "requests>=2.31.0",  # HTTP client
       "click>=8.0.0",      # CLI framework
   ]
   ```

8. **Use flakes for reproducibility**

   ```nix
   inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
   ```

9. **Leverage workspace features**

   ```toml
   [tool.uv.workspace]
   members = ["packages/*"]
   ```

10. **Keep uv and uv2nix updated**

    ```bash
    uv self update
    nix profile upgrade uv2nix
    ```

#### DON'T ❌

1. **Don't commit**pycache

   ```gitignore
   __pycache__/
   *.pyc
   ```

2. **Don't skip lock file**

   ```bash
   # ❌ Bad
   uv add requests  # without uv lock

   # ✅ Good
   uv add requests && uv lock
   ```

3. **Don't mix pip and uv**

   ```bash
   # ❌ Don't use pip install with uv project
   # ✅ Use uv add
   ```

4. **Don't hardcode paths**

   ```python
   # ❌ Bad
   config_path = "/home/user/config.json"

   # ✅ Good
   config_path = os.path.expanduser("~/.config/myapp/config.json")
   ```

5. **Don't commit secrets**

   ```bash
   # Use environment variables or secret management
   # Never commit API keys, passwords
   ```

6. **Don't skip tests**

   ```bash
   # Always run tests before committing
   pytest tests/
   ```

7. **Don't ignore warnings**

   ```bash
   # Address deprecation warnings
   # Fix type errors
   ```

## Command Reference

```bash
# uv commands
uv init [project]              # Initialize project
uv add <package>              # Add dependency
uv add --dev <package>        # Add dev dependency
uv remove <package>           # Remove dependency
uv lock                       # Generate lock file
uv lock --upgrade             # Update all dependencies
uv sync                       # Install dependencies
uv run <command>              # Run in environment
uv tree                       # Show dependency tree

# uv2nix commands
uv2nix                        # Generate Nix expressions
uv2nix --help                 # Show help

# Nix commands
nix-build                     # Build package
nix-shell                     # Enter dev environment
nix flake init               # Initialize flake
nix build                     # Build (flakes)
nix develop                   # Dev shell (flakes)
nix run                       # Run app (flakes)
```

## Success Metrics

- **Reproducible**: Same pyproject.toml → same build
- **Fast**: uv's Rust-based speed + Nix caching
- **Declarative**: Everything in configuration
- **Workspace Support**: Monorepo capabilities
- **Modern**: PEP-621 compliant
- **Integrated**: Works with NixOS services
- **Tested**: CI integration validated

Ready to build reproducible Python applications with uv2nix! 🐍

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.