# AGENTS.md — the repository root One repository holding a Claude Code **plugin marketplace** and the **binary one of its plugins drives**. Three things live here and nothing else does: ``` .claude-plugin/marketplace.json the catalog: one entry per plugin cli/ the kettle binary — Go, no cobra, 8 packages plugins/ one directory per plugin ``` Where to go from here, and each of these directories documents itself: | directory | what it is | |---|---| | [`cli/`](cli/AGENTS.md) | one Go module, two binaries: `kettle`, which owns every mechanical thing about issues — the format, the store, the credentials, the tracker — and [`cmd/release`](cli/cmd/release/AGENTS.md), which publishes this repository's own releases. `make check` is the gate; there is no CI here | | [`plugins/`](plugins/AGENTS.md) | what a plugin is here, and what the catalog entry has to match | | [`plugins/kettle/`](plugins/kettle/AGENTS.md) | the plugin that wraps the binary: skills, the runner subagent, the hooks | | [`plugins/tdl/`](plugins/tdl/AGENTS.md) | the Three Dots Labs Go rule set — no binary, no state, just rules and templates | The split between `cli/` and `plugins/kettle/` is the one architectural fact worth carrying: **a binary holds what can be enforced, a plugin holds what can only be stated.** Anything mechanical belongs in Go where a test can hold it down; anything that is a judgement an operator makes belongs in a SKILL.md. ## The AGENTS.md convention **Every directory with a story documents itself, in that directory.** This file is a map, not a manual — it says what lives where and sends you down. A reader who opens `cli/internal/gitea/` gets the transport's rules from `cli/internal/gitea/AGENTS.md` and does not have to load the whole repository's design to change one request. Three rules make that work: 1. **`AGENTS.md` is the real file; `CLAUDE.md` beside it is a symlink to it.** `plugins/kettle/hooks/agents-sync.sh` enforces that before every Bash call and repairs any directory that drifted — it renames, re-points and swaps, and it never deletes content. Two real files with different content is the one case it refuses to resolve and reports instead. `CLAUDE.md` is gitignored, because it is generated. 2. **A directory's file describes that directory only.** What a parent or a child owns gets a link, never a second copy — the copy is what goes stale. If a sentence is true of the whole binary it belongs in `cli/AGENTS.md`; if it is true of one package it belongs in that package's file. 3. **Every file ends with its own maintenance contract** — the *Keeping this file true* section. It names the files the document covers and what kind of change obliges an edit. ### What keeps them true Nothing automatic, and that is a choice. Keeping these files honest is the job of whoever changes the code they describe, which is what the *Keeping this file true* section at the bottom of each one is for. A hook that nagged after every write was written and then removed: it would have fired for every user of the `kettle` plugin, on every edit in every repository they touched, to enforce a documentation convention that is this repository's and nobody else's. A plugin about issue tracking does not get to reach that far. `plugins/kettle/hooks/agents-sync.sh` stays, because it repairs the filesystem layout rather than asking anybody for anything: `AGENTS.md` a real file, `CLAUDE.md` a symlink to it. It cannot fail a tool call — it exits 0 on every path, including its own bugs, because documentation maintenance is not permitted to break a build. ## Development ```bash cd cli && make check # fmt, vet, test, go mod verify, build, docs — the gate cd cli && make help # install, dist, release ``` **There is no CI on the instance this lives on**, so `make check` is the only thing between a mistake and the tracker, and it is on whoever is committing to run it. Its last step is the repository's one mechanical documentation invariant: the command reference an agent reads inside the plugin is generated from the command registry the binary is built from. Everything else in this tree — including every `AGENTS.md` — is prose, and prose is held true by the hook above and by whoever is editing. ## Keeping this file true - **Scope:** the repository layout, the plugin/binary split, and the AGENTS.md convention itself. Every deeper subject belongs to a deeper file. - **Update it when** a top-level directory appears or goes, a plugin is added or removed, the marketplace catalog changes shape, or either hook's behaviour changes. - **Do not** put a command reference, a package's rules, or a skill's procedure here. Link to the file that owns it.