10 KiB
Nix Tool Preference Directive
Core Instruction
Always prioritize Nix-based tools (nix_nix, nix_nix_versions, nix-shell, nix run, etc.) for querying packages, versions, options, environments, and reproducible workflows whenever relevant.
Nix ensures declarative, isolated, reproducible results. Use these before generic searches, manual installs, or distro tools.
Trigger Conditions
- Package discovery/version info:
nix_nixornix_nix_versions. - Environment setup:
nix-shell,nix develop. - NixOS/Home-manager config:
nix_nix action=options. - Reproducibility/CI: Nix flakes/builds.
Fallback: Native tools if Nix unsuitable; note Nix alternative.
Specific Tools
nix_nix - Query NixOS, Home Manager, Darwin, flakes, and more
| Parameter | Description |
|---|---|
action |
search, info, stats, options, channels, flake-inputs, cache |
source |
nixos, home-manager, darwin, flakes, flakehub, nixvim, wiki, nix-dev, noogle, nixhub |
query |
Search term, name, or prefix |
type |
packages, options, programs, list, ls, read |
channel |
unstable, stable, 25.05 |
limit |
1-100 (or 1-2000 for flake-inputs read) |
nix_nix_versions - Get package version history from NixHub.io
| Parameter | Description |
|---|---|
package |
Package name |
version |
Specific version to find (optional) |
limit |
1-50 |
Key Use-Cases
| Use-Case | Tool/Command | Example |
|---|---|---|
| Search packages | nix_nix |
nix_nix action=search query=ripgrep source=nixos |
| Find options | nix_nix |
nix_nix action=options query=services.nginx source=nixos |
| Flake inputs | nix_nix |
nix_nix action=flake-inputs query=read source=flakes |
| Version history | nix_nix_versions |
nix_nix_versions package=nodejs |
| Temporary tool | nix run |
nix run nixpkgs#ripgrep -- search_term |
| Project env | nix develop |
Loads flake.nix deps |
| Pure shell | nix-shell --pure |
Isolated env |
Agent Integration
- Query packages/options first: Use
nix_nixbefore assuming availability. - Pin versions: Check
nix_nix_versionsfor stable choices. - Generate configs: Create
shell.nix/flakes based on queries. - Verify:
nix --versionif needed.
Example shell.nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [ nodejs_20 python311 ripgrep ];
}
Flake Creation for Packages
Guideline: Create flake.nix for building packages, reproducible dev shells, multi-language support, and cross-platform compatibility.
Triggers:
- Building language-specific packages (e.g., Rust via
crane). - Configurable dev environments (Rust/Node/Go/etc.).
- Use
nix_nixfirst: e.g.,nix_nix action=search query=crane source=flakesfor libs.
Key Structure:
- inputs:
nixpkgs,flake-parts, lang tools (crane,fenix, etc.). - outputs:
packages.default,devShells.defaultwithshellHook. - Multi-system:
x86_64-linux,aarch64-darwin, etc.
Example flake.nix (Rust MCP server + configurable dev envs via dev-environments):
{
description = "Rust documentation MCP server";
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
dev-environments.url = "github:Govcraft/dev-environments";
crane = {
url = "github:ipetkov/crane";
};
};
outputs =
inputs@{ flake-parts, nixpkgs, crane, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [
inputs.dev-environments.flakeModules.rust
inputs.dev-environments.flakeModules.golang
inputs.dev-environments.flakeModules.node
inputs.dev-environments.flakeModules.typst
];
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
"x86_64-darwin"
];
perSystem =
{
config,
self',
inputs',
pkgs,
system,
...
}:
let
craneLib = inputs.crane.mkLib pkgs;
# Common arguments shared between all builds
commonArgs = {
src = craneLib.cleanCargoSource ./.;
buildInputs = with pkgs; [
openssl
] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
# Additional darwin specific inputs
pkgs.darwin.apple_sdk.frameworks.Security
pkgs.darwin.apple_sdk.frameworks.SystemConfiguration
];
nativeBuildInputs = with pkgs; [
pkg-config
perl
];
};
# Build *just* the cargo dependencies
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
# Build the actual crate itself
rustdocs-mcp-server = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
});
in
{
# Add the package
packages = {
default = rustdocs-mcp-server;
rustdocs-mcp-server = rustdocs-mcp-server;
};
# Golang Development Environment Options
# ----------------------------------
# enable: boolean - Enable/disable the Golang environment
# goVersion: enum - Go toolchain version ("1.18", "1.19", "1.20", "1.21, "1.22", "1.23") (default: "1.23")
# withTools: list of strings - Additional Go tools to include (e.g., "golint", "gopls")
# extraPackages: list of packages - Additional packages to include
go-dev = {
# enable = true;
# goVersion = "1.23";
# withTools = [ "gopls" "golint" ];
# extraPackages = [ ];
};
# Rust Development Environment Options
# ----------------------------------
# enable: boolean - Enable/disable the Rust environment
# rustVersion: enum - Rust toolchain ("stable", "beta", "nightly") (default: "stable")
# withTools: list of strings - Additional Rust tools to include (converted to cargo-*)
# extraPackages: list of packages - Additional packages to include
# ide.type: enum - IDE preference ("rust-rover", "vscode", "none") (default: "none")
rust-dev = {
enable = true;
rustVersion = "stable";
# Example configuration:
# withTools = [ ]; # Will be prefixed with cargo-
extraPackages = [ pkgs.openssl pkgs.openssl.dev pkgs.pkg-config ]; # Add openssl libs, dev libs, and pkg-config
# ide.type = "none";
};
# Node.js Development Environment Options
# -------------------------------------
# enable: boolean - Enable/disable the Node environment
# nodeVersion: string - Version of Node.js to use (default: "20")
# withTools: list of packages - Global tools to include (default: ["typescript" "yarn" "pnpm"])
# extraPackages: list of packages - Additional packages to include
# ide.type: enum - IDE preference ("vscode", "webstorm", "none") (default: "none")
node-dev = {
# Example configuration:
# enable = true;
# nodeVersion = "20";
# withTools = [ "typescript" "yarn" "pnpm" ];
# extraPackages = [ ];
# ide.type = "none";
};
typst-dev = {
# Example configuration:
# enable = true;
# withTools = [ "typst-fmt" "typst-lsp" ];
# extraPackages = [ ];
# ide.type = "none";
};
# Create the combined shell
devShells.default = pkgs.mkShell {
buildInputs = nixpkgs.lib.flatten (nixpkgs.lib.attrValues config.env-packages ++ [ ]);
# Combine existing hooks with new exports for OpenSSL
shellHook = ''
${nixpkgs.lib.concatStringsSep "\n" (nixpkgs.lib.attrValues config.env-hooks)}
# Export paths for openssl-sys build script
export OPENSSL_DIR="${pkgs.openssl.out}"
export OPENSSL_LIB_DIR="${pkgs.openssl.out}/lib"
export OPENSSL_INCLUDE_DIR="${pkgs.openssl.dev}/include"
# Ensure pkg-config can find the openssl .pc file
export PKG_CONFIG_PATH="${pkgs.openssl.dev}/lib/pkgconfig:${pkgs.pkg-config}/lib/pkgconfig:$PKG_CONFIG_PATH"
# Debug: List contents of OpenSSL lib directory to verify
echo "OpenSSL lib directory contents:"
ls -la ${pkgs.openssl.out}/lib || echo "Failed to list OpenSSL lib directory"
echo ">>> OpenSSL environment variables set by shellHook <<<"
'';
};
# Add app for `nix run`
apps = {
default = {
type = "app";
program = "${rustdocs-mcp-server}/bin/rustdocs_mcp_server";
};
};
};
};
}
Usage:
nix developfor dev shell.nix buildfor package.nix runfor app.
uv2nix for Python Projects
When to use: Python projects with uv.lock - handles complex dependencies not in nixpkgs.
Inputs needed:
pyproject-nix.url = "github:pyproject-nix/pyproject.nix";
uv2nix.url = "github:pyproject-nix/uv2nix";
pyproject-build-systems.url = "github:pyproject-nix/build-system-pkgs";
Critical API details:
- Function is
loadWorkspace, NOTloadUvWorkspace(despite tool name) - Use
python = pkgs.python313, NOTinherit (pkgs) python313 - Creates virtual environments via
mkVirtualEnv, not traditional derivations
Overlay composition order (must be exact):
pyproject-build-systems.overlays.default- Project overlay from
workspace.mkPyprojectOverlay - Custom
pyprojectOverrides
Pattern:
workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; };
overlay = workspace.mkPyprojectOverlay { sourcePreference = "wheel"; };
pythonSet = (pkgs.callPackage pyproject-nix.build.packages {
python = pkgs.python313;
}).overrideScope (lib.composeManyExtensions [
pyproject-build-systems.overlays.default
overlay
pyprojectOverrides
]);
in {
packages.default = pythonSet.mkVirtualEnv "env-name" workspace.deps.default;
}
Output: Virtual env with executables in result/bin/<package-name>.
Prohibitions
- Avoid non-reproducible installs (e.g.,
apt). - Avoid non-declarative package management (e.g.,
nix-env -iA nixos.ripgrepornix profile add nixpkgs#ripgrep) - Always check Nix tools first.
Next: Query a package with nix_nix or generate shell.nix.