AGENTS.md · diff
git:20260724.f78514f to git:20260918.f9f16ae
1 added, 1 removed. Audit A to A.
# Agent instructions
## Repository layout
This repo is a Claude Code plugin (a "marketplace" with a single plugin).
- `skills/` — one directory per skill (`developer`, `fix-pr`, `implement-issue`,
`review-pr`, `setup-developer-skills`), each with its own `SKILL.md`.
- `agents/` — worker agent definitions as top-level `.md` files
- (`code-author.md`, `diff-reviewer.md`, `dispatcher.md`).
+ (`code-author.md`, `diff-reviewer.md`).
- `hooks/` — `hooks.json` plus the hook scripts it registers. Claude Code
auto-loads `hooks/hooks.json` from this standard path, so **do not** also
name it in `plugin.json`'s `hooks` key: that registers the same file twice
and the whole plugin fails to load. The manifest key is only for hook files
kept somewhere else.
- `tests/` — regression tests for the bundled scripts (plain bash, no
framework; run directly, e.g. `bash tests/cleanup-worktrees.test.sh`).
- `.claude-plugin/plugin.json` — the plugin manifest and **canonical version**.
- `.claude-plugin/marketplace.json` — marketplace entry; points at `./`. The
schema *allows* a per-plugin `version`, but we deliberately omit it so
`plugin.json` stays the single source of truth — **do not add one here**.
- `CHANGELOG.md` — user-facing history (see release process below).
- `BACKLOG.md` — unscheduled ideas, with what blocks each one. Not a roadmap;
entries leave when they ship or stop being good ideas.
## Conventions
- **Commits** follow [Conventional Commits](https://www.conventionalcommits.org)
(`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`…).
- Agent definitions live **only** in `agents/`, at the plugin root, where
Claude Code auto-loads them. There is no second copy to keep in sync.
- **Never** add a `Co-Authored-By: Claude` / Anthropic trailer to commits.
- The version lives in **one place** (`.claude-plugin/plugin.json`); nothing
else should hard-code it.
## Releasing a new version
Any change that puts a **bare** `X.Y.Z` in `.claude-plugin/plugin.json` **must**
update the changelog and publish the release — never set one without completing
every step below. Setting a `-next` pre-release (step 9) is the one exception:
it publishes nothing.
Versioning follows [Semantic Versioning](https://semver.org). While the project
is `0.x`, every GitHub release is a **pre-release** (there is no stable/`Latest`
release until `1.0.0`).
Development happens on the **`next` branch**, whose `version` is the release it
is working **toward**, marked as a semver pre-release: `0.16.0-next` is the
unreleased run-up to `0.16.0`, and sorts after `0.15.0` but before `0.16.0`.
The suffix exists so `claude plugin list` and the `/plugin` UI say out loud
that the loaded build is not the published one. Only the release steps below
take it off. The target number is a forecast, not a promise — if the cycle's
scope turns out to be a patch rather than a minor, correct the string when you
release (step 1). Try it out with `scripts/plugin-mode.sh dev` (this checkout,
uncommitted edits included — this machine only) or `scripts/plugin-mode.sh
next` (the pushed `next` branch on GitHub — works the same on any machine).
`scripts/plugin-mode.sh prod` switches back to the published release.
Changelog entries land under the `## [Unreleased]` heading as you go; a release
promotes that section to the new version.
### Steps
1. **Set the version** in `.claude-plugin/plugin.json` to the release `X.Y.Z` —
a bare number, dropping the `-next` suffix `next` carries between releases.
Usually that is just `0.16.0-next` → `0.16.0`, but if the cycle's actual
scope no longer matches what the branch was forecasting, set the number the
changes earn and ignore the forecast.
2. **Update `CHANGELOG.md`** ([Keep a Changelog](https://keepachangelog.com)
format):
- Rename the `## [Unreleased]` heading to `## [X.Y.Z] - YYYY-MM-DD`, then add
a fresh empty `## [Unreleased]` section above it for the next cycle.
- Group entries under `Added` / `Changed` / `Fixed` / `Documentation`.
- Update the link references at the bottom of the file: repoint
`[Unreleased]` to `.../compare/vX.Y.Z...next` and add the matching
`[X.Y.Z]: https://github.com/sgomez/developer-skills/releases/tag/vX.Y.Z`
3. **Commit** the version bump and changelog together on `next`, e.g.
`git commit -m "feat: <summary> (X.Y.Z)"`.
4. **Merge `next` into `main`** — publishing always goes through `main`:
```sh
git switch main && git merge --ff-only next
```
Keep it a fast-forward so `main` lands the exact bump commit (rebase `next`
onto `main` first if it has diverged).
5. **Tag** the version-bump commit on `main` with an **annotated** tag:
`git tag -a vX.Y.Z -m vX.Y.Z`. It must be annotated — `--follow-tags` in
the next step pushes annotated tags only, and silently ignores lightweight
ones.
6. **Push** `main` and the tag: `git push origin main --follow-tags`. Confirm
the tag actually landed: `git ls-remote --tags origin vX.Y.Z`.
7. **Publish the GitHub release**, using that version's changelog section as the
body and marking it as a pre-release while on `0.x`:
```sh
gh release create vX.Y.Z --title vX.Y.Z --notes-file <section.md> \
--prerelease --latest=false --verify-tag
```
8. **Continue development on `next`**: `git switch next && git merge --ff-only main`
so both branches share the release commit before the next cycle.
9. **Reopen the cycle on `next`**: set `version` to the *next* anticipated
release with the suffix back on — after `0.15.0` ships, that's
`0.16.0-next` — and commit it alone: `git commit -m "chore: reopen next
(0.16.0-next)"`. `next` now sits one commit ahead of `main`; the next
release's step 4 fast-forwards both this commit and the new bump onto
`main`, which is why step 1 sets the version outright rather than
incrementing whatever string it finds.
The git tag `vX.Y.Z` must point at the exact commit that set `version` to the
bare `X.Y.Z` in `.claude-plugin/plugin.json` — not at the `X.Y.Z-next` reopen
commit that follows it, and not at the pre-release run-up.