Overview
Add plugin lifecycle management to ToolHive. A plugin is the "bundle of primitives" unit pioneered by Claude Code — a directory declared by a .claude-plugin/plugin.json manifest bundling slash commands, subagents, Agent Skills, hooks, MCP server configs, and LSP servers. ToolHive will let users build a plugin directory into a reproducible, content-addressable OCI artifact, push it to any OCI registry, install it (registry name, OCI reference, or git:// URL), and list/info/uninstall it — reusing the registry, OCI, groups, and storage infrastructure that already serves skills and MCP servers.
Two-layer split. The design splits cleanly into:
- a client-agnostic distribution layer (build → OCI → push → catalog → pull → verify → inventory) — the bulk of the value, identical for every client; and
- a per-client materialization layer (turning a verified, pulled bundle into something a specific client loads), behind a stable
MaterializationAdapter seam.
v1 scope. Materialization is implemented for the two clients that consume the .claude-plugin/plugin.json family: Claude Code (in-place skills-directory install, full component set, no config mutation) and Codex (cache install + ~/.codex/config.toml mutation, reduced component set — warns on dropped commands/agents). Cursor/Copilot/Gemini adapters are future work behind the seam. Bundled MCP execution is deferred: v1 packages .mcp.json verbatim but does not run/proxy/rewrite it, records dev.toolhive.plugins.requires (resolves nothing), and reports declared MCP servers as "declared; NOT managed by ToolHive." The managed model via requires references is a follow-up RFC.
RFC: THV-0077 — under review as stacklok/toolhive-rfcs#77.
Cross-repo release gates (the bottleneck)
Every toolhive-core change is a separate Go module that must be merged → tagged → released before toolhive / toolhive-registry-server can bump go.mod and build against it. Three core release gates:
- GATE-C1 — tag
toolhive-core after shared OCI primitives (Phase 0); bump toolhive.
- GATE-C2 — tag
toolhive-core after oci/plugins (Phase 1); bump toolhive. Nothing in Phase 2 compiles before this.
- GATE-C3 — tag
toolhive-core after registry/types.Plugin (Phase 5a); bump both toolhive and toolhive-registry-server to the same tag.
Gate ordering
P0 → GATE-C1 → P1 → GATE-C2 → P2 → P3 → P4
P5a → GATE-C3 → P5b / P5d (P5c parallel, no core dep)
Serialized spine: P0 → C1 → P1 → C2 → P2 → P3.
Phase checklist
Overview
Add plugin lifecycle management to ToolHive. A plugin is the "bundle of primitives" unit pioneered by Claude Code — a directory declared by a
.claude-plugin/plugin.jsonmanifest bundling slash commands, subagents, Agent Skills, hooks, MCP server configs, and LSP servers. ToolHive will let users build a plugin directory into a reproducible, content-addressable OCI artifact, push it to any OCI registry, install it (registry name, OCI reference, orgit://URL), and list/info/uninstall it — reusing the registry, OCI, groups, and storage infrastructure that already serves skills and MCP servers.Two-layer split. The design splits cleanly into:
MaterializationAdapterseam.v1 scope. Materialization is implemented for the two clients that consume the
.claude-plugin/plugin.jsonfamily: Claude Code (in-place skills-directory install, full component set, no config mutation) and Codex (cache install +~/.codex/config.tomlmutation, reduced component set — warns on dropped commands/agents). Cursor/Copilot/Gemini adapters are future work behind the seam. Bundled MCP execution is deferred: v1 packages.mcp.jsonverbatim but does not run/proxy/rewrite it, recordsdev.toolhive.plugins.requires(resolves nothing), and reports declared MCP servers as "declared; NOT managed by ToolHive." The managed model viarequiresreferences is a follow-up RFC.RFC: THV-0077 — under review as stacklok/toolhive-rfcs#77.
Cross-repo release gates (the bottleneck)
Every
toolhive-corechange is a separate Go module that must be merged → tagged → released beforetoolhive/toolhive-registry-servercan bumpgo.modand build against it. Three core release gates:toolhive-coreafter shared OCI primitives (Phase 0); bumptoolhive.toolhive-coreafteroci/plugins(Phase 1); bumptoolhive. Nothing in Phase 2 compiles before this.toolhive-coreafterregistry/types.Plugin(Phase 5a); bump bothtoolhiveandtoolhive-registry-serverto the same tag.Gate ordering
Serialized spine: P0 → C1 → P1 → C2 → P2 → P3.
Phase checklist
oci/artifact) — [plugins] Phase 0: extract artifact-agnostic OCI primitives (THV-0077) toolhive-core#130 (implementation complete; PR incoming)oci/pluginspackage — [plugins] Phase 1: oci/plugins package (THV-0077) toolhive-core#131pkg/plugins+pluginsvcbuild/push/validate + storage migration — [plugins] Phase 2: pkg/plugins + pluginsvc build/push/validate + storage migration (THV-0077) #5526thv pluginCLI + content preview — [plugins] Phase 4: REST API + thv plugin CLI + content preview (THV-0077) #5528registry/types.Plugin— [plugins] Phase 5a: registry/types.Plugin (THV-0077) toolhive-core#132/v0.1/x/dev.toolhive/pluginsroutes + PluginsClient — [plugins] Phase 5b: registry provider methods + catalog routes + PluginsClient (THV-0077) #5529marketplace generate+ signing (cosign/Referrers) — [plugins] Phase 5c: marketplace generate + signing (THV-0077) #5530 (parallel, no core dep)types.Plugin— [plugins] Phase 5d: serve plugin catalog surfacing types.Plugin (THV-0077) toolhive-registry-server#819