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>
54 lines
2.8 KiB
Markdown
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.
|