Commit eabf51348d8d

Vincent Demeester <vincent@sbr.pm>
2026-02-02 11:59:45
feat: add pi-coding-agent config and adopt AGENTS.md standard
Restructure project instructions: - AGENTS.md is now the source of truth (agent-agnostic) - CLAUDE.md uses @AGENTS.md file include for Claude Code Add pi-coding-agent configuration: - settings.json: Vertex AI provider, Claude Sonnet 4 model - extensions/claude-hooks.ts: Wrapper for Go hook binaries - AGENTS.md: Global agent instructions - README.md: Documentation Update dots/Makefile with pi-agent target. Pi is a minimal terminal coding agent from badlogic/pi-mono that supports the same SKILL.md format as Claude Code. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 57fea76
dots/.config/pi/agent/extensions/claude-hooks.ts
@@ -0,0 +1,149 @@
+/**
+ * Pi Extension: Claude Code Hooks Wrapper
+ *
+ * Wraps the Go-based Claude Code hook binaries (claude-hooks-*) to provide
+ * consistent hook behavior across AI coding agents.
+ *
+ * Events mapped:
+ * - session_start -> claude-hooks-initialize-session
+ * - session_shutdown -> claude-hooks-save-session
+ * - tool_call -> claude-hooks-validate-git-push (PreToolUse equivalent)
+ * - tool_result -> claude-hooks-capture-tool-output, claude-hooks-update-terminal-title
+ */
+
+import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
+import { execSync, spawn } from "child_process";
+
+// Track if session has been initialized
+let sessionInitialized = false;
+
+// Convert Pi event format to Claude Code JSON format
+function toClaudePreToolUse(event: { toolName: string; input: any }): string {
+  return JSON.stringify({
+    tool_name: capitalize(event.toolName),
+    tool_input: event.input || {},
+    conversation_id: "pi-session",
+  });
+}
+
+function toClaudePostToolUse(event: {
+  toolName: string;
+  input: any;
+  content?: any[];
+  isError?: boolean;
+}): string {
+  return JSON.stringify({
+    tool_name: capitalize(event.toolName),
+    tool_input: event.input || {},
+    tool_response: {
+      content: event.content || [],
+      is_error: event.isError || false,
+    },
+    conversation_id: "pi-session",
+  });
+}
+
+function capitalize(s: string): string {
+  return s.charAt(0).toUpperCase() + s.slice(1);
+}
+
+// Run a Claude hook binary with JSON input
+async function runHook(
+  binary: string,
+  jsonInput?: string
+): Promise<{ exitCode: number; stdout: string; stderr: string }> {
+  return new Promise((resolve) => {
+    const proc = spawn(binary, [], {
+      shell: true,
+      stdio: ["pipe", "pipe", "pipe"],
+    });
+
+    let stdout = "";
+    let stderr = "";
+
+    proc.stdout.on("data", (data) => (stdout += data.toString()));
+    proc.stderr.on("data", (data) => (stderr += data.toString()));
+
+    if (jsonInput) {
+      proc.stdin.write(jsonInput);
+      proc.stdin.end();
+    } else {
+      proc.stdin.end();
+    }
+
+    proc.on("close", (code) => {
+      resolve({ exitCode: code ?? 0, stdout, stderr });
+    });
+
+    proc.on("error", () => {
+      resolve({ exitCode: 1, stdout: "", stderr: `Failed to spawn ${binary}` });
+    });
+  });
+}
+
+// Check if a binary exists in PATH
+function binaryExists(name: string): boolean {
+  try {
+    execSync(`which ${name}`, { stdio: "ignore" });
+    return true;
+  } catch {
+    return false;
+  }
+}
+
+export default function (pi: ExtensionAPI) {
+  // Session initialization
+  pi.on("session_start", async (_event, ctx) => {
+    if (sessionInitialized) return;
+    sessionInitialized = true;
+
+    if (binaryExists("claude-hooks-initialize-session")) {
+      const result = await runHook("claude-hooks-initialize-session");
+      if (result.stderr && result.exitCode === 0) {
+        ctx.ui.notify(result.stderr.trim(), "info");
+      }
+    }
+  });
+
+  // Session shutdown
+  pi.on("session_shutdown", async (_event, _ctx) => {
+    if (binaryExists("claude-hooks-save-session")) {
+      await runHook("claude-hooks-save-session");
+    }
+    sessionInitialized = false;
+  });
+
+  // Pre-tool-use validation (can block)
+  pi.on("tool_call", async (event, _ctx) => {
+    // Run validate-git-push for bash commands
+    if (
+      event.toolName.toLowerCase() === "bash" &&
+      binaryExists("claude-hooks-validate-git-push")
+    ) {
+      const jsonInput = toClaudePreToolUse(event);
+      const result = await runHook("claude-hooks-validate-git-push", jsonInput);
+
+      if (result.exitCode !== 0) {
+        return {
+          block: true,
+          reason: result.stderr.trim() || "Command blocked by validate-git-push hook",
+        };
+      }
+    }
+
+    return undefined;
+  });
+
+  // Post-tool-use capture
+  pi.on("tool_result", async (event, _ctx) => {
+    const jsonInput = toClaudePostToolUse(event);
+
+    // Run hooks in parallel
+    const hooks = [
+      "claude-hooks-capture-tool-output",
+      "claude-hooks-update-terminal-title",
+    ].filter(binaryExists);
+
+    await Promise.allSettled(hooks.map((hook) => runHook(hook, jsonInput)));
+  });
+}
dots/.config/pi/agent/AGENTS.md
@@ -0,0 +1,42 @@
+# Global Pi Agent Instructions
+
+This file is loaded by pi-coding-agent for all projects.
+
+## Core Principles
+
+Apply the same principles as defined in Claude Code skills:
+
+1. **Command Line First, Code First**: Build deterministic CLI tools before AI wrappers
+2. **Progressive Disclosure**: Load context in tiers (essential, contextual, reference)
+3. **Structured Communication**: Get to the point, use scannable formatting
+4. **Honesty and Uncertainty**: Say "I don't know" when uncertain
+
+## Git Safety
+
+- **ALWAYS use explicit refspecs for git push**: `git push origin branch:branch`
+- **NEVER use bare `git push`** - branch tracking can push to unexpected branches
+- **Before pushing, verify the tracking branch** with `git status`
+
+## Skills
+
+Skills from `~/.config/claude/skills/` are compatible with pi. Key skills:
+
+- **CORE**: Operating principles and behaviors
+- **Git**: Version control workflows
+- **Nix**: NixOS configuration
+- **Org**: Note-taking, journaling, TODOs
+- **Homelab**: NixOS infrastructure
+
+## Stack Preferences
+
+- **Package managers:** uv for Python (NOT pip)
+- **Markdown over HTML/XML:** Use markdown formatting
+- **Analysis vs Action:** If asked to analyze, do analysis only
+
+## Response Patterns
+
+1. **Understand**: Clarify the task and requirements
+2. **Plan**: Break down complex tasks
+3. **Execute**: Implement systematically
+4. **Verify**: Test and validate results
+5. **Document**: Capture decisions and outcomes
dots/.config/pi/agent/README.md
@@ -0,0 +1,66 @@
+# Pi Coding Agent Configuration
+
+Configuration for [pi-coding-agent](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent),
+a minimal terminal coding agent.
+
+## Structure
+
+```
+~/.config/pi/agent/
+├── settings.json    # Global settings (provider, model, thinking)
+├── extensions/      # TypeScript extensions
+│   └── claude-hooks.ts  # Wrapper for Claude Code hook binaries
+├── skills/          # Skills directory (SKILL.md format)
+└── README.md
+```
+
+## Extensions
+
+### claude-hooks.ts
+
+Wraps the Go-based Claude Code hook binaries to provide consistent hook behavior:
+
+| Pi Event | Claude Hook Binary | Purpose |
+|----------|-------------------|---------|
+| session_start | claude-hooks-initialize-session | Session initialization |
+| session_shutdown | claude-hooks-save-session | Save session summary |
+| tool_call | claude-hooks-validate-git-push | Block unsafe git push |
+| tool_result | claude-hooks-capture-tool-output | Capture tool output |
+| tool_result | claude-hooks-update-terminal-title | Update terminal title |
+
+## Skills
+
+Pi is compatible with Claude Code skills format. To use Claude skills with pi:
+
+```bash
+# Option 1: Symlink individual skills
+ln -s ~/.config/claude/skills/Git ~/.config/pi/agent/skills/Git
+ln -s ~/.config/claude/skills/Nix ~/.config/pi/agent/skills/Nix
+
+# Option 2: Symlink entire skills directory
+rm -rf ~/.config/pi/agent/skills
+ln -s ~/.config/claude/skills ~/.config/pi/agent/skills
+```
+
+## Settings
+
+The `settings.json` configures:
+
+- **defaultProvider**: LLM provider (vertex, anthropic, openai, etc.)
+- **defaultModel**: Model to use
+- **enabledModels**: Models available for cycling (Ctrl+P)
+- **defaultThinkingLevel**: off, low, medium, high, xhigh
+- **steeringMode**: Message delivery control
+
+## Usage
+
+```bash
+# Start pi in current directory
+pi
+
+# Start with specific prompt
+pi "explain this codebase"
+
+# Use a specific skill
+pi "/Git:commit"
+```
dots/.config/pi/agent/settings.json
@@ -0,0 +1,13 @@
+{
+  "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/settings-schema.json",
+  "defaultProvider": "vertex",
+  "defaultModel": "claude-sonnet-4-20250514",
+  "enabledModels": [
+    "claude-sonnet-4-*",
+    "claude-opus-4-*",
+    "gemini-2.5-*"
+  ],
+  "defaultThinkingLevel": "low",
+  "steeringMode": "one-at-a-time",
+  "followUpMode": "one-at-a-time"
+}
dots/Makefile
@@ -53,10 +53,11 @@ lazypr : ~/.config/lazypr/config.toml
 all += gh-news
 gh-news : ~/.config/gh-news/config.toml
 
