Summary
spawn has no plugin registry — only a bare-name→URL convention hardcoded in
pkg/plugin/registry.go. There is no index to discover plugins from, no way for a
third-party repo to publish one discoverably, and (bug, below) the bare-name path
the resolver builds doesn't match the layout the official registry actually uses.
Found while building a downstream consumer (aws-hf-model-deploy, a HuggingFace→AWS
inference deployer) that wants to ship its own spore.host plugin — an
inference-server plugin (vLLM / SGLang / llama.cpp) installed onto a spawned GPU
instance. There's currently no supported way to publish that so users can find it.
Verified 2026-07-27 against spawn @ current main and spore-plugins @ 97d8d97.
Bug first: bare-name resolution 404s against the official registry
fetchGitHubSpec (pkg/plugin/registry.go:119) builds:
url := fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/%s/%s/plugin.yaml",
owner, repo, gitRef, name)
For the official registry that's spore-host/spore-plugins/main/<name>/plugin.yaml.
But spore-plugins stores plugins under plugins/<name>/ — as its own
AUTHORING.md:81 instructs ("Create plugins/<your-plugin-name>/plugin.yaml") and
as spawn's own pkg/plugin/validate.go:243 comment already assumes
("plugins/<name>/plugin.yaml").
$ curl -s -o /dev/null -w "%{http_code}\n" \
https://raw.githubusercontent.com/spore-host/spore-plugins/main/tailscale/plugin.yaml
404
$ curl -s -o /dev/null -w "%{http_code}\n" \
https://raw.githubusercontent.com/spore-host/spore-plugins/main/plugins/tailscale/plugin.yaml
200
So every documented bare-name install fails. From spawn plugin --help and
spore-plugins/README.md:
spawn plugin install tailscale --instance <id> --config tag=tag:spore
spawn plugin install globus-personal-endpoint@v1.0.0 --instance <id>
Both resolve to a 404 path. registry_test.go only covers ParseRef (string
parsing) — nothing exercises the constructed URL, which is why this is silent.
The github:user/repo/name form has the mirror-image problem: it forces
<name>/plugin.yaml at the repo root, so a third-party repo cannot use the
plugins/<name>/ layout that the official registry and AUTHORING.md prescribe.
The two forms are mutually inconsistent.
Minimal fix (independent of the registry work below): try plugins/<name>/plugin.yaml
then fall back to <name>/plugin.yaml, and add a test that asserts the URL.
The actual ask: a registry index
Even with the path fixed, install is the only thing that works. Concretely missing:
- No discovery.
spawn plugin list lists plugins installed on an instance
(cmd/plugin.go:52). There is no spawn plugin search / spawn plugin list --available. A user cannot find out that spore-sync exists without reading
the repo.
- No index file.
spore-plugins has no manifest of its contents — just
AUTHORING.md, CLAUDE.md, CONCEPTS.md, LICENSE, README.md, plugins/.
Resolution is convention-only, so a typo is indistinguishable from a plugin that
doesn't exist yet, and there's no metadata (description, supported platforms,
required IAM, maintainer, latest version) available without fetching each
plugin.yaml blindly by guessed name.
- No third-party publishing story. A repo like
aws-hf-model-deploy can host a
plugin.yaml and tell users to type the full
github:scttfrdmn/aws-hf-model-deploy/<name> ref, but it cannot register so the
plugin is findable, and users get
warning: installing plugin from unverified source (registry.go:100) with no
path to ever clearing that.
- No version listing.
name@v1.2.0 pins to a git tag, but nothing enumerates
available tags, so a user can't discover what versions exist or what the latest is.
Suggested shape
An index file in spore-plugins — index.json (or registry.yaml) at the repo
root, generated in CI from plugins/*/plugin.yaml:
{
"generatedAt": "2026-07-27T00:00:00Z",
"schemaVersion": 1,
"plugins": [
{
"name": "tailscale",
"version": "v1.0.0",
"description": "Join the instance to a Tailscale tailnet",
"path": "plugins/tailscale/plugin.yaml",
"source": "spore-host/spore-plugins",
"verified": true
},
{
"name": "hf-inference-server",
"version": "v0.1.0",
"description": "vLLM/SGLang/llama.cpp OpenAI-compatible endpoint",
"source": "scttfrdmn/aws-hf-model-deploy",
"path": "plugin/hf-inference-server/plugin.yaml",
"verified": false
}
]
}
Third-party entries are pointers, not vendored copies — the index carries
source + path and the resolver fetches from that repo, so plugin code stays
with its owner while remaining discoverable. That mirrors the "recipe, not cake"
pattern already used in libs/catalog, and the static-JSON-on-a-schedule pattern
already used by hf-bedrock-map.
Then:
spawn plugin search [query] / spawn plugin list --available reads the index
spawn plugin info <name> shows description, version, config schema, source
- resolution consults
index.json for path, removing the hardcoded convention
(and fixing the bug above structurally rather than by guessing two paths)
verified: true only for spore-host-owned entries, which gives the existing
unverified-source warning a real meaning instead of a dead end
Two things worth deciding explicitly, both of which affect whether a downstream
repo can rely on this:
- Trust model for third-party entries. Listing in the index is an implicit
endorsement even with verified: false, and install runs arbitrary shell on the
instance. A PR-review gate for index entries is probably the minimum; commit-SHA
pinning rather than branch refs would be stronger.
- Caching + offline. The index should be cached locally with a visible age
(same discipline as hf-bedrock-map's generatedAt) so search isn't a hard
network dependency, and so a stale index is distinguishable from a missing plugin.
Happy to contribute the index generator and the search/info commands if this
shape is agreeable — I need it downstream either way, and would rather build it
here than work around it. If you'd prefer the path bug split into its own issue,
say so and I'll file it separately.
Summary
spawnhas no plugin registry — only a bare-name→URL convention hardcoded inpkg/plugin/registry.go. There is no index to discover plugins from, no way for athird-party repo to publish one discoverably, and (bug, below) the bare-name path
the resolver builds doesn't match the layout the official registry actually uses.
Found while building a downstream consumer (
aws-hf-model-deploy, a HuggingFace→AWSinference deployer) that wants to ship its own spore.host plugin — an
inference-server plugin (vLLM / SGLang / llama.cpp) installed onto a spawned GPU
instance. There's currently no supported way to publish that so users can find it.
Verified 2026-07-27 against
spawn@ current main andspore-plugins@ 97d8d97.Bug first: bare-name resolution 404s against the official registry
fetchGitHubSpec(pkg/plugin/registry.go:119) builds:For the official registry that's
spore-host/spore-plugins/main/<name>/plugin.yaml.But
spore-pluginsstores plugins underplugins/<name>/— as its ownAUTHORING.md:81instructs ("Createplugins/<your-plugin-name>/plugin.yaml") andas
spawn's ownpkg/plugin/validate.go:243comment already assumes("
plugins/<name>/plugin.yaml").So every documented bare-name install fails. From
spawn plugin --helpandspore-plugins/README.md:Both resolve to a 404 path.
registry_test.goonly coversParseRef(stringparsing) — nothing exercises the constructed URL, which is why this is silent.
The
github:user/repo/nameform has the mirror-image problem: it forces<name>/plugin.yamlat the repo root, so a third-party repo cannot use theplugins/<name>/layout that the official registry andAUTHORING.mdprescribe.The two forms are mutually inconsistent.
Minimal fix (independent of the registry work below): try
plugins/<name>/plugin.yamlthen fall back to
<name>/plugin.yaml, and add a test that asserts the URL.The actual ask: a registry index
Even with the path fixed,
installis the only thing that works. Concretely missing:spawn plugin listlists plugins installed on an instance(
cmd/plugin.go:52). There is nospawn plugin search/spawn plugin list --available. A user cannot find out thatspore-syncexists without readingthe repo.
spore-pluginshas no manifest of its contents — justAUTHORING.md,CLAUDE.md,CONCEPTS.md,LICENSE,README.md,plugins/.Resolution is convention-only, so a typo is indistinguishable from a plugin that
doesn't exist yet, and there's no metadata (description, supported platforms,
required IAM, maintainer, latest version) available without fetching each
plugin.yamlblindly by guessed name.aws-hf-model-deploycan host aplugin.yamland tell users to type the fullgithub:scttfrdmn/aws-hf-model-deploy/<name>ref, but it cannot register so theplugin is findable, and users get
warning: installing plugin from unverified source(registry.go:100) with nopath to ever clearing that.
name@v1.2.0pins to a git tag, but nothing enumeratesavailable tags, so a user can't discover what versions exist or what the latest is.
Suggested shape
An index file in
spore-plugins—index.json(orregistry.yaml) at the reporoot, generated in CI from
plugins/*/plugin.yaml:{ "generatedAt": "2026-07-27T00:00:00Z", "schemaVersion": 1, "plugins": [ { "name": "tailscale", "version": "v1.0.0", "description": "Join the instance to a Tailscale tailnet", "path": "plugins/tailscale/plugin.yaml", "source": "spore-host/spore-plugins", "verified": true }, { "name": "hf-inference-server", "version": "v0.1.0", "description": "vLLM/SGLang/llama.cpp OpenAI-compatible endpoint", "source": "scttfrdmn/aws-hf-model-deploy", "path": "plugin/hf-inference-server/plugin.yaml", "verified": false } ] }Third-party entries are pointers, not vendored copies — the index carries
source+pathand the resolver fetches from that repo, so plugin code stayswith its owner while remaining discoverable. That mirrors the "recipe, not cake"
pattern already used in
libs/catalog, and the static-JSON-on-a-schedule patternalready used by
hf-bedrock-map.Then:
spawn plugin search [query]/spawn plugin list --availablereads the indexspawn plugin info <name>shows description, version, config schema, sourceindex.jsonforpath, removing the hardcoded convention(and fixing the bug above structurally rather than by guessing two paths)
verified: trueonly forspore-host-owned entries, which gives the existingunverified-source warning a real meaning instead of a dead end
Two things worth deciding explicitly, both of which affect whether a downstream
repo can rely on this:
endorsement even with
verified: false, andinstallruns arbitrary shell on theinstance. A PR-review gate for index entries is probably the minimum; commit-SHA
pinning rather than branch refs would be stronger.
(same discipline as
hf-bedrock-map'sgeneratedAt) sosearchisn't a hardnetwork dependency, and so a stale index is distinguishable from a missing plugin.
Happy to contribute the index generator and the
search/infocommands if thisshape is agreeable — I need it downstream either way, and would rather build it
here than work around it. If you'd prefer the path bug split into its own issue,
say so and I'll file it separately.