Files
azos/AGENTS.md
T
2026-06-07 01:27:09 +03:00

255 lines
8.5 KiB
Markdown

# AGENTS.md - Guidelines for Agentic Coding in Azos
This is a NixOS/Nix flake-based configuration repository using home-manager for dotfiles and system configuration.
## Build Commands
### Evaluating
```bash
nix eval .#nixosConfigurations.lauretta.config.system.build.toplevel
nix flake show
```
### Building
```bash
# VM (with submodules for azos-core)
nix build '.?submodules=1#nixosConfigurations.vm.config.system.build.vm'
# Formatter
nix build .#formatter.x86_64-linux
```
### Deploying
```bash
# Rebuild the azos environment for lauretta (this machine) — use this when asked to "rebuild"
azos-lauretta-update
nix flake update --flake '.?submodules=1' # Update all inputs
nix flake lock --flake '.?submodules=1' --update-input X # Update specific input
```
> **Note**: When the user asks to "rebuild", they mean rebuilding the lauretta environment with the command above — NOT building the VM.
### Dev Shell & REPL
```bash
nix develop .#shells.x86_64-linux.default
nix repl
:lf .
```
### Ad-hoc Commands
If an executable doesn't exist on the system, run it ad-hoc with:
```bash
nix shell nixpkgs#<package> --command <cmd> <args>
```
## Linting/Formatting
Uses [alejandra](https://github.com/kamadorama/alejandra):
```bash
nix fmt # Format all Nix files
alejandra .
```
## Testing
Manual VM testing:
```bash
nix build '.?submodules=1#nixosConfigurations.vm.config.system.build.vm'
./result/bin/run-nixos-vm
```
## Emacs Debugging
When adding or debugging Emacs functionality, you can interact with the running Emacs session via `emacsclient` (with user permission):
```bash
# Create and switch to a buffer
emacsclient -c -e '(switch-to-buffer (get-buffer-create "test"))'
# Evaluate arbitrary Elisp
emacsclient -e '(message "hello")'
```
## Repository Structure
```
azos/
├── flake.nix # Main flake
├── home-manager/home.nix # Home-manager entry point; manually imports all modules
├── _machines/ # Per-machine NixOS configs (pass suiteModules as specialArgs)
├── nixos/ # NixOS system configs (configuration.nix, configuration-vm.nix, etc.)
├── features/ # Machine-specific home-manager features (auto-discovered)
├── overlays/ # Package overlays
├── shells/ # Dev shells
└── azos-core/ # Shared feature library (git submodule)
├── flake.nix
├── features/ # Shared/reusable features (auto-discovered)
├── overlays/ # Core overlays
└── _lib/ # Module schema helpers
```
Features are auto-discovered by `import-tree` — no central imports file. Each feature's
`default.nix` registers itself via `config.flake.modules.homeManager.<name>`. Modules are
then explicitly imported in `home-manager/home.nix` via `suiteModules.homeManager.<name>`.
**Where to put a new feature:**
- Shared / reusable across machines → `azos-core/features/<name>/default.nix`
- Machine-specific → `azos/features/<name>/default.nix`
## Code Style Guidelines
### Nix Module Template
All features follow this flake-parts registration pattern:
```nix
{...}: {
config.flake.modules.homeManager.<name> = {
lib,
config,
pkgs,
...
}: {
options.azos.<name>.enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
};
config = lib.mkIf config.azos.<name>.enable {
home.packages = with pkgs; [pkg1 pkg2];
};
};
}
```
### Naming Conventions
- Option paths: `azos.<module-name>.<option>`
- Module names: kebab-case (`git-config`, `claude-memory`)
- Feature directories: kebab-case, one `default.nix` per feature
- Variables: kebab-case
### Formatting
- Indentation: 2 spaces
- Packages: `with pkgs; [pkg1 pkg2]` (no trailing semicolon inside list)
### Imports
- Always include `{...}` for the outer module args
- Inner module args: `lib, config, pkgs, ...`
### Option Patterns
- Boolean enable: `lib.mkOption { default = false; example = true; type = lib.types.bool; }`
- Conditional config: `lib.mkIf config.azos.<name>.enable { ... }`
- Auto-enable a dependency: `azos.<dep>.enable = lib.mkDefault true;`
- Force value: `lib.mkForce` (sparingly)
### Extensible Options
For options that multiple modules should be able to contribute to, use attrset options:
```nix
options.azos.<name>.things = lib.mkOption {
default = {};
type = lib.types.attrsOf lib.types.path; # or lines, str, etc.
};
```
Any module can then add entries without modifying the owning feature. Examples in use:
- `azos.claude.globalSkills` — attrset of skill name → markdown file path
- `azos.claude.globalMdSections` — attrset of key → markdown string (merged into `~/.claude/CLAUDE.md`)
### Home-Manager vs NixOS
- Home-manager: `home.packages`, `home.file`, `programs.<program>`
- NixOS: `config.services`, `environment.systemPackages`
### Deploying Files
- Static file: `home.file."dest".source = ./file;`
- Generated text: `home.file."dest".text = "...";`
- Runtime script (e.g. merging JSON at activation): `home.activation.<name> = lib.hm.dag.entryAfter ["writeBoundary"] ''...'';`
### Suites System
Top-level suites group related features (defined in `azos-core/`):
- `azos.suites.base` — base packages and config
- `azos.suites.editor` — editor tools
- `azos.suites.dev` — development tools
- `azos.suites.station` — desktop applications
- `azos.suites.exwm` — EXWM window manager
The machine suite (`azos.suites.lauretta`) enables the relevant suites for this machine.
### Specializations
NixOS supports specializations for alternative configurations:
```nix
specialisation = {
hyprland = {
configuration = {
home-manager.users.aner = {pkgs, ...}: {
azos.suites.exwm.enable = lib.mkForce false;
azos.suites.hyprland.enable = true;
};
};
};
};
```
## Adding New Modules
1. Create `features/<name>/default.nix` (machine-specific) or `azos-core/features/<name>/default.nix` (shared)
2. Use the module template above
3. Add `suiteModules.homeManager.<name>` to the imports list in `home-manager/home.nix`
4. Run `nix fmt`
> **Submodule gotcha**: New files in `azos-core/` must be `git add`-ed inside the submodule
> before `nix build` will see them — Nix flakes only evaluate git-tracked files.
> ```bash
> cd azos-core && git add features/<name>/
> ```
## Claude Integration
Claude Code is integrated with this environment via several azos-core features:
| Feature | Option | What it does |
|---------|--------|--------------|
| `azos-core/features/claude-memory` | `azos.claude-memory.enable` | Registers org-roam-mcp as a global MCP server in `~/.claude.json` |
| `azos-core/features/claude-skills` | `azos.claude-skills.enable` | Deploys skills to `~/.claude/commands/` and content to `~/.claude/CLAUDE.md` |
| `azos/features/claude` | `azos.claude.enable` | Installs claude-code, auto-enables the above two |
### Adding Claude skills or standing instructions
From any module — no need to touch azos-core:
```nix
azos.claude.globalSkills.my-skill = ./skills/my-skill.md;
azos.claude.globalMdSections.my-rule = ''
# My Rule
Always do X when Y.
'';
```
See `azos-core/features/claude-skills/README.md` for full documentation.
## Key Files
| File | Purpose |
|------|---------|
| `flake.nix` | Main flake, defines systems and overlays |
| `home-manager/home.nix` | Home-manager entry point, imports all modules |
| `_machines/lauretta.nix` | Lauretta machine config, passes `suiteModules` as specialArgs |
| `nixos/configuration.nix` | Lauretta NixOS system config |
| `nixos/configuration-vm.nix` | Test VM config |
| `overlays/` | Package overlays |
| `azos-core/` | Shared feature library (git submodule) |
| `azos-core/features/` | Shared features (auto-discovered by import-tree) |
| `features/` | Machine-specific features (auto-discovered by import-tree) |
| `azos-core/features/editor/emacs/config.org` | Literate Emacs config |
| `azos-core/features/claude-skills/README.md` | Claude skills extensibility docs |
## Common Tasks
**Add system package**: Edit a NixOS feature, add to `environment.systemPackages = with pkgs; [ pkg ]`
**Add home-manager package**: Edit a feature's config block, add to `home.packages = with pkgs; [ pkg ]`
**Add system service**: Edit a NixOS feature, add under `services.<service>`
**Add custom package**: Add to `azos-core/overlays/` via `config.flake.overlayPkgs.<name>`, then use as `pkgs.<name>`
**Access unstable packages**: Use `pkgs.unstable.<package>` (via unstable-packages overlay)