nixy - Simple Declarative Nix Package Management

Reproducible Nix packages, simple commands. Install packages with a single command, sync them across all your machines.
nixy manages your Nix packages through a declarative flake.nix. Unlike nix profile which lacks built-in reproducibility, nixy ensures the same packages and versions on every machine. Written in Rust for reliability and performance.
Motivation
For users frustrated with Homebrew, asdf, or similar tools who want:
- Reproducible environments across machines (not just "it works on my machine")
- Atomic upgrades that never leave your system in a broken state
- A single lockfile for all packages (no more version drift)
nixy is a package management layer on top of Nix. It doesn't replace Nix's full capabilities (dev shells, builds, NixOS) - it focuses solely on managing globally installed packages, like Homebrew does.
What nixy gives you:
- Simple commands:
nixy install,nixy uninstall,nixy upgrade - True reproducibility:
flake.nix+flake.lock= identical environments everywhere - Multiple profiles: Separate package sets for work, personal, projects
- No lock-in: Plain Nix underneath - eject anytime
- Cross-platform: Same workflow on macOS and Linux
What nixy is NOT:
- A replacement for Home Manager or NixOS
- A development environment tool (use
nix developfor that) - A build system
If you want Homebrew's simplicity with Nix's reproducibility for your CLI tools, nixy is for you.
How it works
nixy uses plain Nix features - no Home Manager, no NixOS, no complex setup. Your packages are defined in flake.nix at ~/.config/nixy/profiles/<name>/, built with nix build.
nixy is purely declarative - your flake.nix is the single source of truth. Unlike nix profile which maintains mutable state, nixy uses nix build --out-link to create a symlink (~/.local/state/nixy/env) pointing to your built environment. This means:
- No hidden profile state to get out of sync
- What's in
flake.nixis exactly what's installed - Easy to understand, debug, and version control
nixy edits the flake.nix and runs standard nix commands. The flake.nix it generates is plain Nix - you can read it, edit it manually, or use nix commands directly anytime.
nixy and nix profile
nixy is not a replacement for nix profile - it's a complement that adds reproducibility.
nix profile is great for quick, single-machine package management. nixy adds a declarative layer on top of Nix for when you need:
- A unified lockfile: All packages pinned to the same nixpkgs version
- Easy sync: Copy
flake.nixto a new machine, runnixy sync, done - Version-controlled config:
flake.nixis designed for git
nixy and nix profile use separate paths (~/.local/state/nixy/env vs ~/.nix-profile) and don't interfere with each other. Use nix profile for quick experiments, nixy for your reproducible base environment - or use both together.
Quick Start
nixy uses profiles to organize packages. A "default" profile is created automatically on first use. You can create additional profiles later for different contexts (work, personal, projects).
1. Install Nix (if you haven't)
|
2. Install nixy
Quick install (recommended):
|
This will try (in order): pre-built binary, cargo install, or nix build.
With cargo:
With nix:
From source:
3. Set up your shell
Add to your shell config (.bashrc, .zshrc, etc.):
For fish, add to ~/.config/fish/config.fish:
nixy config fish | source
4. Start installing packages
Packages are installed globally and available in all terminal sessions.
Commands
| Command | Description |
|---|---|
nixy install <pkg> |
Install a package from nixpkgs |
nixy install --from <flake> <pkg> |
Install from a flake (registry name or URL) |
nixy uninstall <pkg> |
Uninstall a package |
nixy list |
List packages in flake.nix |
nixy search <query> |
Search for packages |
nixy upgrade [input...] |
Upgrade all inputs or specific ones |
nixy sync |
Build environment from flake.nix (for new machines) |
nixy gc |
Clean up old package versions |
nixy config <shell> |
Output shell config (for PATH setup) |
nixy version |
Show nixy version |
nixy profile |
Show current profile |
nixy profile switch <name> |
Switch to a different profile |
nixy profile switch -c <name> |
Create and switch to a new profile |
nixy profile list |
List all profiles |
nixy profile delete <name> |
Delete a profile (requires --force) |
Multiple Profiles
Maintain separate package sets for different contexts (work, personal, projects):
Each profile has its own flake.nix at ~/.config/nixy/profiles/<name>/. Switching profiles rebuilds the environment symlink to point to that profile's packages.
Use cases:
- Work vs Personal: Keep work tools separate from personal apps
- Client projects: Different toolchains for different clients
- Experimentation: Try new packages without affecting your main setup
Managing profiles with dotfiles:
# Back up all profiles to dotfiles
# On a new machine, restore and sync
Sync Across Machines
Your package list is just a text file. Back it up, version control it, or sync it with dotfiles:
# Back up your package list (default profile)
# On a new machine:
Same packages, same versions, on every machine.
FAQ
How do I find the right package name?
Use nixy search <keyword>. Package names sometimes differ from what you expect (e.g., ripgrep not rg).
Where are packages actually installed?
In the Nix store (/nix/store/). nixy builds a combined environment and creates a symlink at ~/.local/state/nixy/env pointing to it. The nixy config command sets up your PATH to include this location.
Can I edit the flake.nix manually? Yes! nixy provides custom markers where you can add your own inputs, packages, and paths that will be preserved during regeneration:
# [nixy:custom-inputs]
my-overlay.url = "github:user/my-overlay";
# [/nixy:custom-inputs]
Any content outside these markers will be overwritten when nixy regenerates the flake. For heavy customization, see "Customizing flake.nix" in the Appendix.
How do I update nixy?
Rebuild from source or run cargo install --git https://github.com/yusukeshib/nixy.git --force.
How do I uninstall nixy?
Delete the nixy binary (typically /usr/local/bin/nixy or ~/.cargo/bin/nixy). Your flake.nix files remain and work with standard nix commands.
Why not use nix profile directly?
nix profile lacks built-in reproducibility - there's no official way to export your packages and recreate the same environment on another machine. nixy uses flake.nix as the source of truth, which can be copied, version-controlled, and shared.
Appendix
Customizing flake.nix
nixy provides custom markers where you can add your own content that will be preserved when nixy regenerates the flake:
Custom inputs - Add your own flake inputs:
# [nixy:custom-inputs]
my-overlay.url = "github:user/my-overlay";
home-manager.url = "github:nix-community/home-manager";
# [/nixy:custom-inputs]
Custom packages - Add custom package definitions:
# [nixy:custom-packages]
my-tool = pkgs.writeShellScriptBin "my-tool" ''echo "Hello"'';
patched-app = pkgs.app.overrideAttrs { ... };
# [/nixy:custom-packages]
Custom paths - Add extra paths to the buildEnv:
# [nixy:custom-paths]
my-tool
patched-app
# [/nixy:custom-paths]
If you edit content outside these markers, nixy will warn you before overwriting:
Warning: flake.nix has modifications outside nixy markers.
Use --force to proceed (custom changes will be lost).
For Existing Nix Users
If you already manage your own flake.nix and want to use nixy's package list, you can import it:
{
inputs.nixy.url = "path:~/.config/nixy";
outputs = { self, nixpkgs, nixy }: {
# nixy.packages.<system>.default is a buildEnv with all nixy packages
# You can use it as a dependency or merge it with your own environment
};
}
This way, nixy manages your package list while you maintain full control of your flake.
Coexistence with nix profile
nixy and nix profile use separate paths and don't conflict:
- nixy:
~/.local/state/nixy/env/bin - nix profile:
~/.nix-profile/bin
If you have both in your PATH, the one listed first takes precedence for packages installed in both. You can use both tools for different purposes.
Installing from External Flakes
Install packages from any flake using --from:
# Direct flake URL
# Or use nix registry names
The flake is added as a custom input to your flake.nix, and the full URL is stored for reproducibility. This works with any flake that exports packages.
Custom Package Definitions
Install packages from custom nix files:
Format for my-package.nix:
{
name = "my-package";
inputs = { overlay-name.url = "github:user/repo"; };
overlay = "overlay-name.overlays.default";
packageExpr = "pkgs.my-package";
}
Config Locations
| Path | Description |
|---|---|
~/.config/nixy/profiles/<name>/flake.nix |
Profile packages |
~/.config/nixy/active |
Current active profile name |
~/.config/nixy/profiles/<name>/packages/ |
Custom package definitions for profile |
~/.local/state/nixy/env |
Symlink to built environment (add bin/ to PATH) |
~/.config/nixy/flake.nix |
Legacy location (auto-migrated to default profile) |
Environment Variables
| Variable | Default | Description |
|---|---|---|
NIXY_CONFIG_DIR |
~/.config/nixy |
Location of global flake.nix |
NIXY_ENV |
~/.local/state/nixy/env |
Symlink to built environment |
Limitations
- Package names use Nix naming (search with
nixy searchto find exact names) - No GUI app support (like Homebrew Cask) yet
- Requires Nix with flakes enabled (the Determinate installer enables this by default)
Development
# Build
# Run tests
# Run with debug output
RUST_LOG=debug
License
MIT