feat: add opt-in update-check hook for claude and cursor targets#12
Open
steve-calvert-glean wants to merge 4 commits into
Open
feat: add opt-in update-check hook for claude and cursor targets#12steve-calvert-glean wants to merge 4 commits into
steve-calvert-glean wants to merge 4 commits into
Conversation
Hosts don't reliably surface plugin updates: Claude Code's auto-update is off by default for third-party marketplaces, and Cursor has no nudge at all. When a target sets `updateCheck`, pluginpack now generates a session-start hook per emitted plugin that compares the build-stamped version against the latest git tag of the plugin repo and nudges the user when outdated — via Claude's user-visible `systemMessage`, or via agent context on Cursor (whose sessionStart hook has no user-facing output). The generated script follows update-notifier discipline: throttled to one `git ls-remote` per repo per 24h via a shared cache file, fail-open on any error/offline/missing git, and skippable via CI or PLUGINPACK_NO_UPDATE_CHECK=1. The hook registration merges into a source-authored hooks/hooks.json rather than clobbering it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- core.test.ts: build-level coverage for hook injection, per-plugin version overrides, merging into a source-authored hooks.json, and the reject paths (unsupported target, missing repository, script path collision, invalid hooks.json). - update-check.test.ts: unit tests for the hooks.json merge helpers, and end-to-end execution of the generated script under /bin/sh with a git shim, covering the throttle/cache, opt-out env vars, offline fallback, and semver tag filtering. - conformance.test.ts: enables updateCheck in the fixture config so the emitted cursor `hooks` manifest key and hooks.json validate against the existing oracles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
README: new "Update Check" section and config-reference rows for `updateCheck` (target-level) and the per-plugin opt-out. CONFORMANCE.md: record the two upstream hook behaviors the feature relies on (Claude SessionStart systemMessage, Cursor sessionStart additional_context) with sources and verification date. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- validate.ts: import UPDATE_CHECK_SCRIPT_PATH instead of re-hardcoding the path, so validation can't silently desync from generation. - update-check.ts: collapse the three separate `format === "claude"` branches into one per-format config table, and extract the duplicated per-plugin opt-out check into `pluginAllowsUpdateCheck`. - README: document that the generated hook is wired in independently of a plugin's `components` selection (mirrors the MCP precedent), since Cursor's manifest needs the `hooks` pointer set even when `components` excludes "hooks". - update-check.test.ts: add coverage for the throttle cache being shared across sibling plugins pointing at the same repository. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hosts don't reliably surface plugin updates: Claude Code's auto-update is off by default for third-party marketplaces, and Cursor has no update nudge at all. This adds an opt-in
updateChecktarget option that generates a session-start hook per emitted plugin (claude and cursor only — the only two targets that run plugin hooks).scripts/pluginpack-update-check.shplus ahooks/hooks.jsonregistration, merged into a source-authoredhooks/hooks.jsonwhen one exists rather than clobbering it.git ls-remoteper repo per 24h (cache shared across sibling plugins pointing at the same repo), fail-open on any error/offline/missing git, and skippable viaCIorPLUGINPACK_NO_UPDATE_CHECK=1.systemMessagewith the/plugin updatecommand to run. On Cursor (whosesessionStarthook has no user-facing output) it's injected as agent context instead.updateCheck: false; a config-load error ifupdateCheckis set oncopilot/antigravity/codex.Went through a two-axis code review (standards + spec-vs-plan) before opening this; the review-fixes commit addresses what came back (hardcoded path duplication, a repeated format branch, a duplicated opt-out guard, plus a missing sibling-repo-throttle test and a README gap around the
componentsinteraction).Test plan
npm run check(format, lint, typecheck, unit/integration tests, build, docs) passestests/update-check.test.tsexecutes the generated script under/bin/shwith a git shim — covers throttle/cache, corrupt-cache recovery, offline/no-git fallback, CI/env opt-outs, semver tag filtering, and the cross-plugin shared-cache casetests/core.test.tscovers build-level injection, per-plugin version overrides, merging into a source-authoredhooks/hooks.json, and all reject paths (unsupported target, missing repository, script collision, invalid hooks.json)tests/conformance.test.tsvalidates the emitted cursorhooksmanifest key against the vendored schemagleanwork/pluginpackrepo🤖 Generated with Claude Code