`ce:release-notes` Skill — Conversational Lookup Over Plugin Releases
Add a new slash-only skill `/ce:release-notes` to the `compound-engineering` plugin. Bare invocation summarizes the last 10 plugin releases; argument invocation answers a specific question with a release-version citation, optionally enriching from linked PR descriptions. Data source is the GitHub Releases API for `EveryInc/compound-engineering-plugin`, with `gh` CLI preferred and an anonymous `htt
Overview
ce:release-notes Skill — Conversational Lookup Over Plugin Releases
Overview
Add a new slash-only skill /ce:release-notes to the compound-engineering plugin. Bare invocation summarizes the last 10 plugin releases; argument invocation answers a specific question with a release-version citation, optionally enriching from linked PR descriptions. Data source is the GitHub Releases API for EveryInc/compound-engineering-plugin, with gh CLI preferred and an anonymous https://api.github.com/... fallback. Releases are filtered to the compound-engineering-v* tag prefix to exclude cli-v* and other sibling components.
The skill is the first in this plugin to implement a layered gh → anonymous-API state machine. The pattern is encapsulated in a single Python helper script so the SKILL.md prose stays focused on presentation.
Problem Frame
Per the origin document: the plugin ships multiple releases per week. Marketplace-installed users can't easily answer "what happened to the deepen-plan skill?" without scrolling GitHub release pages. This skill makes the release history queryable from inside Claude Code without leaving the workflow.
The skill is plugin-only (filters out cli-v*, coding-tutor-v*, marketplace-v*, cursor-marketplace-v* even when linked-versions sync forces a sibling bump) so users see only changes to the plugin they actually use.
Requirements Trace
- R1.
/ce:release-notesslash command vianame: ce:release-notesfrontmatter. - R2. Bare invocation → summary of recent releases.
- R3. Argument invocation → direct answer to user's question.
- R4. Slash-only in v1 (
disable-model-invocation: true); auto-invoke deferred to v2. - R5. GitHub Releases API; layered
ghpreferred, anonymous fallback. - R6. Filter to
compound-engineering-v*tag prefix only. - R7. No local caching, no
CHANGELOG.mdfallback. - R8. Graceful failure with actionable message when both access paths fail.
- R9. Summary mode renders the last 10 plugin releases.
- R10. Per-release format: version + date + release-please body, trimmed minimally (per-release implementation policy: soft 25-line cap with a "see full release notes" link in summary mode only — see Key Technical Decisions).
- R11. Each release links to its GitHub release URL.
- R12. Query mode searches a fixed window of 20 plugin releases.
- R13. Confident match → narrative answer with version citation; PR enrichment via
gh pr view. - R14. No confident match → say so plainly + releases-page link.
Scope Boundaries
- Out of scope: CLI / coding-tutor / marketplace / cursor-marketplace release coverage (R6).
- Out of scope: Unreleased changes from the open release-please PR.
- Out of scope: Local caching or
CHANGELOG.mdparsing. - Out of scope: Per-PR or per-commit drill-down as a primary surface (query mode may follow PR links per R13, but it does not expose PR-level navigation).
- Out of scope: Customization flags for window size or output format in v1.
- Out of scope:
mode:headlessprogrammatic invocation in v1 (see Key Technical Decisions —disable-model-invocation: trueblocks Skill-tool calls anyway, so headless support would be dead code).
Deferred to Separate Tasks
docs/solutions/write-up of thegh→ anonymous-API fallback pattern: Once this skill ships, document the layered-access recipe as a reusable solution underdocs/solutions/integrations/ordocs/solutions/skill-design/so future skills don't reinvent it. This is documentation work, not part of the skill's behavior, and can land in a follow-up PR.- v2 auto-invocation gate definition: If/when v2 is reconsidered, define the trigger (≥N explicit user requests OR a time-box review). Tracked as the deferred question carried over from the origin document.
Context & Research
Relevant Code and Patterns
plugins/compound-engineering/skills/ce-update/SKILL.md— closest precedent: usesgh release list --repo EveryInc/compound-engineering-plugin --limit 30 --json tagName --jq '[.[] | select(.tagName | startswith("compound-engineering-v"))][0]...'for the exact tag-prefix filter we need. Uses sentinel-on-failure pattern (|| echo '__SENTINEL__'). Setsce_platforms: [claude]because it reads a Claude-only cache — we deliberately do not inherit that field so this skill ships to all targets.plugins/compound-engineering/skills/ce-pr-description/SKILL.md— precedent for runtimegh pr view --json title,body,url,...calls. Used here for query-mode PR enrichment.plugins/compound-engineering/skills/resolve-pr-feedback/scripts/get-pr-comments— establishedscripts/helper pattern; relative-path invocation; no${CLAUDE_PLUGIN_ROOT}.plugins/compound-engineering/skills/ce-demo-reel/scripts/capture-demo.py— established Python helper convention:#!/usr/bin/env python3shebang, executable bit set, invoked from SKILL.md via relative path.plugins/compound-engineering/skills/document-review/SKILL.md— establishedmode:*argument-token stripping rule, adopted here verbatim for argument parsing.plugins/compound-engineering/skills/changelog/SKILL.md— adjacent skill (witty marketing changelog of recent PRs); confirmed not redundant with this skill's version-aware release lookup.src/converters/claude-to-codex.ts(around line 183-198) —name.startsWith("ce:")triggers special Codex workflow-prompt duplication. Choosing the colon form is intentional and creates a.codex/prompts/ce-release-noteswrapper on Codex (handled by the existing converter).tests/frontmatter.test.ts— automatically validates the new SKILL.md YAML; no test wiring needed.scripts/release/validate.tsandbun run release:sync-metadata— skill-count sync pipeline. May need to runbun run release:sync-metadataonce the new skill directory exists.
Institutional Learnings
docs/solutions/workflow/manual-release-please-github-releases.md— confirms GitHub Releases is the canonical release-notes surface;CHANGELOG.mdis a pointer only;compound-engineering-v*is the correct tag prefix for plugin releases; linked-versions can produce acompound-engineering-v*bump with no plugin-semantic change (the helper passes the body through; rendering tolerates this naturally).docs/solutions/best-practices/prefer-python-over-bash-for-pipeline-scripts-2026-04-09.md— strong guidance to write the multi-tool fallback orchestration in Python, not bash. macOS bash 3.2 +set -euo pipefailis a footgun for thegh-fails-then-fallback control flow.docs/solutions/skill-design/script-first-skill-architecture.md— the helper produces structured data, SKILL.md presents it. Keeps the model from spending tokens on parsing.docs/solutions/skill-design/git-workflow-skills-need-explicit-state-machines-2026-03-27.md— capture both stdout and exit code; treat "gh missing", "gh unauthed", "rate-limited" as state transitions, not errors.docs/solutions/codex-skill-prompt-entrypoints.md— Codex skill frontmatter supports onlynameanddescription;argument-hintanddisable-model-invocationare dropped on the Codex side; the colon-formnametriggers a Codex prompt wrapper.docs/solutions/integrations/colon-namespaced-names-break-windows-paths-2026-03-26.md— the established convention: directory uses dash form (ce-release-notes/), frontmatter uses colon form (ce:release-notes). Converter handles sanitization.AGENTS.md"Platform-Specific Variables in Skills" and "File References in Skills" — relative paths only, no${CLAUDE_PLUGIN_ROOT}without a fallback, no cross-skill references.
External References
None. Local patterns + institutional learnings cover this fully. The skill sets a precedent for the gh → anonymous-API fallback pattern; documenting it as a new solution doc is the deferred-to-separate-task above.
Key Technical Decisions
- Frontmatter
name: ce:release-notes(colon form): This is a user-facing slash-invoked workflow surface, not an internal supporting utility. The colon form matches the discoverability story for/ce:release-notesand opts into the Codex workflow-prompt path (which auto-creates.codex/prompts/ce-release-notes). The dash-form precedent (ce-update,ce-pr-description) is reserved for skills that act as internal utilities or are invoked from inside other workflows. - No
ce_platformsfield: The skill is designed to work everywhere — Claude Code, Codex, Gemini CLI, OpenCode. No Claude-only assumptions in the implementation. Omitting the field lets the converter pipeline ship to all targets. - Python helper with all retry/fallback logic; SKILL.md only presents: Per the script-first-architecture and Python-over-bash learnings. The helper exposes a single JSON contract; SKILL.md never branches on transport details. Single source of truth for tag filtering, state machine, and error shapes.
- Helper is invoked via
python3 scripts/list-plugin-releases.py ...(explicit interpreter, relative path): Explicitpython3is more portable than relying on shebang resolution across platforms. The shebang and execute bit are still set (matching thece-demo-reelpattern) so the script works as a standalone tool in dev too. - Hardcoded repo reference inside the helper:
EveryInc/compound-engineering-pluginlives in the helper as a constant. Single point of change if the plugin moves repos. Reading from.claude-plugin/plugin.jsonwas considered and rejected — that file's location is platform-dependent and adds complexity for a one-time-edit cost. - JSON contract between helper and SKILL.md (defined under "Output Structure" → see High-Level Technical Design): Lock the shape so the two pieces don't drift. Helper pre-extracts linked PR numbers from release bodies (regex
\\[#(\\d+)\\]matching the markdown-link form release-please uses, e.g.[#568](https://github.com/.../issues/568)) so SKILL.md decides which PRs to follow without re-parsing markdown. Verified againstcompound-engineering-v2.67.0release body on 2026-04-17. - Fetch-buffer >> render-window: Summary mode fetches 40 raw releases (not 10) and filters to the first 10 plugin releases; query mode fetches 60 and filters to 20. Sibling tags (
cli-v*,coding-tutor-v*,marketplace-v*,cursor-marketplace-v*) interleave with plugin tags. The 4× multiplier (40 raw → 10 rendered) and 3× multiplier (60 raw → 20 rendered) are sized so that even if 75% of the fetch buffer is sibling-tag noise, the render window still fills. If sibling release cadence shifts dramatically and the buffer no longer fills the window, raise the multiplier — keep the same shape, just enlarge the constants. R12's "fixed cap, no expansion" applies to the search/render window, not the fetch buffer. - State machine, silent fallback: The helper attempts
ghfirst; on any failure (binary missing, unauthed, errored, timed out) it transparently tries the anonymous API. The transport choice is recorded in the JSON contract (source: "gh" | "anon") but is not surfaced to the user — falling back is a stability signal, not a user-facing event. Per R8, a hard error only fires when both paths fail, and the message points to the GitHub releases URL as the manual fallback. - Per-release body cap in summary mode (soft 25-line cap): R10's "trimmed minimally" rule defers per-release-size policy to implementation; this is the implementation choice. When a single release body exceeds 25 rendered lines, the skill shows the first 25 lines plus a "— N more changes, see full release notes →" link. Truncation must be markdown-fence aware: if the 25-line cut would land inside an open code fence (an odd number of triple-backtick lines above the cut), close the fence on the truncated output before appending the "see more" link, so renderers don't swallow following content. Query mode keeps full bodies to preserve narrative-synthesis fidelity.
- Confidence judgment by the model, not by the helper: The helper returns raw release bodies; SKILL.md instructs the model to read them, judge whether a confident match exists, and route to R13 or R14. Substring matching was considered and rejected — it would miss renames (e.g., a query about
deepen-planwon't substring-match the release that introducedce-debug). The model is the right judge. - Multiple matching releases policy: Cite the most recent matching release as the primary citation; reference up to 2 older matches inline as "previously: vX.Y.Z, vA.B.C". Prevents inconsistent citation counts.
- PR enrichment is best-effort: When the matched release body has no
(#N)reference orgh pr viewfails, the skill answers from the release body alone and adds a one-line note ("PR could not be retrieved — answer is based on release notes alone"). It does not refuse. - No
mode:headlesssupport in v1: R4 mandatesdisable-model-invocation: true, which blocks Skill-tool calls from other skills. Headless support would be dead code. The argument parser still stripsmode:*tokens (per thedocument-reviewconvention) so a straymode:foodoesn't get treated as a query string, but the parser does not branch on them. - Argument parsing rule (locked):
args.strip()after stripping allmode:*tokens. Empty string → summary mode. Non-empty → query mode. Version-like inputs (2.65.0,v2.65.0,compound-engineering-v2.65.0) are treated as query strings — they're not a third "lookup-by-version" mode. - Release-please format drift: Accept silent degradation if release-please's
Features/Bug Fixesgrouping changes. The helper passes raw bodies through; rendering tolerates whatever markdown comes back. Low priority — the format has been stable for the project's lifetime.
Open Questions
Resolved During Planning
- Truncation policy for long bodies? → Soft 25-line cap in summary mode with "see full release notes" link; full bodies in query mode.
- Anonymous fallback implementation? → Python
urllib.requestfrom stdlib (no extra dependencies), notcurl+jq. - "Confident match" criterion? → Model judgment, not substring or embedding match.
- Repo reference: hardcoded vs. derived? → Hardcoded in helper.
- Release-please format drift handling? → Accept silent degradation.
mode:headlesssupport? → No in v1; strip-but-don't-act on the token.- Frontmatter name form (colon vs. dash)? → Colon (
ce:release-notes), matching user-facing workflow convention. - Helper script language? → Python (per institutional learning).
- Where does the gh→anon fallback live? → Entirely inside the helper;