-all += git-template copilot-hooks opencode-plugin
+all += git-template copilot-hooks opencode-plugin pi-agent
 git-template : ~/.config/git/template
 copilot-hooks : ~/.config/copilot-hooks
 opencode-plugin : ~/.config/opencode/plugin
+pi-agent : ~/.config/pi/agent
 
 # Backward compatibility: symlink ~/.claude to ~/.config/claude
 ~/.claude : force
AGENTS.md
@@ -0,0 +1,199 @@
+# AGENTS.md
+
+This file provides guidance to AI coding agents when working with code in this repository.
+
+## Repository Overview
+
+This is a comprehensive NixOS and home-manager monorepo for managing personal infrastructure, system configurations, and custom tools. The repository uses Nix flakes as the primary interface for building and deploying configurations across multiple machines.
+
+## Architecture
+
+### Core Structure
+
+The repository follows a modular architecture centered around `flake.nix`:
+
+- **`/lib`**: Core library functions including `mkHost`, `mkHome`, and `mkSystemManager` for generating NixOS, home-manager, and system-manager configurations
+- **`globals.nix`**: Global configuration including machine definitions (network, SSH, syncthing), DNS zones, and VPN settings
+- **`/systems`**: NixOS system configurations, organized by hostname with a shared `/systems/common` directory containing base, desktop, hardware, programs, services, and users modules
+- **`/home`**: Home-manager configurations with `/home/common` containing desktop, dev, services, and shell modules
+- **`/pkgs`**: Custom Nix packages that are exposed via overlays
+- **`/tools`**: Source code for custom tools (battery-monitor, emacs configuration)
+- **`/modules`**: Custom NixOS modules (wireguard-client, wireguard-server, govanityurl, gosmee)
+- **`/overlays`**: Nix overlays for additions, modifications, and unstable packages
+- **`/keyboards`**: Hardware keyboard configurations (ZMK for Corne, QMK for Moonlander, Kanata software remapper)
+- **`/imperative`**: Idempotent configuration scripts for non-NixOS managed systems, organized by hostname (e.g., `/imperative/nagoya/apply.sh`). These scripts are meant to be run repeatedly to maintain system state on hosts that cannot use NixOS.
+
+### Host Configuration Pattern
+
+Each host has a dedicated directory in `/systems/<hostname>` containing:
+- `boot.nix`: Boot configuration (bootloader, initrd, kernel modules)
+- `hardware.nix`: Hardware-specific settings (hardware imports, filesystem mounts)
+- `extra.nix` (optional): Additional host-specific configuration
+- `home.nix` (optional): Host-specific home-manager configuration
+
+### System Types
+
+- **Unstable systems** (kyushu, aomi, sakhalin, foobar): Use `nixpkgs` (nixos-unstable)
+- **Stable systems** (athena, demeter, aix, aion, rhea, kerkouane): Use `nixpkgs-25_05` with specific hardware types like "rpi4" for Raspberry Pi 4
+
+### Package Management
+
+Custom packages are defined in `/pkgs/default.nix` and exposed through the `additions` overlay. They are built using standard Nix packaging functions (`pkgs.callPackage`). The repository provides packages for both x86_64-linux and aarch64-linux architectures.
+
+### Secrets Management
+
+Secrets are managed using agenix:
+- `secrets.nix` defines which secrets are encrypted for which hosts and users
+- Yubikeys are used for age encryption
+- Host SSH keys are used for system-level secret decryption
+
+## Common Commands
+
+Everything should happen using `make` (and `Makefile` accross the repository). You can use `make help` to figure out what it does.
+
+**IMPORTANT: Never use `home-manager switch` or `nixos-rebuild` commands directly. Always use `make switch` or the appropriate make targets.**
+
+### Building and Deploying Systems
+
+```bash
+# Build and switch the current system
+make switch
+
+# Build and activate on next boot
+make boot
+
+# Test build without switching
+make dry-build
+
+# Build a specific remote host
+make host/<hostname>/build
+
+# Deploy to a remote host (boot)
+make host/<hostname>/boot
+
+# Deploy to a remote host (switch)
+make host/<hostname>/switch
+```
+
+### Building Packages
+
+```bash
+# Build a single package
+nix build .#<package-name>
+
+# Install a package to your profile
+nix profile install .#<package-name>
+
+# List all available packages
+nix flake show
+```
+
+### Home Manager
+
+```bash
+# Update home-manager configuration
+home-manager switch --flake .#<username>@<hostname>
+```
+
+### Development
+
+```bash
+# Enter development shell
+nix develop
+
+# Format Nix files
+make fmt
+
+# Run pre-commit checks
+make pre-commit
+
+# Install git hooks
+make install-hooks
+```
+
+### Maintenance
+
+```bash
+# Clean old system generations (older than 15 days) and build results
+make clean
+
+# Update flake inputs
+nix flake update
+```
+
+## Pre-commit Hooks
+
+The repository uses pre-commit hooks configured in `flake.nix` for:
+- Go formatting (gofmt)
+- Nix formatting (nixfmt-rfc-style) and linting (deadnix)
+- Python linting (flake8, ruff)
+- Shell script checking (shellcheck)
+
+These run automatically via git hooks if installed with `make install-hooks`.
+
+## Key Patterns
+
+### Adding a New Host
+
+1. Create `/systems/<hostname>` directory with `boot.nix` and `hardware.nix`
+2. Add host entry in `flake.nix` nixosConfigurations using `libx.mkHost`
+3. Add machine metadata to `globals.nix` (network IPs, SSH keys, syncthing ID if applicable)
+4. If using secrets, update `secrets.nix` with host SSH key
+
+### Adding a New Package
+
+1. Create package directory in `/pkgs/<package-name>` with `default.nix`
+2. Add entry to `/pkgs/default.nix` using `pkgs.callPackage`
+3. Package will be available via `nix build .#<package-name>`
+
+### Modifying Desktop Environment
+
+Desktop configurations are in `/systems/common/desktop` and `/home/common/desktop`. The desktop type ("sway" or "niri") is specified when calling `mkHost` in `flake.nix` and conditionally imports desktop modules.
+
+## Testing
+
+For Go-based tools, run tests from the tool directory:
+```bash
+cd tools/<tool-name>
+go test ./...
+```
+
+### Keyboard Firmware
+
+```bash
+# Build Moonlander QMK firmware in folder keyboards/moonlander of the git repository
+make keyboards/moonlander/build
+
+# Build eyelash_corne ZMK firmware in folder keyboards/eyelash_corne of the git repository
+make keyboards/eyelash_corne/build
+
+# Generate keymap SVGs for visualization
+make keyboards/draw                # Generate SVGs for all keyboards
+make keyboards/moonlander/draw     # Generate SVG for Moonlander only
+make keyboards/eyelash_corne/draw  # Generate SVG for Eyelash Corne only
+```
+
+## Deployment Safety
+
+**IMPORTANT: Always ask for user confirmation before deploying to remote hosts.**
+
+When making configuration changes that require deployment:
+
+1. **Show the changes first** - Use `git diff` or explain what will be deployed
+2. **Ask for explicit approval** - Never run `nixos-rebuild switch` or `make host/<hostname>/switch` without asking the user first
+3. **Suggest dry-run builds** - Offer to run `make host/<hostname>/build` or `nixos-rebuild build` to test first
+4. **Confirm the target host** - Make sure the user wants to deploy to that specific machine
+
+Examples of what to ask:
+- "Would you like me to deploy these changes to rhea?"
+- "Should I run a dry-build first to verify the configuration?"
+- "These changes will affect <hostname>. Do you want to proceed with the deployment?"
+
+**Never deploy automatically** - even if it seems like the logical next step. Remote deployments can have significant impact on running services.
+
+## Special Notes
+
+- The repository uses XDG base directories for Nix configuration (enabled via `use-xdg-base-directories = true`)
+- Custom binary caches are configured: vdemeester.cachix.org, chapeau-rouge.cachix.org, nixos-raspberrypi.cachix.org
+- The `globals.nix` file contains sensitive network topology information and should be consulted when working with networking or machine-specific configurations
+- Some hosts use specific NixOS versions: stable hosts use 25.05, unstable hosts use nixos-unstable
CLAUDE.md
@@ -1,199 +1,3 @@
 # CLAUDE.md
 
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
-## Repository Overview
-
-This is a comprehensive NixOS and home-manager monorepo for managing personal infrastructure, system configurations, and custom tools. The repository uses Nix flakes as the primary interface for building and deploying configurations across multiple machines.
-
-## Architecture
-
-### Core Structure
-
-The repository follows a modular architecture centered around `flake.nix`:
-
-- **`/lib`**: Core library functions including `mkHost`, `mkHome`, and `mkSystemManager` for generating NixOS, home-manager, and system-manager configurations
-- **`globals.nix`**: Global configuration including machine definitions (network, SSH, syncthing), DNS zones, and VPN settings
-- **`/systems`**: NixOS system configurations, organized by hostname with a shared `/systems/common` directory containing base, desktop, hardware, programs, services, and users modules
-- **`/home`**: Home-manager configurations with `/home/common` containing desktop, dev, services, and shell modules
-- **`/pkgs`**: Custom Nix packages that are exposed via overlays
-- **`/tools`**: Source code for custom tools (battery-monitor, emacs configuration)
-- **`/modules`**: Custom NixOS modules (wireguard-client, wireguard-server, govanityurl, gosmee)
-- **`/overlays`**: Nix overlays for additions, modifications, and unstable packages
-- **`/keyboards`**: Hardware keyboard configurations (ZMK for Corne, QMK for Moonlander, Kanata software remapper)
-- **`/imperative`**: Idempotent configuration scripts for non-NixOS managed systems, organized by hostname (e.g., `/imperative/nagoya/apply.sh`). These scripts are meant to be run repeatedly to maintain system state on hosts that cannot use NixOS.
-
-### Host Configuration Pattern
-
-Each host has a dedicated directory in `/systems/<hostname>` containing:
-- `boot.nix`: Boot configuration (bootloader, initrd, kernel modules)
-- `hardware.nix`: Hardware-specific settings (hardware imports, filesystem mounts)
-- `extra.nix` (optional): Additional host-specific configuration
-- `home.nix` (optional): Host-specific home-manager configuration
-
-### System Types
-
-- **Unstable systems** (kyushu, aomi, sakhalin, foobar): Use `nixpkgs` (nixos-unstable)
-- **Stable systems** (athena, demeter, aix, aion, rhea, kerkouane): Use `nixpkgs-25_05` with specific hardware types like "rpi4" for Raspberry Pi 4
-
-### Package Management
-
-Custom packages are defined in `/pkgs/default.nix` and exposed through the `additions` overlay. They are built using standard Nix packaging functions (`pkgs.callPackage`). The repository provides packages for both x86_64-linux and aarch64-linux architectures.
-
-### Secrets Management
-
-Secrets are managed using agenix:
-- `secrets.nix` defines which secrets are encrypted for which hosts and users
-- Yubikeys are used for age encryption
-- Host SSH keys are used for system-level secret decryption
-
-## Common Commands
-
-Everything should happen using `make` (and `Makefile` accross the repository). You can use `make help` to figure out what it does.
-
-**IMPORTANT: Never use `home-manager switch` or `nixos-rebuild` commands directly. Always use `make switch` or the appropriate make targets.**
-
-### Building and Deploying Systems
-
-```bash
-# Build and switch the current system
-make switch
-
-# Build and activate on next boot
-make boot
-
-# Test build without switching
-make dry-build
-
-# Build a specific remote host
-make host/<hostname>/build
-
-# Deploy to a remote host (boot)
-make host/<hostname>/boot
-
-# Deploy to a remote host (switch)
-make host/<hostname>/switch
-```
-
-### Building Packages
-
-```bash
-# Build a single package
-nix build .#<package-name>
-
-# Install a package to your profile
-nix profile install .#<package-name>
-
-# List all available packages
-nix flake show
-```
-
-### Home Manager
-
-```bash
-# Update home-manager configuration
-home-manager switch --flake .#<username>@<hostname>
-```
-
-### Development
-
-```bash
-# Enter development shell
-nix develop
-
-# Format Nix files
-make fmt
-
-# Run pre-commit checks
-make pre-commit
-
-# Install git hooks
-make install-hooks
-```
-
-### Maintenance
-
-```bash
-# Clean old system generations (older than 15 days) and build results
-make clean
-
-# Update flake inputs
-nix flake update
-```
-
-## Pre-commit Hooks
-
-The repository uses pre-commit hooks configured in `flake.nix` for:
-- Go formatting (gofmt)
-- Nix formatting (nixfmt-rfc-style) and linting (deadnix)
-- Python linting (flake8, ruff)
-- Shell script checking (shellcheck)
-
-These run automatically via git hooks if installed with `make install-hooks`.
-
-## Key Patterns
-
-### Adding a New Host
-
-1. Create `/systems/<hostname>` directory with `boot.nix` and `hardware.nix`
-2. Add host entry in `flake.nix` nixosConfigurations using `libx.mkHost`
-3. Add machine metadata to `globals.nix` (network IPs, SSH keys, syncthing ID if applicable)
-4. If using secrets, update `secrets.nix` with host SSH key
-
-### Adding a New Package
-
-1. Create package directory in `/pkgs/<package-name>` with `default.nix`
-2. Add entry to `/pkgs/default.nix` using `pkgs.callPackage`
-3. Package will be available via `nix build .#<package-name>`
-
-### Modifying Desktop Environment
-
-Desktop configurations are in `/systems/common/desktop` and `/home/common/desktop`. The desktop type ("sway" or "niri") is specified when calling `mkHost` in `flake.nix` and conditionally imports desktop modules.
-
-## Testing
-
-For Go-based tools, run tests from the tool directory:
-```bash
-cd tools/<tool-name>
-go test ./...
-```
-
-### Keyboard Firmware
-
-```bash
-# Build Moonlander QMK firmware in folder keyboards/moonlander of the git repository
-make keyboards/moonlander/build
-
-# Build eyelash_corne ZMK firmware in folder keyboards/eyelash_corne of the git repository
-make keyboards/eyelash_corne/build
-
-# Generate keymap SVGs for visualization
-make keyboards/draw                # Generate SVGs for all keyboards
-make keyboards/moonlander/draw     # Generate SVG for Moonlander only
-make keyboards/eyelash_corne/draw  # Generate SVG for Eyelash Corne only
-```
-
-## Deployment Safety
-
-**IMPORTANT: Always ask for user confirmation before deploying to remote hosts.**
-
-When making configuration changes that require deployment:
-
-1. **Show the changes first** - Use `git diff` or explain what will be deployed
-2. **Ask for explicit approval** - Never run `nixos-rebuild switch` or `make host/<hostname>/switch` without asking the user first
-3. **Suggest dry-run builds** - Offer to run `make host/<hostname>/build` or `nixos-rebuild build` to test first
-4. **Confirm the target host** - Make sure the user wants to deploy to that specific machine
-
-Examples of what to ask:
-- "Would you like me to deploy these changes to rhea?"
-- "Should I run a dry-build first to verify the configuration?"
-- "These changes will affect <hostname>. Do you want to proceed with the deployment?"
-
-**Never deploy automatically** - even if it seems like the logical next step. Remote deployments can have significant impact on running services.
-
-## Special Notes
-
-- The repository uses XDG base directories for Nix configuration (enabled via `use-xdg-base-directories = true`)
-- Custom binary caches are configured: vdemeester.cachix.org, chapeau-rouge.cachix.org, nixos-raspberrypi.cachix.org
-- The `globals.nix` file contains sensitive network topology information and should be consulted when working with networking or machine-specific configurations
-- Some hosts use specific NixOS versions: stable hosts use 25.05, unstable hosts use nixos-unstable
+@AGENTS.md