This document provides comprehensive technical documentation for all commands exposed by the specify CLI tool. The CLI serves as the bootstrap and management interface for Spec-Driven Development projects, handling project initialization, environment validation, and extension lifecycle management.
For details about the interactive selection system (arrow-based UI), see Interactive Selection System. For environment validation internals, see Environment Validation. For the project initialization process, see Project Initialization.
The specify CLI is built using the Typer framework and follows a hierarchical command structure with core commands and an extension management subcommand group.
Sources: src/specify_cli/__init__.py436-442 src/specify_cli/__init__.py1405-1410
specify initInitializes a new Spec-Driven Development project by downloading the appropriate template from GitHub releases and setting up the project structure.
Command Implementation: src/specify_cli/__init__.py980-1279
Syntax:
specify init [PROJECT_NAME] [OPTIONS]
specify init . [OPTIONS]
specify init --here [OPTIONS]
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
project_name | str | Conditional | Name for new project directory. Required unless using --here or . for current directory |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
--ai | str | Interactive selection | AI assistant key from AGENT_CONFIG. Valid values: copilot, claude, gemini, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, codebuddy, amp, shai, q, bob, qoder |
--script | str | Platform-dependent (sh on Unix, ps on Windows) | Script type: sh (POSIX shell) or ps (PowerShell) |
--ignore-agent-tools | bool | False | Skip CLI tool checks for AI agents that requires_cli=True |
--no-git | bool | False | Skip git repository initialization |
--here | bool | False | Initialize in current directory instead of creating new directory |
--force | bool | False | Skip confirmation when using --here with non-empty directory |
--skip-tls | bool | False | Disable SSL/TLS verification (not recommended) |
--debug | bool | False | Show verbose diagnostic output for network/extraction failures |
--github-token | str | None | GitHub token for API requests (or use GH_TOKEN/GITHUB_TOKEN env vars) |
Initialization Flow:
Key Internal Functions:
download_template_from_github() src/specify_cli/__init__.py637-749: Fetches latest release metadata and downloads ZIPdownload_and_extract_template() src/specify_cli/__init__.py751-898: Orchestrates download and extraction with StepTracker integrationensure_executable_scripts() src/specify_cli/__init__.py901-943: Sets execute bits on .sh scripts recursively (Unix only)ensure_constitution_from_template() src/specify_cli/__init__.py945-978: Copies constitution-template.md to .specify/memory/constitution.md if not existsExamples:
Agent Configuration Mapping:
The --ai flag accepts keys from the AGENT_CONFIG dictionary:
| Key | Name | Folder | CLI Required | Install URL |
|---|---|---|---|---|
copilot | GitHub Copilot | .github/ | No | N/A (IDE-based) |
claude | Claude Code | .claude/ | Yes | https://docs.anthropic.com/en/docs/claude-code/setup |
gemini | Gemini CLI | .gemini/ | Yes | https://github.com/google-gemini/gemini-cli |
cursor-agent | Cursor | .cursor/ | No | N/A (IDE-based) |
qwen | Qwen Code | .qwen/ | Yes | https://github.com/QwenLM/qwen-code |
opencode | opencode | .opencode/ | Yes | https://opencode.ai |
codex | Codex CLI | .codex/ | Yes | https://github.com/openai/codex |
windsurf | Windsurf | .windsurf/ | No | N/A (IDE-based) |
kilocode | Kilo Code | .kilocode/ | No | N/A (IDE-based) |
auggie | Auggie CLI | .augment/ | Yes | https://docs.augmentcode.com/cli/setup-auggie/install-auggie-cli |
codebuddy | CodeBuddy | .codebuddy/ | Yes | https://www.codebuddy.ai/cli |
qoder | Qoder CLI | .qoder/ | Yes | https://qoder.com/cli |
roo | Roo Code | .roo/ | No | N/A (IDE-based) |
q | Amazon Q Developer CLI | .amazonq/ | Yes | https://aws.amazon.com/developer/learning/q-developer-cli/ |
amp | Amp | .agents/ | Yes | https://ampcode.com/manual#install |
shai | SHAI | .shai/ | Yes | https://github.com/ovh/shai |
bob | IBM Bob | .bob/ | No | N/A (IDE-based) |
Sources: src/specify_cli/__init__.py126-229 (AGENT_CONFIG), src/specify_cli/__init__.py980-1279 (init command)
specify checkValidates that required and optional tools are installed on the system, including git, VS Code variants, and all AI agent CLI tools.
Command Implementation: src/specify_cli/__init__.py1281-1321
Syntax:
specify check
Parameters: None
Options: None
Check Process:
Output Example:
The command uses StepTracker to display results in a tree format:
Check Available Tools
├── ● Git version control (available)
├── ● Claude Code (available)
├── ○ Gemini CLI (not found)
├── ○ GitHub Copilot (IDE-based, no CLI check)
├── ● Cursor (IDE-based, no CLI check)
└── ● Visual Studio Code (available)
Special Agent Handling:
For Claude Code, the function checks for the migrated installer path at ~/.claude/local/claude before checking PATH. This handles the behavior after running claude migrate-installer, which removes the original executable from PATH.
Sources: src/specify_cli/__init__.py1281-1321 src/specify_cli/__init__.py484-513 (check_tool function), src/specify_cli/__init__.py233 (CLAUDE_LOCAL_PATH)
specify versionDisplays version information for the CLI tool, template release, and system environment.
Command Implementation: src/specify_cli/__init__.py1323-1400
Syntax:
specify version
Parameters: None
Options: None
Version Resolution Logic:
Output Format:
The command renders a Rich panel with a table containing:
| Field | Source | Example |
|---|---|---|
| CLI Version | Package metadata or pyproject.toml | 1.2.3 |
| Template Version | GitHub API /releases/latest | 1.2.3 |
| Released | GitHub API published_at | 2024-01-15 |
| Python | platform.python_version() | 3.11.5 |
| Platform | platform.system() | Linux |
| Architecture | platform.machine() | x86_64 |
| OS Version | platform.version() | #1 SMP PREEMPT_DYNAMIC... |
GitHub API Integration:
The command fetches the latest release information using the same authentication mechanism as init:
GH_TOKEN and GITHUB_TOKEN environment variables via _github_auth_headers() src/specify_cli/__init__.py63-66Sources: src/specify_cli/__init__.py1323-1400 src/specify_cli/__init__.py1413-1431 (get_speckit_version helper)
The extension subcommand group provides lifecycle management for extensions. All extension commands require execution from within a spec-kit project directory (must have .specify/ folder).
Extension Subapp Structure: src/specify_cli/__init__.py1405-1410
Project Root Validation:
All extension commands perform this check:
specify extension listLists installed extensions with their metadata and status.
Command Implementation: src/specify_cli/__init__.py1434-1475
Syntax:
specify extension list [OPTIONS]
Options:
| Option | Type | Default | Description |
|---|---|---|---|
--available | bool | False | Show available extensions from catalog (future feature) |
--all | bool | False | Show both installed and available (future feature) |
Output Format:
For each installed extension, displays:
Internal Flow:
Sources: src/specify_cli/__init__.py1434-1475
specify extension addInstalls an extension from the catalog, a URL, or a local directory.
Command Implementation: src/specify_cli/__init__.py1477-1595
Syntax:
specify extension add EXTENSION [OPTIONS]
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
extension | str | Yes | Extension name/ID (catalog), file path (local), or extension name (URL) |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
--dev | bool | False | Install from local directory |
--from | str | None | Install from custom URL (HTTPS required, HTTP only for localhost) |
Installation Sources:
Version Compatibility:
The command uses get_speckit_version() src/specify_cli/__init__.py1413-1431 to determine the current spec-kit version and passes it to the installation methods for compatibility checking.
Error Handling:
Catches and displays specific exceptions:
ValidationError: Extension manifest validation failuresCompatibilityError: Spec-kit version incompatibilityExtensionError: General extension system errorsExamples:
Sources: src/specify_cli/__init__.py1477-1595
specify extension removeUninstalls an extension with optional configuration preservation.
Command Implementation: src/specify_cli/__init__.py1598-1658
Syntax:
specify extension remove EXTENSION [OPTIONS]
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
extension | str | Yes | Extension ID to remove |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
--keep-config | bool | False | Don't remove config files |
--force | bool | False | Skip confirmation |
Removal Process:
Backup Location:
When --keep-config is not specified, configuration files are backed up to .specify/extensions/.backup/{extension_id}/ before removal.
Sources: src/specify_cli/__init__.py1598-1658
specify extension searchSearches the extension catalog with filtering options.
Command Implementation: src/specify_cli/__init__.py1661-1729
Syntax:
specify extension search [QUERY] [OPTIONS]
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
query | str | No | Search query string |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
--tag | str | None | Filter by tag (e.g., docker, kubernetes) |
--author | str | None | Filter by author |
--verified | bool | False | Show only verified extensions |
Search Flow:
Output Format:
For each matching extension:
Examples:
Sources: src/specify_cli/__init__.py1661-1729
specify extension infoDisplays detailed information about a specific extension from the catalog.
Command Implementation: src/specify_cli/__init__.py1732-1837
Syntax:
specify extension info EXTENSION
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
extension | str | Yes | Extension ID or name |
Information Displayed:
The command shows comprehensive metadata including:
| Section | Fields |
|---|---|
| Header | Name, version, ID, verified status |
| Description | Full description text |
| Author & License | Author, license type |
| Requirements | Spec-kit version, required tools with versions |
| Provides | Command count, hook count |
| Tags | List of tags |
| Statistics | Downloads, stars |
| Links | Repository, homepage, documentation, changelog |
| Installation Status | Whether installed, commands to install/remove |
Catalog Integration:
Sources: src/specify_cli/__init__.py1732-1837
specify extension updateUpdates extension(s) to the latest version from the catalog.
Command Implementation: src/specify_cli/__init__.py1840-1944
Syntax:
specify extension update [EXTENSION]
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
extension | str | No | Extension ID to update (if omitted, updates all) |
Update Process:
Current Limitations:
The command currently displays manual update instructions rather than performing automatic updates:
Automatic update functionality is planned for a future version.
Version Comparison:
Uses the packaging library for semantic version comparison:
Sources: src/specify_cli/__init__.py1840-1944
specify extension enableEnables a previously disabled extension.
Command Implementation: src/specify_cli/__init__.py1947-1989
Syntax:
specify extension enable EXTENSION
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
extension | str | Yes | Extension ID to enable |
Enable Mechanism:
Effect:
metadata["enabled"] = True in .registryextensions.ymlSources: src/specify_cli/__init__.py1947-1989
specify extension disableDisables an extension without removing it.
Command Implementation: src/specify_cli/__init__.py1991-2035
Syntax:
specify extension disable EXTENSION
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
extension | str | Yes | Extension ID to disable |
Disable Mechanism:
The disable operation is the inverse of enable:
Effect:
metadata["enabled"] = False in .registryUse Case:
Temporary disabling without losing configuration or requiring re-download. Useful for troubleshooting conflicts or testing behavior without an extension.
Sources: src/specify_cli/__init__.py1991-2035
All commands inherit these options from Typer:
| Option | Description |
|---|---|
--help / -h | Show command help and exit |
--version | Show version and exit (root command only) |
Boolean Flags:
All boolean options default to False and are enabled by specifying the flag:
Optional String Arguments:
Options like --ai and --script fall back to interactive selection when omitted:
Path Arguments:
Commands like extension add --dev accept paths that are resolved and validated:
The CLI uses Typer's exit code conventions:
| Exit Code | Meaning | Trigger |
|---|---|---|
0 | Success | Command completed successfully |
1 | General Error | Command failed with error message |
130 | User Interrupt | User pressed Ctrl+C during execution |
Exit codes are signaled via:
Commands perform upfront validation and exit early with descriptive error messages:
GitHub API errors include rate-limit information:
Rate Limit Helper Functions:
_parse_rate_limit_headers() src/specify_cli/__init__.py68-94: Extracts X-RateLimit-* and Retry-After headers_format_rate_limit_error() src/specify_cli/__init__.py96-123: Formats user-friendly error message with troubleshootingExtension commands catch specific exception types:
| Exception | Description | Handling |
|---|---|---|
ValidationError | Extension manifest validation failure | Show validation error details |
CompatibilityError | Spec-kit version incompatibility | Show compatibility requirements |
ExtensionError | General extension system error | Show generic error message |
Many commands use StepTracker src/specify_cli/__init__.py245-328 for progress display. See StepTracker and Progress Display for details.
Integration Pattern:
Commands that download templates use authenticated requests:
Authentication Flow:
Rate Limits:
Sources: src/specify_cli/__init__.py59-66 (token helpers), src/specify_cli/__init__.py68-123 (rate limit parsing)
Extension commands delegate to the ExtensionManager and related classes:
| Class | Responsibility | Location |
|---|---|---|
ExtensionManager | Main extension lifecycle management | src/specify_cli/extensions.py |
ExtensionRegistry | Registry persistence (.registry JSON) | src/specify_cli/extensions.py |
ExtensionCatalog | Catalog search and download | src/specify_cli/extensions.py |
HookExecutor | Hook execution and configuration | src/specify_cli/extensions.py |
ExtensionManifest | Manifest parsing and validation | src/specify_cli/extensions.py |
See Extension Architecture for detailed internal documentation.
This diagram maps command invocations to their implementing functions and key data structures:
Sources: src/specify_cli/__init__.py436-442 (app setup), src/specify_cli/__init__.py980-1279 (init), src/specify_cli/__init__.py1281-1321 (check), src/specify_cli/__init__.py1323-1400 (version), src/specify_cli/__init__.py1405-1410 (extension_app), src/specify_cli/__init__.py1477-1595 (extension add), src/specify_cli/__init__.py1434-1475 (extension list)
Refresh this wiki