Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

101 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LazyNix Logo

Providing reproducible environments for all developers

Why LazyNix?

LazyNix makes Nix development environments accessible through simple YAML configuration.

  • πŸš€ Simple: Write YAML instead of Nix expressions
  • πŸ”„ Reproducible: Powered by Nix flakes for deterministic builds
  • 🎯 Focused: Designed for DevShell only - when you need more, just use the generated flake.nix

Installation

πŸ“‹ Pre-Requirements

We recommend using Nix to install LazyNix. If you don't have Nix installed yet, get it from nixos.org/download.

Alternatively, you can use pre-built binaries from the release page or build from source.

⚑ No Installation Required

Try LazyNix without installing anything. Run it directly from GitHub using nix run:

# Display help
nix run github:shunsock/lazynix -- --help

# Initialize a new project
nix run github:shunsock/lazynix -- init

# Enter development environment
nix run github:shunsock/lazynix -- develop

❄️ Install to Profile

For permanent installation, add LazyNix to your Nix profile:

# Install from GitHub
nix profile install github:shunsock/lazynix

# Then use the lnix command directly
lnix --help
lnix init
lnix develop

πŸ“¦ Pre-built Binaries

Download platform-specific binaries from GitHub Releases.

🐧 Linux x86_64

curl -L -o lnix https://github.com/shunsock/lazynix/releases/latest/download/lnix-x86_64-linux
chmod +x lnix
sudo mv lnix /usr/local/bin/

🐧 Linux ARM64

curl -L -o lnix https://github.com/shunsock/lazynix/releases/latest/download/lnix-aarch64-linux
chmod +x lnix
sudo mv lnix /usr/local/bin/

🍎 macOS Apple Silicon

curl -L -o lnix https://github.com/shunsock/lazynix/releases/latest/download/lnix-aarch64-darwin
chmod +x lnix
sudo mv lnix /usr/local/bin/

πŸ”¨ Build from Source

Clone the repository and build using Nix:

# Clone the repository
git clone https://github.com/shunsock/lazynix.git
cd lazynix

# Build with Nix
nix build

# Run the built binary
./result/bin/lnix --help

Quick Start

Initialize a New Project

Create a new LazyNix configuration in your project directory:

lnix init

