287
.ruler/09-NIX.md
Normal file
287
.ruler/09-NIX.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# 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_nix` or `nix_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_nix` before assuming availability.
|
||||
- **Pin versions**: Check `nix_nix_versions` for stable choices.
|
||||
- **Generate configs**: Create `shell.nix`/flakes based on queries.
|
||||
- **Verify**: `nix --version` if needed.
|
||||
|
||||
## Example `shell.nix`
|
||||
|
||||
````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_nix` first: e.g., `nix_nix action=search query=crane source=flakes` for libs.
|
||||
|
||||
**Key Structure**:
|
||||
- **inputs**: `nixpkgs`, `flake-parts`, lang tools (`crane`, `fenix`, etc.).
|
||||
- **outputs**: `packages.default`, `devShells.default` with `shellHook`.
|
||||
- Multi-system: `x86_64-linux`, `aarch64-darwin`, etc.
|
||||
|
||||
**Example `flake.nix`** (Rust MCP server + configurable dev envs via `dev-environments`):
|
||||
|
||||
````nix
|
||||
{
|
||||
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 develop` for dev shell.
|
||||
- `nix build` for package.
|
||||
- `nix run` for app.
|
||||
|
||||
## uv2nix for Python Projects
|
||||
|
||||
**When to use**: Python projects with `uv.lock` - handles complex dependencies not in nixpkgs.
|
||||
|
||||
**Inputs needed**:
|
||||
```nix
|
||||
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`, NOT `loadUvWorkspace` (despite tool name)
|
||||
- Use `python = pkgs.python313`, NOT `inherit (pkgs) python313`
|
||||
- Creates virtual environments via `mkVirtualEnv`, not traditional derivations
|
||||
|
||||
**Overlay composition order** (must be exact):
|
||||
1. `pyproject-build-systems.overlays.default`
|
||||
2. Project overlay from `workspace.mkPyprojectOverlay`
|
||||
3. Custom `pyprojectOverrides`
|
||||
|
||||
**Pattern**:
|
||||
```nix
|
||||
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.ripgrep` or `nix profile add nixpkgs#ripgrep`)
|
||||
- Always check Nix tools first.
|
||||
|
||||
**Next**: Query a package with `nix_nix` or generate `shell.nix`.
|
||||
Reference in New Issue
Block a user