-
Notifications
You must be signed in to change notification settings - Fork 1
docs(playbook): add reintegration (consumer-adoption) section #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9756dd9
69d4772
7358e0b
4f47218
df82e0f
56bebfc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,8 +4,10 @@ How skills, hooks, and agents become reusable plugins in this marketplace. One p | |
| time: lift it out, make it work in plugin form and in any repo, build in configuration and extensibility, | ||
| vet it against best practices, then publish. | ||
|
|
||
| All schema and behavior claims below were verified against the official docs on 2026-06-22. Re-verify | ||
| fresh before acting — see `CLAUDE.md` "Fresh-docs mandate". | ||
| All schema and behavior claims below were verified against the official docs on 2026-06-22 (the | ||
| "Reintegration" section's marketplace-settings claims — `extraKnownMarketplaces` / `enabledPlugins` in a | ||
| project's `settings.json` — on 2026-06-29, against the discover-plugins "Configure team marketplaces" | ||
| guide). Re-verify fresh before acting — see `CLAUDE.md` "Fresh-docs mandate". | ||
|
|
||
| ## Intent | ||
|
|
||
|
|
@@ -105,6 +107,67 @@ claude --plugin-dir ./plugins/<name> | |
| - **Then ship.** Run `claude plugin validate` before opening a PR; after merge, consumers pull the | ||
| change with `/plugin marketplace update melodic-software`, gated by the `version` bump in `plugin.json`. | ||
|
|
||
| ## Reintegration — a consumer adopts the published plugin | ||
|
|
||
| The forward migration (above) ends at *publish*. The lifecycle closes when the source repo stops running | ||
| its in-repo copy and instead **consumes the published plugin** — one source of truth, and the repo | ||
| dogfoods the marketplace. Reintegration is a *consumer-side* change: adapt through the documented | ||
| extension points, never by teaching the plugin a consumer's specifics. | ||
|
|
||
| **The plugin is generic; the consumer's own seams restore its specifics.** Map each behavior the | ||
| in-repo hook had that the generalized plugin dropped to one of these, in order: | ||
|
|
||
| - **Kill switch / toggles** → the plugin's own env var, set in the consumer's `settings.json` `env` | ||
| (the name changes from the in-repo `HOOK_<OLD>_ENABLED` to the plugin's `HOOK_<PLUGIN>_ENABLED`). | ||
| - **Project conventions** → for a hook plugin, the consumer's own tool config files that the hook already | ||
| reads (`biome.json`, `.shellcheckrc`, `.editorconfig`, …) — that is where these plugins pick up project | ||
| conventions, **not** `CLAUDE.md`. (`CLAUDE.md` / `.claude/rules` reach only a plugin's *skill/agent* | ||
| components, which run in Claude's model context; hook scripts see only env vars and file-based config.) | ||
| - **Telemetry / observability** → the consumer's own **telemetry sink**. This is the key seam: the | ||
| plugin emits the generic telemetry envelope contract to `HOOK_TELEMETRY_SINK`, and the consumer's sink | ||
| script translates that envelope into the consumer's local observability shape. A consumer whose prior | ||
| hook emitted a different status or hook-identity (e.g. `status=error` on a surfaced violation, or a | ||
| legacy hook name) restores that contract **in its own sink**, by remapping the plugin's native envelope | ||
| (`status=ok` + populated `findings`) — not by changing the plugin. Before remapping, verify how the | ||
| consumer's observability actually keys events (e.g. on `status` vs a derived `exit_code`/findings count), | ||
| so the remap preserves the real contract rather than a guessed one. | ||
|
|
||
| If a genuine specific has **no** seam, that is a real plugin gap → add a declared extension | ||
| (`userConfig`, or a new env var consistent with the plugin's existing ones) — but only when it carries | ||
| real behavior, not cosmetic prose a consumer's `CLAUDE.md` already establishes. Resist adding config | ||
| surface to a published plugin for a single consumer's low-value nicety. | ||
|
|
||
| **Cutover checklist:** | ||
|
|
||
| 1. Register the marketplace in the consumer's `extraKnownMarketplaces` and enable the plugin in | ||
| `enabledPlugins` (project `settings.json`, so clones inherit it on trust — the interactive trust prompt | ||
| both registers and installs the enabled plugin). Headless/CI has no such prompt, and registering a | ||
| marketplace does not install its plugins, so do both explicitly: `claude plugin marketplace add <repo>` | ||
| then `claude plugin install <plugin>@<marketplace> --scope project` — otherwise the marketplace is known | ||
| but the plugin is absent, and step 3's verify edit would run with no plugin hook. | ||
| 2. Rewire the kill-switch env var to the plugin's name; keep the `HOOK_TELEMETRY_SINK` wiring and the | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This assumes the env var is derived from the plugin manifest name, but Useful? React with 👍 / 👎. |
||
| sink script (the bridge), adapting the sink for any observability-contract divergence. | ||
| 3. **Verify before retiring** the old hook (blue-green — keep it recoverable, but never run both on the | ||
| same edit). Matching `PostToolUse` hooks run concurrently, so leaving both registered would race two | ||
| formatters on the just-edited file (last-writer-wins clobbering, plus doubled telemetry and context) — | ||
| idempotence only makes *serial* re-runs converge, not concurrent writes safe. So **exactly one is | ||
| active at a time**: disable the in-repo hook by setting its kill-switch env var to `"false"` (or, if it | ||
| has none, removing its registration entry — `settings.json` is JSON, so toggling the value or removing | ||
| the entry is the edit, never a `//` comment). With the old hook off and the plugin enabled, edit a | ||
| governed file and confirm: the plugin formats/lints and surfaces findings, the telemetry sink receives | ||
| the expected envelope (so a broken remap is caught now, not when observability is next needed), and the | ||
| consumer's hard gate (commit hooks, CI) is untouched — those are independent of the edit-time hook. If | ||
| verification fails, **disable the plugin first, then re-enable the old hook** (always flip one off as you | ||
| turn the other on) and debug before retrying — so the two never run together and there is never a | ||
| no-hook gap. | ||
| 4. Only once verified, remove the in-repo hook's `settings.json` registration and delete the hook script | ||
| **and its test**. | ||
|
|
||
| **Bootstrap-direction caveat.** While a repo is still the harvest *source* (its hooks are mid-migration | ||
| out), reintegrating one plugin makes it consume one plugin while still running the rest in-repo — a mixed | ||
| state. Flip a repo from source to consumer deliberately, not incidentally, and ideally once the repo's | ||
| ported plugins can move together. | ||
|
|
||
| ## What to wait on / avoid for now | ||
|
|
||
| - Don't pre-build cross-plugin `dependencies` graphs until two plugins genuinely share a need. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In an existing Claude Code session, the headless install/enabled path here is followed immediately by step 3's edit, but installed/enabled plugins are not activated until the session reloads them; the official Discover plugins guide (https://code.claude.com/docs/en/discover-plugins) says, "After installing, run
/reload-pluginsto activate the plugin," and its CLI section repeats this for install/enable/disable. Without an explicit/reload-pluginsor restart before the verify edit, the old hook can be disabled while the plugin hook is still absent, causing a false fallback or a no-hook window.Useful? React with 👍 / 👎.