# Agent Instructions

This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context.

## Quick Reference

```bash
bd ready              # Find available work
bd show <id>          # View issue details
bd update <id> --claim  # Claim work atomically
bd close <id>         # Complete work
bd dolt push          # Push beads data to remote
```

## Non-Interactive Shell Commands

**ALWAYS use non-interactive flags** with file operations to avoid hanging on confirmation prompts.

Shell commands like `cp`, `mv`, and `rm` may be aliased to include `-i` (interactive) mode on some systems, causing the agent to hang indefinitely waiting for y/n input.

**Use these forms instead:**

```bash
# Force overwrite without prompting
cp -f source dest           # NOT: cp source dest
mv -f source dest           # NOT: mv source dest
rm -f file                  # NOT: rm file

# For recursive operations
rm -rf directory            # NOT: rm -r directory
cp -rf source dest          # NOT: cp -r source dest
```

**Other commands that may prompt:**

- `scp` - use `-o BatchMode=yes` for non-interactive
- `ssh` - use `-o BatchMode=yes` to fail instead of prompting
- `apt-get` - use `-y` flag
- `brew` - use `HOMEBREW_NO_AUTO_UPDATE=1` env var

<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->

## Beads Issue Tracker

This project uses **bd (beads)** for persistent task tracking. Run `bd prime` for full workflow context.

### Why Beads?

- **Prefer Beads over ad-hoc markdown TODO lists** — Beads provides structured, queryable, shareable issue tracking with dependency management
- **Never use `bd edit`** — it opens an interactive editor which blocks agent workflows
- **Use flags and stdin instead** — `bd update <id> --claim`, `bd create --title "..." --estimate 2`

### Slash Commands (Agent Workflow)

| Command | Purpose |
|---------|---------|
| `/beads:ready` | Find unblocked issues |
| `/beads:create` | Create a new issue |
| `/beads:update` | Update an issue (claim, status) |
| `/beads:close` | Close completed work |
| `/beads:stats` | Project-level snapshot |

### Core Workflow (6 Steps)

#### 1. Find Unblocked Work
```bash
bd ready --json
```
Lists issues with no blocking dependencies that are ready to work on.

#### 2. Claim Work
```bash
bd update <id> --claim
```
Atomically assigns the issue to you (sets status to "in-progress").

#### 3. Inspect Details
```bash
bd show <id>
```
View full issue details including:
- Description and acceptance criteria
- Blocking/blocked-by dependencies
- Time estimates
- Status history

#### 4. Create Newly Discovered Work
```bash
# Create a new issue
bd create \
  --title "Fix audio on m3-helios" \
  --estimate 2 \
  --priority high \
  --labels nixos,audio

# Link dependencies
bd dep <id> --blocks <blocked-id>      # This issue blocks another
bd dep <id> --after <after-id>         # This issue after another completes
bd dep <id> --requires <requires-id>  # This issue requires another
```

#### 5. Complete Work
```bash
bd close <id> --reason "Added PulseAudio fallback to configuration.nix"
```
Provide a concise summary of what was done. The `--reason` is mandatory.

#### 6. Project Snapshot
```bash
bd status --json    # Current state of all issues
bd stats            # Metrics: velocity, cycle time, bottlenecks
```

### Example Complete Workflow

```bash
# Start session - find work
bd ready --json

# Claim available issue
bd update 42 --claim

# Do the work...

# Discover something else needed
bd create --title "Document hermes-agent setup" --estimate 1
# Link as related
bd dep 43 --after 42

# Complete original
bd close 42 --reason "Added Hyprland idle timeout config"

# Close related
bd close 43 --reason "Added setup docs to AGENTS.md"

# Push state to remote
bd dolt push
```

### Rules

- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
- Run `bd prime` for detailed command reference and session close protocol
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files

## Session Completion

**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.

**MANDATORY WORKFLOW:**

1. **File issues for remaining work** - Create issues for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **PUSH TO REMOTE** - This is MANDATORY:
   ```bash
   git pull --rebase
   bd dolt push
   git push
   git status  # MUST show "up to date with origin"
   ```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
7. **Hand off** - Provide context for next session

**CRITICAL RULES:**