This creates two files:

  • πŸ“ lazynix.yaml - Your environment configuration (edit this)
  • βš™οΈ flake.nix - Generated Nix flake (auto-generated, don't edit)

Configure Your Environment

Edit lazynix.yaml to specify your development tools. Find packages at search.nixos.org.

devShell:
  allowUnfree: true

  package:
    stable:
      - name: python312
      - name: uv
    unstable: []
    pinned: []

  shellHook:
    - "echo Python $(python --version) ready!"
    - "echo uv $(uv --version) ready!"

  env:
    # Load from .env files
    dotenv:
      - .env

    # Define variables directly
    envvar:
      - name: PYTHONPATH
        value: ./src
      - name: DEBUG
        value: "true"

Enter the Development Environment

Activate your configured environment:

lnix develop

LazyNix will automatically:

  1. πŸ“– Read your lazynix.yaml configuration
  2. πŸ”§ Generate the flake.nix file
  3. πŸ”’ Update flake.lock with pinned dependencies (with --update)
  4. πŸš€ Enter the Nix development shell with all specified packages

πŸ“ Generate flake.nix Only

Regenerate flake.nix from lazynix.yaml without entering a shell or running any commands:

lnix generate

Handy for CI validation, applying edits to lazynix.yaml, or preparing to migrate to Pure Nix. When no pinned packages are configured, this runs fully offline without invoking Nix.

Commands Reference

LazyNix ships nine subcommands. All commands accept the global flags described below.

Subcommand Description Flags
init Create lazynix.yaml and flake.nix from templates --force (-f) β€” overwrite existing files
update Update flake.lock without entering a shell β€”
generate Regenerate flake.nix from lazynix.yaml without entering the shell β€”
develop Generate flake.nix and enter nix develop --update β€” update flake.lock first
run [--] <command>... Run a single command inside the dev environment --update, --no-regen (skip regenerating flake.nix)
test Run test commands defined under devShell.test: --update
task <name> [args...] Run a named task from devShell.task:; trailing args expand into {{.CLI_ARGS}} β€”
lint Validate every declared package (stable + unstable + pinned) via nix eval, and verify pinned versions can still be resolved --verbose (-v), --arch <target>
search <package> Look up available versions via nix-versions --version <semver> (-v), --json (-j), --one (-1)

Global Flags

  • -C, --config-dir <DIR> β€” directory containing lazynix.yaml and lazynix-settings.yaml (env: LAZYNIX_CONFIG_DIR, default: current directory)
  • --version β€” print the CLI version and exit

Exit Codes and Notes

  • lint exits with code 1 when any package fails validation, otherwise 0.
  • run, task, and test propagate the exit code of the underlying child process.
  • lint validates stable, unstable, and pinned packages. For each pinned entry, lint also asks nix-versions whether the requested version can still be resolved, catching typos in the version constraint before the next lnix develop.

Configuration

Custom Config Directory

By default, LazyNix looks for lazynix.yaml and lazynix-settings.yaml in the current directory. You can customize this location using either a CLI flag or environment variable.

Methods

1. CLI Flag (Recommended for one-off usage)

Use the --config-dir flag (or -C short form) before the subcommand:

lnix --config-dir ./configs develop
lnix -C ./configs develop  # Short form

2. Environment Variable (Recommended for persistent setup)

Set the LAZYNIX_CONFIG_DIR environment variable:

LAZYNIX_CONFIG_DIR=./configs lnix develop

# Or export for the entire session
export LAZYNIX_CONFIG_DIR=./configs
lnix init
lnix develop

Advanced Configuration

πŸ“‹ Settings File (Optional)

LazyNix supports an optional lazynix-settings.yaml file for system-level customization. This file is completely optional - LazyNix works perfectly without it using sensible defaults.

When to use settings:

  • Override nixpkgs versions (use older/newer packages)

πŸŽ›οΈ Override Stable Nixpkgs

By default, LazyNix uses nixos-25.11 for stable packages. You can override this in lazynix-settings.yaml:

# lazynix-settings.yaml
override-stable-package: "github:myorg/nixpkgs/custom-branch"

override-stable-package only affects the stable channel; the unstable channel is hardcoded to github:NixOS/nixpkgs/nixos-unstable.

πŸ“Œ Version Pinning

The devShell.package.pinned list lets you pin a package to an exact version, resolved through nix-versions and locked into the generated flake. This is the recommended way to control language runtimes such as go, node, or python down to the patch level.

Workflow:

  1. Find a candidate version:

    lnix search go -v '>=1.21,<1.22'
  2. Add the resolved name and version to lazynix.yaml:

    devShell:
      package:
        stable:
          - name: python312
        pinned:
          - name: go
            version: "1.21.13"
  3. Run lnix develop (or run/test). LazyNix asks nix-versions for the exact nixpkgs commit that ships the requested version, then embeds that commit into the generated flake.nix as its input URL. Subsequent runs reuse the commit encoded in flake.nix and skip the resolver call β€” the flake.nix is the cache. lazynix.yaml is never touched.

πŸ”€ Shell Aliases

Alias definitions can be sourced from external files via devShell.shellAlias. Each entry is a path β€” relative, absolute, or ~-prefixed β€” to a shell script whose alias definitions will be loaded into the dev shell.

devShell:
  allowUnfree: true
  package:
    stable:
      - name: bash
  shellAlias:
    - ./aliases.sh
    - ~/.bash_aliases
    - /etc/aliases.sh

Relative paths are resolved against $PWD; ~ is expanded to the user's home directory; absolute paths are used as-is.

🧩 Tasks and Tests

Two related sections describe reusable commands that run inside the dev shell:

  • devShell.test β€” a flat list of shell commands. lnix test runs them in order and stops on the first failure. Use this for smoke tests you want to run without remembering a task name.
  • devShell.task β€” a named map of workflows, each with an optional description and a list of commands. Run a task with lnix task <name>. Any trailing arguments are substituted into the {{.CLI_ARGS}} placeholder inside the task's commands, so a single task can accept variable arguments.
devShell:
  allowUnfree: true
  package:
    stable:
      - name: python312
      - name: uv

  task:
    fmt:
      description: "Format Python sources"
      commands:
        - "uv run ruff format ."
    review:
      description: "Run a specific pytest, forwarded via CLI_ARGS"
      commands:
        - "uv run pytest {{.CLI_ARGS}}"

  test:
    - "uv run pytest"
    - "uv run mypy src/"

Example invocations:

lnix task fmt
lnix task review tests/test_api.py::test_auth   # expands into {{.CLI_ARGS}}
lnix test

Design Philosophy

βœ… What LazyNix Does

  • Reproducible Development Environments: Consistent, shareable dev setups
  • Simple Configuration Interface: YAML instead of Nix expressions

❌ What LazyNix Doesn't Do

  • Cover All Nix Features: No build definitions, overlays, or modules
  • Replace Nix: It's a thin layer on top of Nix flakes
  • Manage System Configuration: Only development environments

Migration from LazyNix to Pure Nix

When you need advanced Nix features, migration is seamless. LazyNix generates a standard flake.nix, so:

  1. βš™οΈ Run lnix generate to produce the latest flake.nix from lazynix.yaml
  2. πŸ—‘οΈ Delete lazynix.yaml
  3. ✏️ Continue editing flake.nix directly

That's all! Your development environment keeps working without any changes.

Contribution

We welcome contributions!

License

This project is licensed under the MIT License.

About

we provide reproduce environments for all developers

Resources

Stars

25 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages