Files
marketplace/AGENTS.md
T
naudachu 01fb5a2703 feat: publish releases with this repository's own SDK code
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>
2026-08-12 01:01:27 +05:00

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.