AGENTS.md · git:20261027.ca1e0c8 · 2026-10-27 · sha256 81b7bd94bd3bdae3
AGENTS.md git:20261027.ca1e0c8A
Immutable. This exact content never changes and is served at /api/v1/blob/81b7bd94bd3bdae3.
# Niles Rust CLI that coordinates coding agents from different model families in tmux. Single crate, Unix only. Discover modules and commands from the source and `niles --help` rather than a list here. Machine-specific or private notes go in `AGENTS.local.md` (gitignored); read it if present. ## Git - Branch for new work, named `<issue>-<slug>`. Don't commit to `main` unless told to. - Commit and push only when explicitly asked. Finishing a change is not a cue to commit it. ## Checks [CI](.github/workflows/ci.yml) runs the checks on push; don't rerun them locally. Before reporting a change done, run only what CI doesn't cover, such as the focused tests for the code you changed, and say what printed. ## Standards - Simple, idiomatic, first-principles. Find root causes; no shortcuts, temporary fixes, or "just in case" code. - Minimal diffs: touch only what the change needs. - APIs, internal ones included, are self-documenting and hard to misuse. - Names and types carry meaning. Comment only what the code can't say: why, invariants, non-obvious tradeoffs. No comments that restate the code. - For a non-trivial change, ask whether there is a more elegant way before presenting it. Don't over-engineer simple fixes. ## Fail loudly - No silent defaults on failure: propagate with `?` or fail fast. - A default is a decision. Make it at the parse boundary or as a named const, never inline at a use site. A site that truly owns the decision takes `#[expect(clippy::disallowed_methods, reason = "…")]`. - No catch-and-continue; invalid state stops. - No branches for impossible states; encode impossibility in types. ## Modularity - Source files stay under ~500 lines; split by responsibility, one module per job. - DRY by the rule of three; don't abstract at two occurrences. - Never copy-paste-tweak; extract a function or generic. - No pass-through functions unless they change visibility, satisfy a trait, or cross a module boundary under a name the caller's domain needs. ## Correctness - Make invalid states unrepresentable with enums and newtypes. A newtype must carry weight: an invariant enforced at construction, a distinction between same-typed values, or impls the inner type can't have. - Parse, don't validate: type raw input (manifests, status lines, tmux output) once at the boundary. - `debug_assert!` invariants the types can't express. ## Lints Mechanically checkable rules live in `[lints.clippy]` in `Cargo.toml` and in `clippy.toml`, not in prose. The gate lints all targets. Suppress a lint with `#[expect(…, reason = "…")]`, not `#[allow]`. The one exception is test code, which allows `unwrap_used` and `expect_used` at the crate root; `tests/common` may use `#[allow(dead_code)]`, because each test binary uses a different subset of it. ## Invariants - This repository's skills live in `skills/` as ordinary disk skills. They are shareable instructions, so edit them with the same care as code. - Agent families and their launch mechanics are defined in `src/agents/families.rs`; models and effort levels in `src/agents/roster.yaml`. - `niles wait` reserves stdout for wake lines; diagnostics go to stderr. Its workspace exit codes (0 wake, including generated `gone:`, 11 superseded, 22 timeout) are a contract the lead relies on. - Changes that move a trust boundary (agent execution, workspace state, pane text) update the [threat model](docs/security.md). To check new agent CLI releases or what Niles should change for them, follow [CONTRIBUTING.md#agent-cli-compatibility](CONTRIBUTING.md#agent-cli-compatibility).