- Work is NOT complete until `git push` succeeds
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
<!-- END BEADS INTEGRATION -->

# Project Agent

**Workspace Path:** `/home/m3tam3re/p/NIX/nixos-config`
_(Note to Pi: Your file write/edit tools run in a different directory by default. You MUST use absolute paths starting with the Workspace Path above for ALL file operations!)_

**Generated:** 2026-04-26

---

## Stack

| Component        | Version/Source                    |
| ---------------- | --------------------------------- |
| **Nixpkgs**      | nixos-unstable + 25.05 stable     |
| **Home Manager** | github:nix-community/home-manager |
| **Agenix**       | github:ryantm/agenix              |
| **Disko**        | github:nix-community/disko        |
| **NUR**          | github:nix-community/NUR          |
| **Formatter**    | alejandra                         |
| **Linters**      | statix, deadnix                   |
| **IDE**          | nixd                              |
| **Hermes Agent** | NousResearch/hermes-agent         |
| **LLM Agents**   | numtide/llm-agents.nix            |

---

## Structure

```
nixos-config/
├── flake.nix                    # Entry point: hosts, overlays, dev shells
├── coding-rules.json            # Opencode rules configuration
│
├── hosts/                        # Per-host NixOS configurations
│   ├── common/                   # Shared across all hosts
│   │   ├── users/                # User definitions
│   │   ├── ports.nix             # Network ports config
│   │   └── extraServices/        # Common service toggles
│   ├── m3-ares/                  # Main desktop
│   ├── m3-atlas/                 # Desktop with disko
│   ├── m3-helios/                # Desktop with disko
│   ├── m3-hermes/                # Desktop with disko + hermes-agent
│   └── m3-kratos/                # Server with NUR
│
├── modules/                      # Reusable NixOS/home-manager modules
│   ├── nixos/                    # NixOS-specific modules
│   │   └── default.nix           # Imports common + service configs
│   └── home-manager/            # Home-manager configurations
│
├── home/                         # Per-user, per-host home configs
│   └── m3tam3re/
│       └── m3-daedalus.nix
│
├── overlays/                    # Package overlays
│   ├── default.nix              # Stable/locked/master branches
│   └── mods/                    # Package modifications
│
├── pkgs/                        # Custom packages
│
├── secrets/                     # Encrypted secrets (agenix)
│   └── secrets.nix
│
├── .opencode-rules/             # Opencode AI rules
│   ├── concerns/                 # Coding style rules
│   ├── languages/nix.md         # Nix conventions
│   └── USAGE.md
│
└── .pi/                         # Agent configuration
```

---

## Commands

| Action               | Command                                                                | Notes                                             |
| -------------------- | ---------------------------------------------------------------------- | ------------------------------------------------- |
| **Enter dev shell**  | `nix develop`                                                          | Includes alejandra, nixd, agenix, statix, deadnix |
| **Build host**       | `sudo nixos-rebuild switch --flake .#m3-ares`                          | Replace hostname as needed                        |
| **Dry run build**    | `sudo nixos-rebuild dry-run --flake .#m3-ares`                         | Validate without applying                         |
| **List hosts**       | `nix flake show`                                                       | Shows all NixOS configurations                    |
| **Update flake**     | `sudo nixos-rebuild switch --flake .#m3-ares --update-input nixpkgs`   | Update specific input                             |
| **Format code**      | `alejandra .`                                                          | Run before committing                             |
| **Check lint**       | `statix check .`                                                       | Run statix for antipatterns                       |
| **Remove dead code** | `deadnix -w .`                                                         | Clean up unused let bindings                      |
| **Build ISO**        | `nix build .#nixosConfigurations.m3-ares.config.system.build.isoImage` | Generate install ISO                              |

---

## Conventions

### Formatting & Style

- **Formatter:** `alejandra` (mandatory, run before commits)
- **Indentation:** 2 spaces (alejandra default)
- **Variables:** camelCase (e.g., `maxRetryAttempts`)
- **Types/Modules:** PascalCase (e.g., `MyService`)
- **Constants:** UPPER_SNAKE_CASE (e.g., `MAX_RETRIES`)
- **Files:** hyphen-case (e.g., `my-file.nix`)

