Skip to main content
Prefer the most ephemeral install that still meets the tool’s real requirements. Promote upward only when running on demand is too slow.
Across the four Nix repos and the ephemeral options on top, every tool has exactly one correct home. The matrix below is ordered the same way you should read it: always-on at the top, ephemeral at the bottom. Work upward from the bottom and stop at the first row that actually satisfies the tool’s needs.

Placement decision matrix

Package categoryCorrect homeMechanism
Core bootstrapping (git, gnupg, vim)nix-darwinenvironment.systemPackages
macOS-only system tools (mas, mactop)nix-darwinenvironment.systemPackages
macOS system-level C libs (sox, portaudio)nix-darwinenvironment.systemPackages
GUI apps unavailable in nixpkgsnix-darwinhomebrew.casks
CLI tools unavailable in nixpkgs or version-pinnednix-darwinhomebrew.brews
AI tools, MCP servers, speech / audio stacknix-aihome.packages
Host-specific AI provider adaptersconsumer-specific flakeHome Manager module
User dev tools, shell config, linters, credentialsnix-homehome.packages
Pre-commit hook tools (must be on PATH globally)nix-homehome.packages
Project-specific toolchainsnix-devenvimportable module
Language-specific testers, CI linters (bats, actionlint)nix-devenvshell buildInputs
Occasional one-off tools (diagramming, previews)ephemeralnix run nixpkgs#<pkg>
npm-backed CLI toolsephemeralbunx <pkg>@version
Python CLI toolsephemeraluvx <pkg>

Critical rules

homebrew.brews stays in nix-darwin. Home-manager (nix-ai, nix-home) cannot declare Homebrew formulas — homebrew.* is a nix-darwin option only. Group AI-adjacent brew tools with a # AI tools comment block for logical clarity, not a repo move. Pre-commit hooks with language: system require the tool on PATH. If a tool is used as a language: system pre-commit hook, it must stay in nix-home’s home.packages even if it feels project-specific (lychee, for example). IDE linters stay global. Tools like pyright that IDEs invoke as background processes must be in home.packages (always on PATH). Moving them to a project devenv shell breaks editor integration because IDEs activate the system environment, not a project shell. Provider adapters follow the endpoint. If an AI CLI is generally useful, package the CLI in nix-ai. If the config bakes in a private gateway URL, model aliases, or token source, put that adapter module in the consuming host or workstation flake instead. The public package stays reusable; the private topology stays out of shared package docs.

On-demand patterns

# Zero-install ephemeral runs (like bunx but for Nix):
nix run nixpkgs#d2 -- input.d2 output.svg
nix run nixpkgs#mermaid-cli -- -i input.mmd -o output.svg
nix run nixpkgs#python3Packages.grip -- README.md

# Enter a project shell with tools available:
nix develop github:JacobPEvans/nix-devenv?dir=shells/ansible
nix develop github:JacobPEvans/nix-devenv?dir=shells/kubernetes

# Use uvx for Python CLIs (preferred over pipx in Nix):
uvx aider-chat
uvx ruff check .

Repo responsibilities

RepoScope
nix-darwinmacOS system config: system packages, Homebrew, security, GUI apps, LaunchDaemons
nix-aiAI tool ecosystem: Claude Code, Gemini, MCP servers, whisper stack, AI CLIs
nix-homeUser dev environment: dev tools, shell config, git, linters, credentials
nix-devenvReusable project shells and importable modules: per-language toolchains
Full package lists live in each repo — this page carries placement logic only. Adding a repo to this set means updating the matrix categories above and the AGENTS.md of every consumer repo that references the rule.

Where to go next

Nix Ecosystem overview

The four-repo split and how the layers compose at activation time.

nix-darwin

macOS system config — where homebrew.brews legitimately lives.

nix-ai

AI tool ecosystem — what home.packages carries in the AI tier.

nix-devenv

Reusable per-language project shells and importable modules.