01fb5a2703
There is no CI: the instance has no act_runner and none is planned, so releases are cut by hand. That makes `make check` the only thing standing between a mistake and the tracker, and it is one command: gofmt, vet, the suite with the cache defeated, `go mod verify`, a vendored build, and `kettle gen skills --check`. The last one is the invariant worth having — the plugin's SKILL.md command reference is generated from the binary's registry, so a flag that changed cannot ship with documentation that recommends the old one. `cli/cmd/release` publishes to Gitea using the same SDK the binary already vendors, which is a pleasing thing to be able to say: nothing third-party handles the artifacts. It is a second binary rather than a `kettle` subcommand on purpose — `kettle`'s command tree is what generates the plugin's skills, so a verb there ships to every operator, and publishing a release is build infrastructure. It is idempotent end to end: an existing release for the tag is reused, an asset of the same name is replaced rather than doubled, and a retried run converges instead of duplicating. `make release` refuses three things, each with its own message: a dirty working tree, a TAG that is not what `git describe` reports, and a tag the remote does not have. A release built from uncommitted code is unreproducible and nobody finds out until they need to reproduce it. `kettle version` reports the stamp, the toolchain and the VCS revision. The default is `dev`, and a hand build says so and means it — a binary out of somebody's working tree is not a release and must not claim to be one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
91 lines
4.7 KiB
Markdown
91 lines
4.7 KiB
Markdown
# 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.
|