Skip to content

Commit 55ed5ea

Browse files
authored
chore: add agent skills for CLI releases (#272)
- Add skills/hookdeck-cli-release with checklist, SemVer checks, CI gates, gh release create flow (temp notes file), and contributor policy - Symlink .cursor/skills and .claude/skills to repo-root skills/ - Add CLAUDE.md (stop ignoring); point agents to AGENTS.md and skills/ - Document agent skills layout in AGENTS.md; link from README Releasing - Remove CLAUDE.md from .gitignore so it ships with the repo Made-with: Cursor
1 parent 73df929 commit 55ed5ea

8 files changed

Lines changed: 236 additions & 3 deletions

File tree

.claude/skills

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../skills

.cursor/skills

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../skills

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,3 @@ test-scripts/.install-test/
2424

2525
# Claude Code temporary worktrees
2626
.claude/worktrees/
27-
28-
# Claude Code project notes (local only)
29-
CLAUDE.md

AGENTS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,4 +511,13 @@ default:
511511
512512
---
513513
514+
## Agent skills
515+
516+
- **Location:** Repo-specific agent skills live under **`skills/`** at the repository root (e.g. `skills/hookdeck-cli-release/`).
517+
- **Cursor / Claude Code:** `.cursor/skills` and `.claude/skills` are **symlinks** to `../skills` so both tools load the same tree. Do not replace the whole `.cursor` directory with a symlink—only `skills`, so `.cursor/rules/` and similar can stay as normal files.
518+
- **Windows:** Git must create symlinks correctly (`core.symlinks` / Developer Mode). If symlinks are missing after clone, recreate them (`mklink /D` on Windows, or copy `skills/` into `.cursor/skills` and `.claude/skills` as a fallback).
519+
- **Releases:** For cutting GitHub releases, tags, npm/beta publish flow, and drafting release notes, use **`skills/hookdeck-cli-release/SKILL.md`**; human-facing steps remain in **README.md § Releasing**.
520+
521+
---
522+
514523
Following these guidelines ensures consistent, maintainable CLI commands that provide an excellent user experience while maintaining architectural consistency with the existing codebase.

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Hookdeck CLI — Claude / agent context
2+
3+
Read **[AGENTS.md](AGENTS.md)** first for project structure, testing, and CLI conventions.
4+
5+
Repo-specific agent workflows (e.g. releases) live under **[skills/](skills/)** — see `skills/hookdeck-cli-release/` for cutting GitHub releases and drafting release notes.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,8 @@ Install output is written to `test-scripts/.install-test/` (gitignored).
14041404

14051405
This section describes the release process for the Hookdeck CLI.
14061406

1407+
Maintainers using AI assistants: see **[skills/hookdeck-cli-release/](skills/hookdeck-cli-release/)** for the release skill (automation details and release-note workflow).
1408+
14071409
## Release Process
14081410

14091411
The release workflow supports tagging from **ANY branch** - it automatically detects which branch contains the tag. This means you can create beta releases directly from feature branches for testing before merging to `main`.
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
---
2+
name: hookdeck-cli-release
3+
description: >-
4+
Guides maintainers through Hookdeck CLI releases (stable GA, beta from main,
5+
beta from feature branches) and user-centric GitHub release notes. Validates
6+
proposed versions against SemVer from the actual change set (e.g. breaking
7+
changes require a major bump). Use when cutting a release, publishing a tag,
8+
drafting release notes, choosing vMAJOR.MINOR.PATCH, GoReleaser, npm publish,
9+
pre-releases, following the release checklist, or `gh release create`.
10+
---
11+
12+
# Hookdeck CLI — release workflow
13+
14+
## Canonical documentation
15+
16+
Follow **[README.md](../../README.md) § Releasing** for human-oriented steps (GitHub UI alternative, install commands for beta/stable).
17+
18+
**Agents:** perform the **publish** step with the **GitHub CLI** (`gh`) — see **Publish with GitHub CLI (`gh`)** below (temp notes file → `gh release create` → remove temp file).
19+
20+
This skill adds **how automation works**, **release note expectations**, and a **research loop** for drafting notes.
21+
22+
## Agent checklist (end-to-end)
23+
24+
Follow **in order**. Treat items with **gate** as blocking unless the maintainer explicitly overrides.
25+
26+
- [ ] **Release shape:** GA from **`main`** vs beta from **`main`** vs beta from **feature branch** — matches [README § Releasing](../../README.md) and maintainer intent.
27+
- [ ] **`PREV_TAG` / `NEW_TAG`:** Confirmed (or proposed and agreed); baseline tag is correct for the line of development (e.g. last GA vs beta series).
28+
- [ ] **Change set:** Reviewed `git log PREV_TAG..HEAD` (and diff if needed); changes grouped for **user-facing** release notes (see **Research loop**).
29+
- [ ] **SemVer gate:** Proposed `NEW_TAG` matches **minimum** MAJOR/MINOR/PATCH for the delta (see **SemVer: validate the proposed version**). Stop and realign if under-bumped.
30+
- [ ] **Release notes:** Draft complete (see **Drafting release notes** and [references/release-notes-template.md](references/release-notes-template.md)); includes **Full Changelog** compare link; **contributor shout-outs only when warranted** (see that section).
31+
- [ ] **CI gate:** Latest commit on the **target branch** has **green** GitHub checks (mandatory for GA on `main`; required for betas on the branch being tagged).
32+
- [ ] **Approval:** Maintainer signed off on tag name, notes, and branch — no unilateral surprise tags.
33+
- [ ] **Publish:** Write notes to a **temporary file**, run **`gh release create`** (see **Publish with GitHub CLI (`gh`)**), then **`rm`** the temp file. Use `--prerelease` for betas. (Humans may still use the GitHub UI per README.)
34+
- [ ] **Post-publish (optional):** Confirm the **`release`** workflow in Actions completed successfully for the new tag.
35+
36+
For commit-level detail while working through the checklist, use the **Research loop** below.
37+
38+
## What triggers a release?
39+
40+
- **[.github/workflows/release.yml](../../.github/workflows/release.yml)** runs on **`push` of tags** matching `v*` (not on ordinary branch pushes).
41+
- Publishing a release in the GitHub UI (with a new tag) or `git push origin vX.Y.Z` both create that tag push and start the workflow.
42+
43+
## What the workflow does (high level)
44+
45+
1. **GoReleaser** (macOS, Linux, Windows jobs): builds binaries/archives, updates distribution channels per [.goreleaser/*.yml](../../.goreleaser/mac.yml) (Homebrew, Scoop, Docker, GitHub release artifacts). Config uses `release.mode: append` and `changelog.disable: true`**GoReleaser does not write the release note body from git**; maintainers supply or edit the GitHub release description.
46+
2. **`publish-npm` job**: Determines which branch contains the tag (prefers `main` / `master`, else first matching remote branch), checks out that branch, sets `package.json` version from the tag, builds npm binaries via GoReleaser, runs **`npm publish`** with `latest` for stable semver or a derived tag (e.g. `beta`) for pre-releases (see workflow `npm_tag` step).
47+
48+
## Stable (GA) release
49+
50+
- **Humans (README):** GitHub Releases → Draft → new tag `vM.m.p` → target **`main`** → notes → Publish.
51+
- **Agents:** After gates pass, use **`gh release create`** with `--target main` and `--notes-file` (see **Publish with GitHub CLI (`gh`)**).
52+
- **Do not publish a GA release until CI is green for `main`:** the **latest commit on `main`** must show successful checks in GitHub (same bar as README: ensure tests pass on `main`). Verify on the **Actions** tab (filter branch `main`, confirm the run for the tip of `main` succeeded) or via the commit’s status on github.com.
53+
- **CLI check (optional):** after `git fetch origin main`, confirm combined status is `success` for `origin/main` (replace owner/repo if forked):
54+
55+
```bash
56+
SHA=$(git rev-parse origin/main)
57+
gh api "repos/hookdeck/hookdeck-cli/commits/${SHA}/status" --jq .state
58+
```
59+
60+
Do **not** tag or publish GA if this is `failure` or still `pending` for required work.
61+
62+
- Stable tags drive **`latest`** on npm, stable Homebrew/Scoop formulas, Docker `latest`.
63+
64+
## Pre-release (beta)
65+
66+
- **From `main`:** Tag like `v1.3.0-beta.1`, target `main`, mark **pre-release** (`gh release create ... --prerelease`). Good for broad beta testing. **Still verify `main` is green** (same CI check as GA) before tagging.
67+
- **From a feature branch:** Same tag pattern; **`--target <feature-branch>`** so the workflow builds that tip. **Verify CI is green for that branch’s latest commit** before tagging. Add notes on **what to test** (betas often ship with minimal notes; still document intent).
68+
- Install paths for beta: see README (npm `@beta`, `hookdeck-beta` brew/scoop, Docker image tag — **not** `latest` for beta).
69+
70+
## Publish with GitHub CLI (`gh`)
71+
72+
**Agents should create the release with `gh`**, not only push a bare tag. That creates the GitHub Release (with notes) and the tag together, which matches how maintainers expect the **`release`** workflow to run.
73+
74+
1. **Create a temp file for notes** (never commit it). Register cleanup so the file is removed even if `gh` fails:
75+
76+
```bash
77+
NOTES_FILE="$(mktemp "${TMPDIR:-/tmp}/hookdeck-cli-release-notes.XXXXXX.md")"
78+
trap 'rm -f "$NOTES_FILE"' EXIT
79+
```
80+
81+
2. **Write** the final markdown body to `"$NOTES_FILE"` (same content you would paste in the GitHub UI).
82+
83+
3. **Create the release** (run from a clone of `hookdeck/hookdeck-cli`, or use `--repo` as below):
84+
85+
**Stable GA from `main`:**
86+
87+
```bash
88+
gh release create "vM.m.p" \
89+
--repo hookdeck/hookdeck-cli \
90+
--target main \
91+
--title "vM.m.p" \
92+
--notes-file "$NOTES_FILE"
93+
```
94+
95+
**Pre-release (beta):** add `--prerelease`. **Feature branch:** set `--target <branch>` instead of `main`.
96+
97+
4. **Cleanup:** With `trap` above, the temp file is deleted on shell exit. If you did not use `trap`, run `rm -f "$NOTES_FILE"` after `gh` succeeds.
98+
99+
**Requirements:** `gh` installed and authenticated (`gh auth login`). Do not put secrets in the notes file.
100+
101+
### Fallback: tag without `gh`
102+
103+
If `gh` is unavailable, a maintainer may use **README** flow (UI) or:
104+
105+
```bash
106+
git checkout <branch>
107+
git tag vX.Y.Z[-beta.N]
108+
git push origin vX.Y.Z[-beta.N]
109+
```
110+
111+
Then **edit the GitHub release** to add notes, or create the release in the UI so assets and changelog align with team practice.
112+
113+
## SemVer: validate the proposed version
114+
115+
The user may suggest a tag (e.g. `v2.0.1`). **Always sanity-check it** against what actually changed since **`PREV_TAG`** (usually the last **GA** tag on that line of development—confirm with the maintainer for long beta series).
116+
117+
**Interpret SemVer for this CLI (user-facing contract):**
118+
119+
| Change since `PREV_TAG` | Bump | Examples |
120+
|-------------------------|------|----------|
121+
| **Breaking** — requires users to change scripts, configs, or habits | **MAJOR** | Removed or renamed commands/flags; different defaults that break automation; dropped or incompatible config file fields; incompatible change to documented machine-readable output |
122+
| **New capability**, backward compatible | **MINOR** | New commands or flags; new subcommands; additive behavior; deprecations **announced** but old path still works |
123+
| **Fixes / internal / docs-only** (no new user-facing capability, no break) | **PATCH** | Bug fixes; telemetry/CI; dependency bumps with no CLI contract change; help text clarifications |
124+
125+
**Signals (hints only):** Conventional commits with `BREAKING CHANGE:` / `feat!:` / `fix!:` suggest severity—still **read the diff and release notes**; commits can be mis-tagged.
126+
127+
**Pre-releases** (`v2.1.0-beta.1`): the **base version** (`2.1.0`) must still follow the table above relative to the last GA. A beta for a **major** rewrite should be `v3.0.0-beta.1`, not `v2.5.0-beta.1`, if the delta includes breaking changes vs `v2.x` GA.
128+
129+
**Agent behavior:**
130+
131+
1. After categorizing changes for release notes, state the **minimum** SemVer bump required.
132+
2. Compare to the user’s proposed `NEW_TAG`. If they conflict (e.g. patch tag but breaking changes), **do not treat the user’s version as authoritative**—explain the mismatch and recommend the correct `vMAJOR.MINOR.PATCH` (and pre-release suffix if applicable).
133+
3. If ambiguous (unclear whether a change breaks callers), **ask the maintainer** before tagging.
134+
135+
## Drafting release notes (user-centric)
136+
137+
Use **[references/release-notes-template.md](references/release-notes-template.md)** as a starting skeleton.
138+
139+
**Patterns observed in this repo:**
140+
141+
- **Large GA (e.g. v2.0.0):** `Summary``Breaking changes / migration``New features` (subsections per area) → `Improvements / behavior changes` → optional `Internal`.
142+
- **Feature release (e.g. v1.9.0):** `## Features` with detailed bullets + **Full Changelog** compare link.
143+
- **Patch (e.g. v1.9.1):** `## Fixes`, `## Updates`, PR links with authors + **Full Changelog**.
144+
145+
Always include a **Full Changelog** line:
146+
147+
`https://github.com/hookdeck/hookdeck-cli/compare/<prev_tag>...<new_tag>`
148+
149+
**Contributors / shout-outs:** Do **not** add a generic “thanks to all contributors” block every release. **Regular maintainers and repeat contributors do not need a call-out.** Only include a contributor section when:
150+
151+
- There are **new contributors** first shipping in this release (welcome them by name/GitHub handle), and/or
152+
- Someone made an **exceptionally large** contribution worth highlighting for this specific release.
153+
154+
Otherwise omit the **Contributors** section entirely.
155+
156+
## Research loop (agent or maintainer)
157+
158+
1. **Tags:** Confirm `PREV_TAG` and `NEW_TAG` with the user (or `git describe --tags --abbrev=0` on the release branch). For beta series, baseline may be last **GA** tag.
159+
2. **Commits:** `git log PREV_TAG..HEAD --oneline` and read full messages. Treat **Conventional Commits** (`feat:`, `fix:`, `BREAKING CHANGE:`) as hints only — rewrite for **user impact** (commands, flags, migrations).
160+
3. **Group:** Merge related commits; call out breaking changes and required user actions explicitly.
161+
4. **SemVer check:** Using **SemVer: validate the proposed version**, classify the delta since `PREV_TAG` and verify the proposed `NEW_TAG` matches the required **MAJOR / MINOR / PATCH** bump. Flag mismatches before any tag or release.
162+
5. **PRs / links:** Map commits to PRs (`gh pr list`, GitHub compare UI) for **PR links in the notes**. Use **Contributors** shout-outs only per **Drafting release notes** (new contributors or exceptional contribution—not every author every time).
163+
6. **Sanity:** Skim diff or `REFERENCE.md` / user-facing help if commits are unclear.
164+
7. **CI on GitHub (gate):** Before tagging, confirm the **branch you will release** (`main` for typical GA, or the feature branch for a branch beta) has **green checks on the latest commit** in GitHub Actions / commit status. For GA from `main`, treat this as **mandatory**; do not proceed on red or unknown pending required checks.
165+
166+
## Safety and governance
167+
168+
- **CI:** Do not cut a **stable GA** release unless **`main`’s latest run of checks** in GitHub is green (see **Stable (GA) release** and research step 7). For betas, require green CI for the **target branch** you are tagging.
169+
- **SemVer:** Do not publish a tag that **under-bumps** the version for the change set (e.g. patch release that includes breaking CLI changes); resolve with the maintainer first.
170+
- Do not push surprise tags; respect branch protection and team process.
171+
- Never put secrets or tokens in release notes or skill content.
172+
173+
## Related files
174+
175+
| Topic | Location |
176+
|--------|-----------|
177+
| Maintainer steps, install commands | [README.md § Releasing](../../README.md) |
178+
| CI entrypoint | [.github/workflows/release.yml](../../.github/workflows/release.yml) |
179+
| Artifacts / brew / scoop / docker | [.goreleaser/](../../.goreleaser/) |
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Release notes template (Hookdeck CLI)
2+
3+
Copy and fill in for the GitHub release description (e.g. write into the temp file used with `gh release create --notes-file`). Adjust heading levels (`##` vs `###`) to match recent GA style (v2.0.0 used `###` subsections) or smaller patch style (v1.9.x used `##`).
4+
5+
## Summary
6+
7+
<!-- 2–4 sentences: who benefits, scope since previous tag (e.g. since `v1.9.1`). -->
8+
9+
## Breaking changes / migration
10+
11+
<!-- Omit or state "None" for patch releases if accurate. For each item: what changed, why, what users must update (scripts, flags, CI). -->
12+
13+
## New features
14+
15+
<!-- Group by area/command. User-facing language; mention important flags. -->
16+
17+
## Fixes
18+
19+
<!-- Optional: merge into "Improvements" for tiny releases. -->
20+
21+
## Improvements / behavior changes
22+
23+
<!-- UX, defaults, performance, reliability visible to users. -->
24+
25+
## Internal / reliability / infrastructure
26+
27+
<!-- Optional: refactors, test/CI, dependency bumps with low user-visible impact. -->
28+
29+
## Contributors (optional)
30+
31+
<!-- Omit this entire section for most releases.
32+
33+
Include ONLY when:
34+
- There are **new contributors** whose first merged work ships in this release — welcome them by name / @handle, OR
35+
- Someone made an **exceptionally large** contribution worth a specific shout-out for this release.
36+
37+
Do NOT add generic "thanks to everyone who contributed" for regular maintainers or repeat contributors. -->
38+
39+
**Full Changelog**: https://github.com/hookdeck/hookdeck-cli/compare/PREV_TAG...NEW_TAG

0 commit comments

Comments
 (0)