init ruler

Signed-off-by: Dmytro Stanchiev <git@dmytros.dev>
This commit is contained in:
2026-04-06 20:48:07 -04:00
parent 4db02f47bf
commit 206f028fdf
12 changed files with 1201 additions and 0 deletions

287
.ruler/09-NIX.md Normal file
View 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`.