Files
marketplace/plugins/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

54 lines
2.8 KiB
Markdown

# AGENTS.md — plugins/
One directory per plugin, and each is self-contained: **a plugin's root is its
directory here**, so `${CLAUDE_PLUGIN_ROOT}` resolves inside it and every path a
plugin uses stays relative to itself.
| plugin | what it is |
|---|---|
| [`kettle/`](kettle/AGENTS.md) | issues as local markdown, driven by the `kettle` binary in [`cli/`](../cli/AGENTS.md). Skills, a runner subagent, two hooks |
| [`tdl/`](tdl/AGENTS.md) | Three Dots Labs Go conventions as an enforceable rule set. One skill, no binary, no state |
## Adding one
Two edits, and nothing else in the repository needs to know:
1. a directory here holding `.claude-plugin/plugin.json`, plus whatever of
`skills/`, `agents/`, `hooks/`, `commands/` it needs;
2. one entry in [`.claude-plugin/marketplace.json`](../.claude-plugin/marketplace.json)
whose `source` is the path into this directory.
**The catalog entry's `name` and the directory name must match, and both must match
`plugin.json`.** They are three spellings of one identity: the catalog resolves a
`source` path, the manifest names the plugin, and the directory is what
`${CLAUDE_PLUGIN_ROOT}` becomes. A rename that misses one of the three installs a
plugin that cannot find its own files — which is exactly what happened when `tea`
became `kettle`.
The catalog's `description` is what somebody reads in `/plugin`; the manifest's is
what the installed plugin reports. Keep them saying the same thing.
## What a plugin may and may not do
- **A skill is prose an agent loads on demand.** Its frontmatter `description:` is
the only thing that decides whether it gets loaded at all, which makes it the one
line worth tuning against real failures — and the one line no generator may write.
- **Heavy reference material goes in `references/`**, not in the SKILL.md. The skill
says when to read it.
- **A hook must fail open.** Both of `kettle`'s exit 0 on every path, including
their own bugs: a plugin that breaks a user's Bash call because its documentation
helper crashed is worse than no plugin.
- **State belongs to the project, never to the plugin directory.** A plugin lives in
a versioned cache that changes path on every update; anything written inside it is
lost or invisible from the next project. This is not hypothetical — it is the bug
that motivated rewriting `kettle`'s Python scripts as a binary, and the whole
reason a project carries a `.kettle/` marker.
## Keeping this file true
- **Scope:** what a plugin directory is, how the catalog points at it, and the rules
common to all of them. The table names every plugin here.
- **Update it when** a plugin is added or removed or renamed, or when the catalog
gains a field a plugin author has to fill in.
- **Do not** describe an individual plugin's skills or design; each has its own file.