Repository navigation
[Feature]: Spec Kit Package Manager — community CLI for extension/preset discovery, install, version pinning, and conflict detection #2566
Description
Problem Statement
The April 2026 newsletter calls out as future work:
"Catalog discovery as package-manager experience for extensions/presets/integrations"
Today the ecosystem has 110+ community extensions and 12+ presets, but installation is still a manual flow: copy a
download URL from a catalog JSON, run specify extension add --from <url>, hope nothing collides with what's already
installed, and re-do it by hand for every update. There is no:
extensions.lock.json(no version pinning, no reproducible installs across machines / CI)- conflict detection (two extensions writing the same
.specify/*.mdartifact silently overwrite each other) - dependency resolution (e.g. "Canon" requires "Canon Core" preset — surfaced only in prose)
- bulk update path (
specify pm outdated,specify pm upgrade) - offline search / filter against the catalog (
specify pm search drift --category process --license MIT) - preset+extension stack snapshot for new team members
This is the exact gap the maintainers named on the roadmap; nothing in extensions/catalog.community.json addresses it
today.
Proposed Solution
A community extension spec-kit-pm that prototypes a package-manager experience the maintainers can later promote into
core (mirroring the pattern of the existing specify self check / self upgrade stubs in v0.7.5):
/speckit.pm.search drift # search community catalog locally
/speckit.pm.install spec-kit-sync # resolves deps, writes extensions.lock.json
/speckit.pm.outdated # compares installed vs catalog versions
/speckit.pm.upgrade # respects pins; --dry-run by default
/speckit.pm.conflicts # static analysis of artifact collisions
/speckit.pm.snapshot # export reproducible stack manifest
/speckit.pm.restore <manifest> # rehydrate stack on new machine
Key design decisions:
- Reads the existing catalog.community.json — zero changes to upstream catalog format
- Writes .specify/extensions.lock.json parallel to existing .specify/integration.json so it integrates with the current
try_read_integration_json schema-guard pattern
- Conflict detection is static: parses each extension's extension.yml provides.commands / artifact-write paths declared
in the manifest
- Honors the existing requires.speckit_version and (proposed extension) requires.extensions fields —
backwards-compatible for extensions that don't declare them
- Pure read+write to project root and .specify/ — no network calls except an opt-in catalog refresh
### Alternatives Considered
- Wait for core support — newsletter lists this as roadmap work but no ETA; a community extension can prove the UX
faster and feed learnings back
- Per-extension installers — every author would reinvent the wheel; a single shared layer is cheaper and more consistent
- Pure shell aliases — doesn't solve conflict detection or lock files
- Fork existing JS/Python package managers — overkill; catalog is JSON, install surface is small, native fit is
.specify/* artifacts
### Component
Specify CLI (initialization, commands)
### AI Agent (if applicable)
All agents
### Use Cases
1. Reproducible installs in CI — specify pm restore stack.json on a clean checkout produces the exact same extension
set, no version drift between team members
2. Pre-merge conflict detection — before a maintainer accepts a new catalog PR, specify pm conflicts can flag if the new
extension's artifact paths collide with popular existing ones
3. Upgrade hygiene — specify pm outdated --severity major surfaces upstream changes a team should review before
consuming
4. Stack discovery for newcomers — instead of reading 110 README files, specify pm search "spec drift" returns ranked
matches with description / author / stars from the catalog
5. Audit trail — extensions.lock.json becomes the durable record of "what shaped this project" — useful for the very
governance and onboarding tools the newsletter highlights (Memory Loader, Onboard, MemoryLint)
### Acceptance Criteria
- /speckit.pm.search <query> returns matching catalog entries with name / description / author / version / category /
license / stars
- /speckit.pm.install <id> downloads from catalog.community.json download_url, writes extensions.lock.json with resolved
version + sha256
- /speckit.pm.outdated reports installed-vs-catalog diff
- /speckit.pm.upgrade defaults to --dry-run; only mutates with --apply
- /speckit.pm.conflicts statically detects two installed extensions writing the same path
- /speckit.pm.snapshot produces a portable manifest; /speckit.pm.restore rehydrates it
- Works with the existing .specify/integration.json schema-guard pattern (silent fallback on missing, loud error on
malformed)
- No network calls unless an explicit --refresh flag is passed
- Read-only by default for search, outdated, conflicts, snapshot; write only for install, upgrade --apply, restore
- README, LICENSE (MIT), CHANGELOG, GitHub release v1.0.0
- Tested against ≥10 randomly-chosen catalog entries
### Additional Context
- Newsletter quote (April 2026, roadmap section): "Catalog discovery as package-manager experience for
extensions/presets/integrations"
- Newsletter pain point: "instruction bloat, context rot" (Thoughtworks Radar v34) — a lock file + curated stack
manifest helps teams keep extension count intentional
- Newsletter pain point: "experienced reviewer is still essential" (XB Software field report) — pm conflicts reduces the
review surface
- Pattern precedent: specify self check / self upgrade stubs already exist in v0.7.5, so a pm family fits the existing
CLI shape
- Wanted to align with the maintainers before building — happy to adjust scope, naming, command shape, or split into a
smaller v0.1 (e.g. just install + lock first) based on your steer.
Activity
mnriem commentedon May 14, 2026
Package management here was meant in the context of creating bundles that an organization wants to maintain. So a curated and versioned set of catalog JSONs. Note the community catalog will stay read-only, but anyone can copy it and use it as the starting point of hosting their own internal catalogs
Quratulain-bilal commentedon May 14, 2026
Ohh that's a much cleaner mental model than what I had in my head, thanks for spelling it out.
So the unit isn't really "a project's installed extensions" (which is where I started), it's "a catalog that an org owns
and distributes." The community catalog stays as the source-of-truth upstream, and downstream is just whoever forked it
and curated. That's basically how Linux distros relate to upstream package maintainers, makes sense.
A few things I want to sanity-check before I rewrite the proposal:
imagining something more structured like a manifest that wraps multiple catalogs + a version + signing metadata? I can
see arguments either way.
spec-kit-sync at v0.3.2, not latest")? That's the one piece of my original lock-file idea I think still applies here,
but at the catalog level not the project level.
do you want this to live entirely as a community extension that orgs adopt by choice?
Happy to either edit this issue down to the bundle scope or close it and open a fresh one if you'd prefer a clean slate.
Whichever's easier to track.
mnriem commentedon May 15, 2026
I included a catalog.json with the presets and extensions I host myself. See https://github.com/mnriem/spec-kit-presets/blob/main/catalog.json for an example for presets catalog. And https://github.com/mnriem/spec-kit-extensions/blob/main/catalog.json
That is how indeed an organization can host it themselves. And they can use a Git tags if so desired
And the you can already do
specify extension catalogandspecify presets catalogQuratulain-bilal commentedon May 15, 2026
ahh I'd missed
specify extension catalogandspecify presets catalogentirely. Just looked at your two repos plusthe implementation in
src/specify_cli/extensions.pyandcatalogs.pyand I see it now:SPECKIT_CATALOG_URLenv var,multi-catalog
CatalogEntryregistry with priorities, schema_version + updated_at + catalog_url at the root. The "hostyour own catalog" plumbing is already there.
That changes what's worth building. The tooling exists; the gap is the convention layer an org needs in order to
actually adopt this pattern:
A template repo (
spec-kit-org-catalog-template) that ships with a startercatalog.jsoncurated from upstream,a CI workflow that validates schema + checks every
download_urlis reachable + diffs vs upstream on every PR, and aRELEASE.mddescribing the git-tag-as-version convention you mentioned.A catalog diff command in the template
make diff-upstreamthat pulls the community catalog and reportsadded/removed/version-changed entries since the last sync. Orgs need this to do periodic refreshes without manually
scanning the upstream catalog.
A short HOSTING.md in spec-kit docs (or a
docs/community/hosting-your-own-catalog.md) that links to your twoexample repos and walks through: fork → curate → set SPECKIT_CATALOG_URL → tag releases. Right now that workflow is
implicit; making it explicit unlocks the org-internal use case you described.
None of that requires touching upstream code. It's purely playbook + tooling that lives alongside the existing CLI.
Two questions before I do anything:
back into the spec-kit repo? Both work; first is faster, second has more reach.
gap? Don't want to reinvent something you already have.
If neither of these is interesting, I'm equally happy to close this issue the underlying need was "make org-hosted
catalogs more discoverable" and you've shown it's already largely solved.
mnriem commentedon May 18, 2026
You do nor have to set the environment variable. You can use multiple catalogs at the same time. Is https://github.github.com/spec-kit/reference/extensions.html#catalog-management not sufficient?
Quratulain-bilal commentedon May 18, 2026
I missed the multi-catalog section first time round specify extension catalog add with priorities is exactly the
surface I was reaching for. Closing.