### Nix Module Patterns

```nix
{ config, lib, pkgs, ... }:
{
  options.myService.enable = lib.mkEnableOption "my service";
  config = lib.mkIf config.myService.enable {
    services.myService.enable = true;
  };
}
```

### Conditionals

```nix
config = lib.mkMerge [
  (lib.mkIf cfg.enable { ... })
  (lib.mkIf cfg.extraConfig { ... })
];
```

### Anti-Patterns (AVOID)

- **Never use `with pkgs;`** — always use explicit package references
- **Never use `builtins.fetchTarball`** — use flake inputs instead
- **Never use `import <nixpkgs>`** — always use inputs
- **Never use `builtins.getAttr/hasAttr`** — use `lib.attrByPath` or `lib.optionalAttrs`
- **Avoid anonymous functions in config** — extract to named lets

### Imports

- Use flake inputs for dependencies (e.g., `inputs.home-manager.nixosModules.home-manager`)
- Import relative paths with `./` or `../`
- Never use absolute paths in imports

### Secrets

- Secrets managed via **agenix** in `secrets/` directory
- Never commit plaintext secrets
- Use `.nix` extension for secret files

---

## Key Files

| File                               | Purpose                                                                                    |
| ---------------------------------- | ------------------------------------------------------------------------------------------ |
| `flake.nix`                        | Central entry point defining all hosts, overlays, packages, dev shells, and nixpkgs config |
| `hosts/common/default.nix`         | Shared Nix settings, nixpkgs overlays, home-manager integration, user defaults             |
| `hosts/m3-ares/default.nix`        | Main desktop host configuration, imports common + service modules                          |
| `hosts/m3-ares/configuration.nix`  | Desktop environment config (Hyprland, display, audio, etc.)                                |
| `hosts/m3-ares/programs.nix`       | CLI tools, dev tools, shell configs                                                        |
| `hosts/m3-ares/services/`          | Service-specific configs (firewall, printing, etc.)                                        |
| `modules/nixos/default.nix`        | Orchestrates common + configuration imports                                                |
| `overlays/default.nix`             | Package version overrides (stable/locked/master branches)                                  |
| `.opencode-rules/languages/nix.md` | Nix-specific conventions and patterns                                                      |

---

## What to Avoid

1. **Don't modify `flake.lock`** directly — use `nix flake update`
2. **Don't use impure operations** — this is a pure flake-based config
3. **Don't commit without formatting** — always run `alejandra .` first
4. **Don't add packages to hosts directly** — prefer adding to overlays or using NUR
5. **Don't hardcode paths** — use `inputs` and relative imports
6. **Don't create monolithic modules** — keep functions under 20 lines
7. **Don't skip the dry-run** — always test with `--dry-run` before switching
8. **Don't use lib.mkDefault lightly** — understand the precedence implications

---

## Notes

### Adding a New Host

1. Add entry to `flake.nix` → `nixosConfigurations`
2. Create directory in `hosts/` with:
   - `default.nix` — imports common + specific configs
   - `configuration.nix` — host-specific system config
   - `hardware-configuration.nix` — from `nixos-generate-config`
   - `programs.nix`, `services/`, `secrets.nix` as needed
3. Run `sudo nixos-generate-config --dir ./hosts/new-host` first time

### Adding a New Package

1. For simple packages: add to appropriate overlay in `overlays/default.nix`
2. For complex packages: create in `pkgs/` directory
3. For upstream packages: use NUR or add as flake input

### Development Workflow

1. Edit config files
2. Run `alejandra .` to format
3. Run `statix check .` for linting
4. Run `sudo nixos-rebuild dry-run --flake .#m3-ares`
5. If successful: `sudo nixos-rebuild switch --flake .#m3-ares`

### Remote Building

```bash
# Build on remote machine
nix copy --to ssh://user@host .#nixosConfigurations.m3-ares.config.system.build.toplevel
ssh user@host 'sudo nixos-rebuild switch --flake /nix/store/...-closure'
```

### Home Manager

- Home configs live in `home/m3tam3re/`
- Use `home-manager.users.m3tam3re` in host config
- Access via `config.home-manager.users.m3tam3re`
