2585a0e9d3
Mirrors the azos-core change: azos.claude.enable now sets azos.agent-memory.backends.claude.enable and azos.agent-skills.backends.claude.enable instead of the old azos.claude-memory.enable/azos.claude-skills.enable. The new agent-shell memory backend needs no wiring here -- it's bundled directly in azos-core's editor/emacs module, alongside wherever agent-shell itself gets installed.
277 lines
11 KiB
Markdown
277 lines
11 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
|
|
├── suites/ # Suites, each grouping related sub-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 → inside an existing or new suite directory,
|
|
`azos-core/suites/<suite>/<name>/default.nix` (registering
|
|
`config.flake.modules.homeManager.<suite>`) — never a bare file directly under
|
|
`azos-core/suites/`; every azos-core feature belongs to a suite.
|
|
- 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`, `desktop`)
|
|
- 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.desktop` — desktop session plumbing (flameshot, dunst, keyboard layout) plus generally-useful apps (browser, libreoffice, zoom, spotify, gimp, whatsapp). Shared, lives in azos-core — wanted on any GUI machine, work included.
|
|
- `azos.suites.exwm` — EXWM window manager, depends on `desktop`
|
|
|
|
Machine-specific, personal-only apps (steam, discord) are **not** part of any azos-core
|
|
suite — they live as standalone features directly in `azos/features/`, imported only on
|
|
machines that want them (e.g. `azos/features/discord`, `azos/features/steam`), since any
|
|
such machine already uses the `azos` project rather than a different downstream repo.
|
|
|
|
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, for shared features,
|
|
`azos-core/suites/<suite>/<name>/default.nix` inside an existing or new suite
|
|
(registering `config.flake.modules.homeManager.<suite>`, not a standalone module name)
|
|
2. Use the module template above
|
|
3. Machine-specific: add `suiteModules.homeManager.<name>` to the imports list in
|
|
`home-manager/home.nix`. Shared: no change needed if the suite is already imported.
|
|
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 suites/<suite>/<name>/
|
|
> ```
|
|
|
|
## Agent Memory/Skills Integration
|
|
|
|
Memory (org-roam) and skills (slash commands/CLAUDE.md) are backend-pluggable, not
|
|
Claude-specific, even though Claude is currently the only skills backend and one of two
|
|
memory backends:
|
|
|
|
| Feature | Option | What it does |
|
|
|---------|--------|--------------|
|
|
| `azos-core/suites/base/agent-memory` | `azos.agent-memory.backends.claude.enable` | Registers org-roam-mcp as a global MCP server in `~/.claude.json`; hooks resync org-roam's index on edit and inject project context at session start |
|
|
| `azos-core/suites/base/agent-memory` | `azos.agent-memory.backends.agent-shell.enable` | Registers org-roam-mcp via `agent-shell-mcp-servers` and resyncs on `file-write` events — applies regardless of which ACP backend (Claude, Gemini CLI, Codex, ...) a given agent-shell session runs. Also marks Claude sessions agent-shell launches (`AZOS_AGENT_SHELL_SESSION=1`) so the claude backend's own hooks no-op for those sessions instead of double-acting |
|
|
| `azos-core/suites/base/agent-skills` | `azos.agent-skills.backends.claude.enable` | Deploys skills to `~/.claude/commands/` and content to `~/.claude/CLAUDE.md` |
|
|
| `azos/features/claude` | `azos.claude.enable` | Installs claude-code, auto-enables the claude backend for both of the above |
|
|
| `azos-core/suites/editor/emacs` | (bundled, not a separate option) | Installs agent-shell, auto-enables `azos.agent-memory.backends.agent-shell.enable` |
|
|
|
|
Both agent-memory and agent-skills register `config.flake.modules.homeManager.base`
|
|
(they live inside the `base` suite, since that's where agent-shell is introduced) — not
|
|
standalone module names, so no separate `suiteModules.homeManager.*` import is needed for
|
|
them in `home-manager/home.nix`.
|
|
|
|
### 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.
|
|
'';
|
|
```
|
|
`globalSkills`/`globalMdSections` stay Claude-specific (`~/.claude/commands/`,
|
|
`~/.claude/CLAUDE.md`) deliberately — no other backend has a uniform equivalent yet. See
|
|
`azos-core/suites/base/agent-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/suites/` | Suites, each grouping related shared sub-features (auto-discovered by import-tree) |
|
|
| `features/` | Machine-specific features (auto-discovered by import-tree) |
|
|
| `azos-core/suites/editor/emacs/config.org` | Literate Emacs config |
|
|
| `azos-core/suites/base/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)
|