AGENTS.md
AGENTS.mdAGENTS.mdroot
Quality
89/100
Scores the file, not the repository.Length
2,324 words
29 headings · 7 code blocksRepository
8.0k
— · pushed 16 days agoLast changed
3 days ago
First indexed 3 days ago.1# AGENTS.md — nullclaw Agent Engineering Protocol23This file defines the default working protocol for coding agents in this repository.4Scope: entire repository.56## 1) Project Snapshot (Read First)78nullclaw is a Zig-first autonomous AI assistant runtime optimized for:910- minimal binary size (target: < 1 MB ReleaseSmall)11- minimal memory footprint (target: < 5 MB peak RSS)12- zero dependencies beyond libc and optional SQLite13- full feature parity with ZeroClaw (Rust reference implementation)1415Core architecture is **vtable-driven** and modular. All extension work is done by implementing16vtable structs and registering them in factory functions.1718Key extension points:1920- `src/providers/root.zig` (`Provider`) — AI model providers21- `src/channels/root.zig` (`Channel`) — messaging channels22- `src/tools/root.zig` (`Tool`) — tool execution surface23- `src/memory/root.zig` (`Memory`) — memory backends24- `src/observability.zig` (`Observer`) — observability hooks25- `src/runtime.zig` (`RuntimeAdapter`) — execution environments26- `src/peripherals.zig` (`Peripheral`) — hardware boards (Arduino, STM32, RPi)2728Current scale: **245 source files, ~204K lines of code, 5,640+ tests**.2930Build and test:3132```bash33zig build # dev build34zig build -Doptimize=ReleaseSmall # release build35zig build test --summary all # run all tests36```3738## 2) Deep Architecture Observations (Why This Protocol Exists)3940These codebase realities should drive every design decision:41421. **Vtable + factory architecture is the stability backbone**43 - Extension points are explicit and swappable via `ptr: *anyopaque` + `vtable: *const VTable`.44 - Callers must OWN the implementing struct (local var or heap-alloc). Never return a vtable interface pointing to a temporary — the pointer will dangle.45 - Most features should be added via vtable implementation + factory registration, not cross-cutting rewrites.46472. **Binary size and memory are hard product constraints**48 - `zig build -Doptimize=ReleaseSmall` is the release target. Every dependency and abstraction has a size cost.49 - Avoid adding libc calls, runtime allocations, or large data tables without justification.50 - `MaxRSS` during `zig build test` must stay well under 50 MB.51523. **Security-critical surfaces are first-class**53 - `src/gateway.zig`, `src/security/`, `src/tools/`, `src/runtime.zig` carry high blast radius.54 - Defaults are secure-by-default (pairing, HTTPS-only, allowlists, AEAD encryption). Keep it that way.55564. **Zig 0.16.0 API is the baseline — no newer features**57 - HTTP client: `std.http.Client.fetch()` with `std.Io.Writer.Allocating` for response body capture.58 - Child processes: `std.process.Child.init(argv, allocator)`, `.Pipe` (capitalized).59 - stdout: `std.fs.File.stdout().writer(&buf)` → use `.interface` for `print`/`flush`.60 - `std.io.getStdOut()` does NOT exist in the current Zig stdlib — use `std.fs.File.stdout()`.61 - SQLite: linked via `/opt/homebrew/opt/sqlite/{lib,include}` on the compile step, not the module.62 - `ArrayListUnmanaged`: init with `.empty`, pass allocator to every method.63645. **All 5,640+ tests must pass at zero leaks**65 - The test suite uses `std.testing.allocator` (leak-detecting GPA). Every allocation must be freed.66 - `Config.load()` allocates — always wrap in `std.heap.ArenaAllocator` in tests and production.67 - `ChaCha20Poly1305.decrypt` can segfault on tag failure with heap-allocated output on macOS with older Zig toolchains — use a stack buffer then `allocator.dupe()`.6869## 3) Engineering Principles (Normative)7071These principles are mandatory. They are implementation constraints, not suggestions.7273### 3.1 KISS7475Required:76- Prefer straightforward control flow over meta-programming.77- Prefer explicit comptime branches and typed structs over hidden dynamic behavior.78- Keep error paths obvious and localized.7980### 3.2 YAGNI8182Required:83- Do not add config keys, vtable methods, or feature flags without a concrete caller.84- Do not introduce speculative abstractions.85- Keep unsupported paths explicit (`return error.NotSupported`) rather than silent no-ops.8687### 3.3 DRY + Rule of Three8889Required:90- Duplicate small local logic when it preserves clarity.91- Extract shared helpers only after repeated, stable patterns (rule-of-three).92- When extracting, preserve module boundaries and avoid hidden coupling.9394### 3.4 Fail Fast + Explicit Errors9596Required:97- Prefer explicit errors for unsupported or unsafe states.98- Never silently broaden permissions or capabilities.99- In tests: `builtin.is_test` guards are acceptable to skip side effects (e.g., spawning browsers), but the guard must be explicit and documented.100101### 3.5 Secure by Default + Least Privilege102103Required:104- Deny-by-default for access and exposure boundaries.105- Never log secrets, raw tokens, or sensitive payloads.106- All outbound URLs must be HTTPS. HTTP is rejected at the tool layer.107- Keep network/filesystem/shell scope as narrow as possible.108109### 3.6 Determinism + No Flaky Tests110111Required:112- Tests must not spawn real network connections, open browsers, or depend on system state.113- Use `builtin.is_test` to bypass side effects (spawning, opening URLs, real hardware I/O).114- Tests must be reproducible across macOS and Linux.115116## 4) Repository Map (High-Level)117118```119src/120 main.zig CLI entrypoint and command routing121 root.zig module exports (lib root)122 agent.zig orchestration loop123 config.zig schema + config loading/merging (~/.nullclaw/config.json)124 gateway.zig webhook/HTTP gateway server125 onboard.zig interactive setup wizard126 health.zig component health registry127 runtime.zig runtime adapters (native, docker, wasm, cloudflare)128 tunnel.zig tunnel providers (cloudflared, ngrok, tailscale, custom)129 skillforge.zig skill discovery and integration130 migration.zig memory migration from other backends131 hardware.zig hardware discovery and management132 peripherals.zig hardware peripherals (Arduino, STM32/Nucleo, RPi)133 security/ policy, pairing, secrets, sandbox backends134 memory/ SQLite + markdown backends, embeddings, vector search135 providers/ 50+ AI provider implementations (9 core + 41 compatible services)136 channels/ 17 channel implementations137 tools/ 30+ tool implementations138 agent/ agent loop, context, planner139```140141## 5) Risk Tiers by Path (Review Depth Contract)142143- **Low risk**: docs, comments, test additions, minor formatting144- **Medium risk**: most `src/**` behavior changes without boundary/security impact145- **High risk**: `src/security/**`, `src/gateway.zig`, `src/tools/**`, `src/runtime.zig`, config schema, vtable interfaces146147When uncertain, classify as higher risk.148149## 6) Agent Workflow (Required)1501511. **Read before write** — inspect existing module, vtable wiring, and adjacent tests before editing.1522. **Define scope boundary** — one concern per change; avoid mixed feature+refactor+infra patches.1533. **Implement minimal patch** — apply KISS/YAGNI/DRY rule-of-three explicitly.1544. **Validate** — `zig build test --summary all` must show 0 failures and 0 leaks.1555. **Document impact** — update comments/docs for behavior changes, risk, and side effects.156157### 6.1 Code Naming Contract (Required)158159Apply these naming rules consistently:160161- Functions and methods: `camelCase` (e.g., `parseCommand`, `buildSimpleRequestBody`, `healthCheck`). This follows standard Zig convention.162- Variables, fields, modules, files: `snake_case` (e.g., `workspace_dir`, `bot_user_id`, `config_parse.zig`).163- Types, structs, enums, unions: `PascalCase` (e.g., `AnthropicProvider`, `BrowserTool`, `CommandRiskLevel`).164- Value constants (numeric limits, URLs, timeouts): `SCREAMING_SNAKE_CASE` (e.g., `MAX_BODY_SIZE`, `DEFAULT_BASE_URL`, `KEY_LEN`).165- Comptime array/table constants: `snake_case` (e.g., `high_risk_commands`, `compat_providers`, `default_allowed_commands`).166- Vtable implementer naming: `<Name>Provider`, `<Name>Channel`, `<Name>Tool`, `<Name>Memory`, `<Name>Sandbox`.167- Vtable function-pointer fields: `camelCase` for new vtables (e.g., `chatWithSystem`, `supportsNativeTools`, `getName`). Note: some older vtable fields use `snake_case` (`supports_streaming`, `record_event`); prefer `camelCase` for new additions and consolidate over time.168- Factory registration keys: stable, lowercase, user-facing (e.g., `"openai"`, `"telegram"`, `"shell"`). Use hyphens for multi-word keys (e.g., `"together-ai"`, `"aws-bedrock"`).169- Tests: named with space-separated descriptive phrases as the test block string (e.g., `"command risk low for read commands"`, `"pushover execute missing message"`). Prefix with the subject or subsystem when helpful. Fixtures use neutral names.170171### 6.2 Architecture Boundary Contract (Required)172173- Extend capabilities by adding vtable implementations + factory wiring first.174- Keep dependency direction inward to contracts: concrete implementations depend on vtable/config/util, not on each other.175- Avoid cross-subsystem coupling (provider code importing channel internals, tool code mutating gateway policy).176- Keep module responsibilities single-purpose: orchestration in `agent/`, transport in `channels/`, model I/O in `providers/`, policy in `security/`, execution in `tools/`.177178## 7) Change Playbooks179180### 7.1 Adding a Provider181182- Add `src/providers/<name>.zig` implementing `Provider.VTable` (`chatWithSystem`, `chat`, `supportsNativeTools`, `getName`, `deinit`).183- Register in `src/providers/root.zig` factory.184- `chatImpl` must extract system/user from `request.messages` (see existing providers for pattern).185- Add tests for vtable wiring, error paths, and config parsing.186187### 7.2 Adding a Channel188189- Add `src/channels/<name>.zig` implementing `Channel.VTable`.190- Keep `send`, `listen`, `name`, `isConfigured` semantics consistent with existing channels.191- Cover auth/config/health behavior with tests.192193### 7.3 Adding a Tool194195- Add `src/tools/<name>.zig` implementing `Tool.VTable` (`execute`, `name`, `description`, `parameters_json`).196- Validate and sanitize all inputs. Return `ToolResult`; never panic in the runtime path.197- Add `builtin.is_test` guard if the tool spawns processes or opens network connections.198- Register in `src/tools/root.zig`.199200### 7.4 Adding a Peripheral201202- Implement the `Peripheral` interface in `src/peripherals.zig`.203- Peripherals expose `read`/`write` methods that delegate to real hardware I/O.204- Use `probe-rs` CLI for STM32/Nucleo flash access; serial JSON protocol for Arduino.205- Non-Linux platforms must return `error.UnsupportedOperation` (not silent 0).206207### 7.5 Security / Runtime / Gateway Changes208209- Include threat/risk notes in the commit or PR.210- Add/update tests for failure modes and boundaries.211- Keep observability useful but non-sensitive (no secrets in logs or errors).212213### 7.6 Updating the Required Zig Version214215Whenever a documentation or code change indicates that the required Zig216toolchain version is changing (for example: `README.md`, `AGENTS.md`,217`CLAUDE.md`, `docs/**/installation.md`, `docs/**/development.md`,218`docs/**/termux.md`, `flake.nix`, `Dockerfile`, `.github/workflows/**`, or any219`zig version` / "Zig 0.16.0" string in the repo), the per-distro install220guides must be updated in the same change so they keep matching the pinned221version.222223Required steps:2242251. Identify the new pinned Zig version (e.g. `0.16.1`, `0.17.0`).2262. Visit `https://ziglang.org/download/` and locate the section for that exact227 version. Do not guess URLs — fetch them from the official download page so228 the filename, archive layout, and presence of the build are confirmed.2293. For every architecture referenced in the install guides (at minimum230 `x86_64-linux`, plus any others already documented), copy the canonical231 tarball URL and checksum from `ziglang.org/download/`.2324. Update every `docs/**/zig-installation.md` file (currently233 `docs/en/zig-installation.md` and `docs/zh/zig-installation.md`) so that234 every URL, checksum, filename, and extracted directory name reflects the new235 version. The version number must appear consistently in:236 - the linked download URL237 - the `wget` command238 - the checksum verification command239 - the `tar -xf` filename240 - the `export PATH="$PWD/zig-...:$PATH"` directory name2415. Keep all `docs/**/zig-installation.md` translations in sync — if the242 English version changes, the Chinese version (and any future translations)243 must be updated in the same commit.2446. Cross-check that the version pin matches everywhere else it appears245 (`AGENTS.md` §2.4, `CLAUDE.md` build commands, other `docs/**` pages,246 `flake.nix`, `Dockerfile`, CI workflows). Mismatches are a hard fail.247248Do not bump the Zig version pin in one place without sweeping all of the249above. A partial bump leaves users following copy-paste instructions that250download a tarball that no longer matches the pinned toolchain.251252## 8) Validation Matrix253254Required before any code commit:255256```bash257zig build test --summary all # all tests must pass, 0 leaks258```259260For release changes:261262```bash263zig build -Doptimize=ReleaseSmall # must compile clean264```265266Before any version bump, release branch, or tag work: read `RELEASING.md` and follow it exactly. Do not tag feature branches.267268Additional expectations by change type:269270- **Docs/comments only**: no build required, but verify no broken code references.271- **Security/runtime/gateway/tools**: include at least one boundary/failure-mode test.272- **Provider additions**: test vtable wiring + graceful failure without credentials.273274If full validation is impractical, document what was run and what was skipped.275276### 8.1 Test Coverage Mandate277278**Every code change must be accompanied by tests.** No exceptions.279280- **Behavior changes**: add or update tests that directly exercise the changed code path.281- **Bug fixes**: add a regression test that reproduces the original failure *before* the fix and passes after.282- **Logging-only or pure error-propagation changes** (e.g., `catch |err|` + `log.err(...)`): unit testing may not be practical. In this case add a comment near the change explaining why formal test coverage is omitted. Example:283```zig284 // NOTE: No unit test for this log path — would require a mock session manager.285 // Covered by manual integration testing against a running NullClaw instance.286```287- **Error path resource cleanup**: when a function allocates resources before returning an error, always free them before the `return error.Foo`. Verify with `zig build test` that the test allocator reports 0 leaks.288- Tests that were added to cover a specific fix must have a comment citing the bug they guard against, e.g.:289```zig290 // Regression: GLM-5 returns content=null on context-limit; parseNativeResponse must not silently succeed.291```292293### 8.2 Git Hooks294295The repository ships with pre-configured hooks in `.githooks/`. Activate once per clone:296297```bash298git config core.hooksPath .githooks299```300301Hooks:302303| Hook | What it does |304|------|-------------|305| `pre-commit` | Runs `zig fmt --check src/` — blocks commit if any file is not formatted |306| `pre-push` | Runs `zig build test --summary all` — blocks push if any test fails or leaks |307308To bypass a hook in an emergency: `git commit --no-verify` / `git push --no-verify`.309310## 9) Privacy and Sensitive Data (Required)311312- Never commit real API keys, tokens, credentials, personal data, or private URLs.313- Use neutral placeholders in tests: `"test-key"`, `"example.com"`, `"user_a"`.314- Test fixtures must be impersonal and system-focused.315- Review `git diff --cached` before push for accidental sensitive strings.316317## 10) Anti-Patterns (Do Not)318319- Do not add C dependencies or large Zig packages without strong justification (binary size impact).320- Do not return vtable interfaces pointing to temporaries — dangling pointer.321- Do not use `std.io.getStdOut()` — it does not exist in Zig 0.16.322- Do not silently weaken security policy or access constraints.323- Do not add speculative config/feature flags "just in case".324- Do not skip `defer allocator.free(...)` — every allocation must be freed.325- Do not use `ArrayListUnmanaged.writer()` as `?*Io.Writer` — incompatible types.326- Do not modify unrelated modules "while here".327- Do not include personal identity or sensitive information in tests, examples, docs, or commits.328- Do not use `SQLITE_TRANSIENT` in auto-translated C code — use `SQLITE_STATIC` (null) instead.329- Do not use heap-allocated output buffers in `ChaCha20Poly1305.decrypt` — use stack buffer + `allocator.dupe()`.330331## 11) Handoff Template (Agent → Agent / Maintainer)332333When handing off work, include:3343351. What changed3362. What did not change3373. Validation run and results (`zig build test --summary all`)3384. Remaining risks / unknowns3395. Next recommended action340341## 12) Vibe Coding Guardrails342343When working in fast iterative mode:344345- Keep each iteration reversible (small commits, clear rollback).346- Validate assumptions with code search before implementing.347- Prefer deterministic behavior over clever shortcuts.348- Do not "ship and hope" on security-sensitive paths.349- If uncertain about Zig 0.16 API, check `src/` for existing usage patterns before guessing.350- If uncertain about architecture, read the vtable interface definition before implementing.351
Also in nullclaw/nullclaw
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| nullclaw/nullclawCLAUDE.md · 8.0k | CLAUDE.md | buildteststylearch+5 | 97/100 | 3 days ago | |
| nullclaw/nullclawsrc/workspace_templates/AGENTS.md · 8.0k | AGENTS.md | styleperformancemonorepo | 50/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| OnlyTerp/prompt-cache-skillsAGENTS.md · 112 | AGENTS.md | setupbuildtestlint-format+5 | 100/100 | 3 days ago | |
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| wpscanteam/wpscanAGENTS.md · 9.7k | AGENTS.md | setupbuildteststyle+6 | 100/100 | 2 days ago | |
| SkeneTechnologies/skene-cookbookAGENTS.md · 51 | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 2 days ago | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| trick77/agents-md-syncAGENTS.md · 2 | AGENTS.md | setupbuildteststyle+5 | 100/100 | 3 days ago | |
| aaif-goose/gooseAGENTS.md · 52k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 3 days ago |
