446 lines
16 KiB
Markdown
446 lines
16 KiB
Markdown
# 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 |
|
|
| **m3ta-home** | code.m3ta.dev/m3tam3re/m3ta-home |
|
|
| **m3ta-nixpkgs** | code.m3ta.dev/m3tam3re/nixpkgs |
|
|
| **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, m3ta-home input
|
|
├── coding-rules.json # Opencode rules configuration
|
|
│
|
|
├── hosts/ # Per-host NixOS configurations
|
|
│ ├── common/ # Shared across all hosts
|
|
│ │ ├── users/
|
|
│ │ │ └── m3tam3re.nix # ← Central user + m3ta-home integration
|
|
│ │ ├── default.nix # Shared NixOS settings, overlays, home-manager setup
|
|
│ │ ├── ports.nix # Network ports config
|
|
│ │ └── extraServices/ # Common service toggles
|
|
│ ├── m3-ares/ # TUXEDO laptop (desktop)
|
|
│ │ └── home.nix # Hyprland: eDP-1 + HDMI, XDG/MIME
|
|
│ ├── m3-kratos/ # AMD desktop (desktop)
|
|
│ │ └── home.nix # Hyprland: dual DP, XDG/MIME
|
|
│ ├── m3-daedalus/ # Portable laptop (desktop, no Hyprland)
|
|
│ │ └── home.nix # XDG/MIME only
|
|
│ ├── m3-atlas/ # Primary server (server + coding)
|
|
│ ├── m3-helios/ # AdGuard DNS server (minimal server)
|
|
│ ├── m3-hermes/ # Secondary server (minimal server)
|
|
│ └── m3-aether/ # Cloud VM (minimal server)
|
|
│
|
|
├── modules/ # Reusable NixOS modules
|
|
│ └── nixos/ # NixOS-specific modules
|
|
│
|
|
├── overlays/ # Package overlays (stable/locked/master/pinned)
|
|
│ ├── default.nix
|
|
│ └── mods/
|
|
│
|
|
├── pkgs/ # Custom packages
|
|
│
|
|
├── secrets/ # Encrypted secrets (agenix)
|
|
│ └── secrets.nix
|
|
│
|
|
├── .opencode-rules/ # Opencode AI rules
|
|
│ ├── concerns/
|
|
│ ├── languages/nix.md
|
|
│ └── USAGE.md
|
|
│
|
|
└── .pi/ # Agent configuration
|
|
```
|
|
|
|
### Home-Manager Integration
|
|
|
|
Home-Manager configs are managed centrally in the **`m3ta-home`** repository:
|
|
- **Repo**: `code.m3ta.dev/m3tam3re/m3ta-home`
|
|
- **Docs**: See m3ta-home README for full documentation
|
|
|
|
What lives where:
|
|
|
|
| Concern | Location | Why |
|
|
|---------|----------|-----|
|
|
| Shell, CLI tools, editors, apps | `m3ta-home/profiles/` | Portable across all hosts |
|
|
| User identity (git, SSH, JJ) | `m3ta-home/users/` | Switchable: private vs work |
|
|
| Feature flags (enable/disable) | `nixos-config/hosts/common/users/m3tam3re.nix` | Per-host decisions |
|
|
| Monitor layouts, window rules | `nixos-config/hosts/<name>/home.nix` | Hardware-specific |
|
|
| XDG/MIME defaults | `nixos-config/hosts/<name>/home.nix` | Host-specific preferences |
|
|
| NixOS overlays | `nixos-config/overlays/` | System-level package management |
|
|
|
|
#### Host → Profile Mapping
|
|
|
|
Defined in `hosts/common/users/m3tam3re.nix`:
|
|
|
|
```nix
|
|
hostProfiles = {
|
|
# Desktop hosts
|
|
m3-ares = { context = "desktop"; sets = ["coding" "gaming" "media"]; };
|
|
m3-kratos = { context = "desktop"; sets = ["coding" "gaming" "media"]; };
|
|
m3-daedalus = { context = "desktop"; sets = ["coding" "media"]; };
|
|
# Server hosts
|
|
m3-atlas = { context = "server"; sets = ["coding"]; };
|
|
m3-helios = { context = "server"; sets = []; };
|
|
m3-hermes = { context = "server"; sets = []; };
|
|
m3-aether = { context = "server"; sets = []; };
|
|
};
|
|
```
|
|
|
|
#### Work Identity Use Case
|
|
|
|
The same `m3ta-home` repo supports a **work identity** for company machines:
|
|
|
|
```nix
|
|
# On a work NixOS machine:
|
|
(m3ta-lib.mkHome {
|
|
user = "m3tam3re";
|
|
identity = "work"; # ← switches git to sascha.koenig, SSH to AZ hosts
|
|
context = "desktop";
|
|
sets = ["coding"];
|
|
})
|
|
```
|
|
|
|
This provides the familiar shell/editor/CLI setup but with work git credentials and SSH 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
|
|
|
|
### Flake Input URLs
|
|
|
|
All `code.m3ta.dev` inputs use **SSH** URLs:
|
|
```nix
|
|
url = "git+ssh://gitea@code.m3ta.dev/m3tam3re/<repo>";
|
|
```
|
|
Anonymous HTTPS git on Gitea is unreliable and prompts for auth. SSH works with configured keys.
|
|
|
|
---
|
|
|
|
## 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 setup (`useGlobalPkgs = true`) |
|
|
| `hosts/common/users/m3tam3re.nix` | User definition + m3ta-home mkHome integration + per-host feature flags |
|
|
| `hosts/<name>/home.nix` | Host-specific overrides: monitors, workspaces, window rules, XDG/MIME |
|
|
| `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. Add entry to `hostProfiles` in `hosts/common/users/m3tam3re.nix`
|
|
4. Add feature flags in the `hostFlags` section
|
|
5. Create `hosts/<name>/home.nix` if the host needs monitor/XDG overrides
|
|
6. 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
|
|
|
|
### Adding a New Home-Manager Feature
|
|
|
|
1. Create the module in `m3ta-home` under the appropriate profile directory
|
|
2. Add the import to the parent `default.nix` in m3ta-home
|
|
3. Enable it per-host via feature flags in `hosts/common/users/m3tam3re.nix`
|
|
|
|
### 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'
|
|
```
|