Simplify the community catalog submission flow to use issue templates
with manual maintainer review (no automation scripts or workflows).
- Add explicit CODEOWNERS entries for catalog.community.json files so
submissions are automatically assigned to a maintainer for review
- Improve preset submission template:
- Add 'Required Extensions' optional field
- Make 'Templates Provided' optional (supports command-only presets)
- Add 'Number of Scripts' optional field
The existing extension and preset issue templates already collect all
required catalog metadata. Maintainers review submissions and manually
update the catalog JSON files.
Closes#2400
The compatibility-error messages in extensions.py and presets.py, plus the
extension troubleshooting guide, told users to upgrade with:
uv tool install specify-cli --force
Without `--from git+https://github.com/github/spec-kit.git`, uv resolves
`specify-cli` from PyPI, where an unrelated package with the same name
(no author, no project URLs) ships a stub CLI that lacks `extension`,
`preset`, and most spec-kit commands. Users following the upgrade hint
land on the squat package and report "extension command removed"
(see #1982).
Reuse the existing `REINSTALL_COMMAND` constant in extensions.py and
import it from presets.py so all three call sites point at the GitHub
source. The doc fix also adds a one-line note explaining the PyPI
collision so the same advice doesn't get re-stripped later.
Refs #1982
* feat: add git extension with hooks on all core commands
- Create extensions/git/ with 5 commands: initialize, feature,
validate, remote, commit
- 18 hooks covering before/after for all 9 core commands
- Scripts: create-new-feature, initialize-repo, auto-commit,
git-common (bash + powershell)
- Configurable: branch_numbering, init_commit_message,
per-command auto-commit with custom messages
- Add hooks to analyze, checklist, clarify, constitution,
taskstoissues command templates
- Allow hooks-only extensions (no commands required)
- Bundle extension in wheel via pyproject.toml force-include
- Resolve bundled extensions locally before catalog lookup
- Remove planned-but-unimplemented before/after_commit hook refs
- Update extension docs (API ref, dev guide, user guide)
- 37 new tests covering manifest, install, all scripts (bash+pwsh),
config reading, graceful degradation
Stage 1: opt-in via 'specify extension add git'. No auto-install,
no changes to specify.md or core git init code.
Refs: #841, #1382, #1066, #1791, #1191
* fix: set git identity env vars in extension tests for CI runners
* fix: address PR review comments
- Fix commands property KeyError for hooks-only extensions
- Fix has_git() operator precedence in git-common.sh
- Align default commit message to '[Spec Kit] Initial commit' across
config-template, extension.yml defaults, and both init scripts
- Update README to reflect all 5 commands and 18 hooks
* fix: address second round of PR review comments
- Add type validation for provides.commands (must be list) and hooks
(must be dict) in manifest _validate()
- Tighten malformed timestamp detection in git-common.sh to catch
7-digit dates without trailing slug (e.g. 2026031-143022)
- Pass REPO_ROOT to has_git/Test-HasGit in create-new-feature scripts
- Fix initialize command docs: surface errors on git failures, only
skip when git is not installed
- Fix commit command docs: 'skips with a warning' not 'silently'
- Add tests for commands:null and hooks:list rejection
* fix: address third round of PR review comments
- Remove scripts frontmatter from command files (CommandRegistrar
rewrites ../../scripts/ to .specify/scripts/ which points at core
scripts, not extension scripts)
- Update speckit.git.commit command to derive event name from hook
context rather than using a static example
- Clarify that hook argument passthrough works via AI agent context
(the agent carries conversation state including user's original
feature description)
* fix: address fourth round of PR review comments
- Validate extension_id against ^[a-z0-9-]+$ in _locate_bundled_extension
to prevent path traversal (security fix)
- Move defaults under config.defaults in extension.yml to match
ConfigManager._get_extension_defaults() schema
- Ship git-config.yml in extension directory so it's copied during
install (provides.config template isn't materialized by ExtensionManager)
- Condition handling in hook templates: intentionally matches existing
pattern from specify/plan/tasks/implement templates (not a new issue)
* fix: add --allow-empty to git commit in initialize-repo scripts
Ensures git init succeeds even on empty repos where nothing has been
staged yet.
* fix: resolve display names to bundled extensions before catalog download
When 'specify extension add "Git Branching Workflow"' is used with a
display name instead of the ID, the catalog resolver now runs first to
map the name to an ID, then checks bundled extensions again with the
resolved ID before falling back to network download.
Also noted: EXECUTE_COMMAND_INVOCATION and condition handling match the
existing pattern in specify/plan/tasks/implement templates (pre-existing,
not introduced by this PR).
* fix: handle before_/after_ prefixes in auto-commit message derivation
- Strip both before_ and after_ prefixes when deriving command name
(fixes misleading 'Auto-commit after before_plan' messages)
- Include phase (before/after) in default commit messages
- Clarify README config example is an override, not default behavior
* fix: use portable grep -qw for word boundary in create-new-feature.sh
BSD grep (macOS) doesn't support \b as a word boundary. Replace with
grep -qw which is POSIX-portable.
* fix: validate hook values, numeric --number, and PS warning routing
- Validate each hook value is a dict with a 'command' field during
manifest _validate() (prevents crash at install time)
- Validate --number is a non-negative integer in bash create-new-feature
(clear error instead of cryptic shell arithmetic failure)
- Route PowerShell no-git warning to stderr in JSON mode so stdout
stays valid JSON
---------
Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com>
* docs: correct specify extension add syntax to require extension name
The specify extension add command requires the extension name as a positional argument. Many documentation files incorrectly demonstrated using the --from flag without specifying the extension name first.
* feat: add superb extension to community catalog
Orchestrates obra/superpowers skills within the spec-kit SDD workflow.
* fix: link superb extension docs
- Add 🧩 Community Extensions section to README.md before Community Walkthroughs
- Add table of contents entry for the new section
- Replace extensions/README.md table with a link back to the main README
- Update EXTENSION-PUBLISHING-GUIDE.md references to point to README.md
- Update EXTENSION-DEVELOPMENT-GUIDE.md references to point to README.md
* feat(extensions): support .extensionignore to exclude files during install
Add .extensionignore support so extension authors can exclude files and
folders from being copied when users run 'specify extension add'.
The file uses glob-style patterns (one per line), supports comments (#),
blank lines, trailing-slash directory patterns, and relative path matching.
The .extensionignore file itself is always excluded from the copy.
- Add _load_extensionignore() to ExtensionManager
- Integrate ignore function into shutil.copytree in install_from_directory
- Document .extensionignore in EXTENSION-DEVELOPMENT-GUIDE.md
- Add 6 tests covering all pattern matching scenarios
- Bump version to 0.1.14
* fix(extensions): use pathspec for gitignore-compatible .extensionignore matching
Replace fnmatch with pathspec.GitIgnoreSpec to get proper .gitignore
semantics where * does not cross directory boundaries. This addresses
review feedback on #1781.
Changes:
- Switch from fnmatch to pathspec>=0.12.0 (GitIgnoreSpec.from_lines)
- Normalize backslashes in patterns for cross-platform compatibility
- Distinguish directories from files for trailing-slash patterns
- Update docs to accurately describe supported pattern semantics
- Add edge-case tests: .., absolute paths, empty file, backslashes,
* vs ** boundary behavior, and ! negation
- Move changelog entry to [Unreleased] section
* docs: Document dual-catalog system for extensions
- Clarify distinction between catalog.json (curated) and catalog.community.json (reference)
- Update EXTENSION-DEVELOPMENT-GUIDE.md to explain community catalog submission
- Update EXTENSION-PUBLISHING-GUIDE.md with dual-catalog workflow
- Update EXTENSION-USER-GUIDE.md with catalog selection guidance
- Expand README.md with comprehensive catalog explanation
- Update RFC-EXTENSION-SYSTEM.md with dual-catalog design and current implementation
- Change GitHub references from statsperform to github
- Add SPECKIT_CATALOG_URL environment variable documentation
This clarifies how organizations can curate their own catalog while
browsing community-contributed extensions for discovery.
* Update extensions/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update extensions/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update extensions/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add modular extension system for Spec Kit
Implement a complete extension system that allows third-party developers
to extend Spec Kit functionality through plugins.
## Core Features
- Extension discovery and loading from local and global directories
- YAML-based extension manifest (extension.yml) with metadata and capabilities
- Command extensions: custom slash commands with markdown templates
- Hook system: pre/post hooks for generate, task, and sync operations
- Extension catalog for discovering and installing community extensions
- SPECKIT_CATALOG_URL environment variable for catalog URL override
## Installation Methods
- Catalog install: `specify extension add <name>`
- URL install: `specify extension add <name> --from <url>`
- Dev install: `specify extension add --dev <path>`
## Implementation
- ExtensionManager class for lifecycle management (load, enable, disable)
- Support for extension dependencies and version constraints
- Configuration layering (global → project → extension)
- Hook conditions for conditional execution
## Documentation
- RFC with design rationale and architecture decisions
- API reference for extension developers
- Development guide with examples
- User guide for installing and managing extensions
- Publishing guide for the extension catalog
## Included
- Extension template for bootstrapping new extensions
- Comprehensive test suite
- Example catalog.json structure
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update Jira extension to v2.1.0 in catalog
Adds 2-level mode support (Epic → Stories only).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Address PR review feedback
- Fix Zip Slip vulnerability in ZIP extraction with path validation
- Fix keep_config option to actually preserve config files on removal
- Add URL validation for SPECKIT_CATALOG_URL (HTTPS required, localhost exception)
- Add security warning when installing from custom URLs (--from flag)
- Empty catalog.json so organizations can ship their own catalogs
- Fix markdown linter errors (MD040: add language to code blocks)
- Remove redundant import and fix unused variables in tests
- Add comment explaining empty except clause for backwards compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add comprehensive organization catalog customization docs
- Explain why default catalog is empty (org control)
- Document how to create and host custom catalogs
- Add catalog JSON schema reference
- Include use cases: private extensions, curated catalogs, air-gapped environments
- Add examples for combining catalog with direct installation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix test assertions for extension system data structures
- Update test_config_backup_on_remove to use new subdirectory structure
(.backup/test-ext/file.yml instead of .backup/test-ext-file.yml)
- Update test_full_install_and_remove_workflow to handle registered_commands
being a dict keyed by agent name instead of a flat list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Address Copilot review feedback
- Fix localhost URL check to use parsed.hostname instead of netloc.startswith()
This correctly handles URLs with ports like localhost:8080
- Fix YAML indentation error in config-template.yml (line 57)
- Fix double space typo in example.md (line 172)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add catalog.example.json as reference for organizations
The main catalog.json is intentionally empty so organizations can ship
their own curated catalogs. This example file shows the expected schema
and structure for creating organization-specific catalogs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Address remaining Copilot security and logic review feedback
- Fix Zip Slip vulnerability by using relative_to() for safe path validation
- Add HTTPS validation for extension download URLs
- Backup both *-config.yml and *-config.local.yml files on remove
- Normalize boolean values to lowercase for hook condition comparisons
- Show non-default catalog warning only once per instance
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Ignoring linter for extensions directory
---------
Co-authored-by: iamaeroplane <michal.bachorik@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Manfred Riem <manfred.riem@microsoft.com>