This document provides comprehensive reference documentation for all CLI commands used to manage extensions in the Spec Kit system. These commands allow users to discover, install, configure, update, and remove extensions that add functionality to their projects without modifying the core toolkit.
For information about the internal architecture of the extension system, see Extension Architecture. For details on extension discovery and the central catalog, see Extension Catalog and Discovery. For guidance on creating your own extensions, see Creating Extensions.
The extension management interface is accessed via the specify extension command group. All commands require execution from within a Spec Kit project directory (containing a .specify/ folder).
| Command | Purpose | Key Options |
|---|---|---|
list | Display installed extensions and their status | --available, --all |
add | Install an extension from catalog, local directory, or URL | --dev, --from |
remove | Uninstall an extension from the project | --keep-config, --force |
search | Search the extension catalog for available extensions | --tag, --author, --verified |
info | Show detailed information about an extension | (none) |
update | Update extensions to their latest versions | (none) |
enable | Enable a previously disabled extension | (none) |
disable | Disable an extension without removing it | (none) |
Sources: src/specify_cli/__init__.py1403-1967 CHANGELOG.md14-66
Sources: src/specify_cli/__init__.py1405-1410 src/specify_cli/__init__.py1434-1967
list - Display Installed Extensions| Option | Type | Description |
|---|---|---|
--available | Flag | Show available extensions from the catalog (not implemented in current version) |
--all | Flag | Show both installed and available extensions |
The list command reads the extension registry at .specify/extensions/.registry and displays all installed extensions with their metadata. For each extension, it shows:
Installed Extensions:
✓ jira (v1.0.0)
Jira integration for spec-driven development
Commands: 3 | Hooks: 2 | Status: Enabled
✗ github-sync (v2.1.0)
Synchronize specs with GitHub issues
Commands: 5 | Hooks: 1 | Status: Disabled
| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| No extensions installed | "No extensions installed." (yellow warning) | 0 |
Sources: src/specify_cli/__init__.py1434-1475
add - Install Extension| Parameter | Type | Required | Description |
|---|---|---|---|
<extension> | Argument | Yes | Extension name (catalog), directory path (--dev), or identifier (--from) |
--dev | Flag | No | Install from local directory for development |
--from <url> | Option | No | Install from custom HTTPS URL (ZIP file) |
The add command supports three distinct installation modes:
When no flags are provided, the command searches the central extension catalog and installs from there.
The process:
ExtensionCatalog.fetch() retrieves the catalog from GitHubExtensionManager.install_from_catalog() handles installation--dev)For extension developers, install from a local directory:
The process:
extension.ymlExtensionManager.install_from_directory() copies files to .specify/extensions/{ext-id}/This mode is useful for testing extensions during development without publishing to the catalog.
--from)Install from a custom HTTPS URL (or localhost HTTP for testing):
Security constraints:
127.0.0.1, localhost, ::1)The process:
.specify/extensions/.cache/downloads/ExtensionManager.install_from_zip() extracts and installsDuring installation, the command performs semantic version compatibility checking:
If the extension's spec_kit_version requirement is incompatible with the current Spec Kit version, installation fails with a CompatibilityError.
After successful installation, the following structure is created:
.specify/extensions/
├── .registry # Updated with new entry
├── {extension-id}/
│ ├── extension.yml # Manifest
│ ├── commands/ # Slash commands
│ │ ├── command1.md
│ │ └── command2.md
│ ├── {extension-id}-config.yml # Default project config
│ └── README.md # Documentation
Additionally, commands are registered in all detected agent directories:
.claude/commands/.gemini/commands/.github/agents/.cursor/commands/| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Extension already installed | "Extension '{name}' is already installed" | 1 |
| Invalid URL scheme | "URL must use HTTPS for security" | 1 |
| Directory not found (--dev) | "Directory not found: {path}" | 1 |
| No extension.yml (--dev) | "No extension.yml found in {path}" | 1 |
| Extension not in catalog | "Extension not found in catalog" | 1 |
| Version incompatibility | "Extension requires spec-kit {version}" | 1 |
| Validation error | "Extension validation failed: {details}" | 1 |
Sources: src/specify_cli/__init__.py1477-1577 CHANGELOG.md19-22
remove - Uninstall Extension| Parameter | Type | Required | Description |
|---|---|---|---|
<extension> | Argument | Yes | Extension identifier to remove |
--keep-config | Flag | No | Preserve configuration files after removal |
--force | Flag | No | Skip confirmation prompt |
The remove command uninstalls an extension and optionally preserves its configuration:
When --keep-config is specified, the following files are preserved:
.specify/extensions/{ext-id}/{ext-id}-config.yml - Project-level configuration.specify/extensions/{ext-id}/local-config.yml - Local user configuration (gitignored)This allows reinstalling the extension later without losing custom settings.
The removal process automatically unregisters commands from all AI agent directories where they were installed, cleaning up:
.claude/commands/speckit.{ext-id}.*.md.gemini/commands/speckit.{ext-id}.*.toml.github/agents/speckit.{ext-id}.*.md| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Extension not found | "Extension '{name}' not found" | 1 |
| User cancels | "Operation cancelled" | 0 |
Sources: src/specify_cli/__init__.py1579-1635 CHANGELOG.md20-22
search - Search Extension Catalog| Parameter | Type | Required | Description |
|---|---|---|---|
<query> | Argument | No | Search term for name/description (case-insensitive) |
--tag <tag> | Option | No | Filter by specific tag |
--author <author> | Option | No | Filter by author |
--verified | Flag | No | Show only verified extensions |
The search functionality is implemented in ExtensionCatalog.search() with the following logic:
Results are displayed in a table with the following columns:
| Column | Description |
|---|---|
| Name | Extension identifier (bold) |
| Version | Latest version number |
| Author | Extension author/maintainer |
| Description | Brief description (truncated if long) |
| Tags | Comma-separated list of tags |
| Verified | ✓ if verified, empty otherwise |
The search command uses a 1-hour cache to minimize GitHub API calls:
.specify/extensions/.cache/catalog.json| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Catalog fetch fails | "Failed to fetch extension catalog" | 1 |
| No results | "No extensions found matching criteria" (warning) | 0 |
Sources: src/specify_cli/__init__.py1637-1726 CHANGELOG.md30-39
info - Display Extension Details| Parameter | Type | Required | Description |
|---|---|---|---|
<extension> | Argument | Yes | Extension identifier |
The info command retrieves data from two sources depending on installation status:
The command displays comprehensive metadata in a formatted panel:
For Installed Extensions:
For Catalog Extensions (not installed):
╭─ Extension: jira (v1.0.0) ─────────────────────────────╮
│ │
│ Description: Jira integration for spec-driven dev │
│ Author: github │
│ License: MIT │
│ Homepage: https://github.com/github/spec-kit-ext- │
│ jira │
│ Status: Enabled ✓ │
│ │
│ Commands (3): │
│ • /speckit.jira.specstoissues │
│ • /speckit.jira.discover-fields │
│ • /speckit.jira.sync-status │
│ │
│ Hooks (2): │
│ • after-plan: Update Jira epic │
│ • after-implement: Close issues │
│ │
│ Configuration: │
│ Project: jira-config.yml │
│ Local: local-config.yml │
│ │
│ Path: .specify/extensions/jira/ │
╰─────────────────────────────────────────────────────────╯
| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Extension not found | "Extension '{name}' not found in installed extensions or catalog" | 1 |
Sources: src/specify_cli/__init__.py1728-1805 CHANGELOG.md23-24
update - Update Extensions| Parameter | Type | Required | Description |
|---|---|---|---|
<extension> | Argument | No | Specific extension to update; if omitted, checks all |
The update command uses semantic version comparison to determine if an update is available:
During updates, all configuration layers are preserved:
{ext-id}-config.yml) - backed up and restoredlocal-config.yml) - backed up and restoredChecking for updates...
Found updates:
• jira: v1.0.0 → v1.2.0
• github-sync: v2.1.0 → v3.0.0
Update jira to v1.2.0? [Y/n]: y
Backing up configuration...
Installing v1.2.0...
Restoring configuration...
✓ Updated successfully
Update github-sync to v3.0.0? [Y/n]: n
Skipped
| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Extension not installed | "Extension '{name}' is not installed" | 1 |
| Extension not in catalog | "Extension '{name}' not found in catalog" | 1 |
| Update fails | "Failed to update extension: {error}" | 1 |
Sources: src/specify_cli/__init__.py1807-1881 CHANGELOG.md60-66
enable - Enable Extension| Parameter | Type | Required | Description |
|---|---|---|---|
<extension> | Argument | Yes | Extension identifier to enable |
The enable command activates a previously disabled extension without reinstalling it:
enabled: true.specify/extensions.ymlWhen an extension is enabled, its lifecycle hooks become active:
Important distinction:
| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Extension not found | "Extension '{name}' not found" | 1 |
| Already enabled | "Extension '{name}' is already enabled" | 0 |
Sources: src/specify_cli/__init__.py1883-1924 CHANGELOG.md60-66
disable - Disable Extension| Parameter | Type | Required | Description |
|---|---|---|---|
<extension> | Argument | Yes | Extension identifier to disable |
The disable command deactivates an extension without removing its files:
enabled: false.specify/extensions.ymlDisabling is useful when:
| Aspect | Disable | Remove |
|---|---|---|
| Extension files | Preserved | Deleted |
| Configuration | Preserved | Deleted (unless --keep-config) |
| Commands | Remain registered | Unregistered |
| Hooks | Inactive | Deleted |
| Can re-enable | Yes (instant) | No (must reinstall) |
| Condition | Error Message | Exit Code |
|---|---|---|
| Not in Spec Kit project | "Not a spec-kit project (no .specify/ directory)" | 1 |
| Extension not found | "Extension '{name}' not found" | 1 |
| Already disabled | "Extension '{name}' is already disabled" | 0 |
Sources: src/specify_cli/__init__.py1926-1967 CHANGELOG.md60-66
This diagram shows the file system changes produced by various extension management commands:
Sources: src/specify_cli/__init__.py1477-1967
All extension management commands share common validation and error handling logic:
Every command begins with this check:
This ensures commands only run in initialized Spec Kit projects.
The extension system defines specific exceptions for different error types:
Commands catch these exceptions and display user-friendly error messages using Rich console formatting.
Destructive operations (remove, update) prompt for confirmation unless --force is provided:
Long-running operations use Rich console status spinners:
Sources: src/specify_cli/__init__.py1434-1967
All installation and removal commands integrate with the multi-agent command registration system to ensure slash commands work across all supported AI assistants:
The CommandRegistrar class handles format conversion and agent-specific conventions automatically. See Multi-Agent Architecture for details on format variations.
Sources: src/specify_cli/__init__.py1477-1577 CHANGELOG.md68-76
Refresh this wiki