This page is generated from the following source files:
Spec Kit is a CLI tool for managing AI assistant configurations through a template and preset system. The architecture centers on four core subsystems: CLI orchestration with GitHub API integration, agent command registration, extension management, and preset template resolution. These components work together to provide a unified interface for scaffolding and maintaining AI assistant configurations across multiple platforms.
The system is organized into four primary modules within src/specify_cli/, each handling a distinct architectural concern.
The main entry point (src/specify_cli/__init__.py:71-949) orchestrates GitHub API interactions with robust rate limiting. The _parse_rate_limit_headers() function extracts standard GitHub headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) and converts epoch timestamps to localized datetime objects. The _format_rate_limit_error() function generates user-friendly error messages with troubleshooting guidance, including the distinction between authenticated (5,000 requests/hour) and unauthenticated (60 requests/hour) rate limits.
The download_template_from_github() function handles template asset retrieval with streaming downloads and progress indicators. It validates release assets against expected naming patterns and provides detailed error context when assets are missing.
The src/specify_cli/agents.py:167-230 module provides YAML frontmatter parsing and rendering for agent command files. The parse_frontmatter() function extracts YAML metadata between --- delimiters, while render_frontmatter() reconstructs the frontmatter dictionary back to YAML format. The _adjust_script_paths() method transforms extension-relative paths (../../scripts/) to repository-relative paths (.specify/scripts/), ensuring portability across different installation contexts.
The src/specify_cli/extensions.py:34-71 module defines the extension error hierarchy and catalog data structures. ValidationError is raised when manifest validation fails, while CompatibilityError indicates version mismatches. The CatalogEntry dataclass captures extension metadata with fields for URL, name, priority, install permissions, and description.
Similarly, src/specify_cli/presets.py:31-52 defines PresetCatalogEntry with an identical structure for preset management, along with PresetValidationError and PresetCompatibilityError exceptions. This parallel structure allows the extension and preset systems to share common patterns while maintaining separate namespaces.
正在加载图表渲染器...
The diagram above illustrates the four core modules and their internal relationships. The CLI module's download function depends on both rate limiting and error formatting capabilities. The agent module's rendering pipeline flows from parsing through path adjustment.
The preset system implements a priority-based template resolution mechanism that searches across four layers: overrides, presets, extensions, and core templates. This architecture is documented in presets/ARCHITECTURE.md:1-45.
When PresetResolver.resolve_template('spec-template') is called, the system walks the priority stack:
| Priority | Source | Path Pattern | Use Case |
|---|---|---|---|
| 1 (highest) | Override | .specify/templates/overrides/ | Project-local one-off customizations |
| 2 | Preset | .specify/presets/<id>/templates/ | Shareable, stackable customizations |
| 3 | Extension | .specify/extensions/<id>/templates/ | Extension-provided templates |
| 4 (lowest) | Core | .specify/templates/ | Shipped defaults |
When multiple presets provide the same template, the one with the lowest priority number wins. This allows fine-grained control over template stacking.
The resolution logic is implemented three times to ensure consistency across execution environments:
PresetResolver class in src/specify_cli/presets.pyresolve_template() function in scripts/bash/common.shResolve-Template function in scripts/powershell/common.ps1This tripartite implementation ensures that template resolution behaves identically whether invoked through the Python CLI, shell scripts, or PowerShell cmdlets.
正在加载图表渲染器...
The flowchart demonstrates the resolution decision tree. Each layer is checked in sequence, with preset conflicts resolved by priority number comparison.
When presets include type: "command" entries, the PresetManager registers them across all detected agent directories using the shared CommandRegistrar from src/specify_cli/agents.py. The command registration flow is documented in presets/ARCHITECTURE.md:44-91.
Command names follow the pattern speckit.<ext-id>.<cmd-name>. When a command has three or more dot segments, the system extracts the extension ID and verifies that .specify/extensions/<ext-id>/ exists. If the extension is not installed, the command registration is skipped to prevent orphan files referencing non-existent extensions. Core commands (e.g., speckit.specify with only two segments) bypass this check and are always registered.
The CommandRegistrar renders command files in different formats based on the target agent:
| Agent | Format | File Extension | Argument Placeholder |
|---|---|---|---|
| Claude, Cursor, opencode, Windsurf | Markdown | .md | $ARGUMENTS |
| Copilot | Markdown | .agent.md + .prompt.md | $ARGUMENTS |
| Gemini, Qwen, Tabnine | TOML | .toml | {{args}} |
The frontmatter rendering logic in src/specify_cli/agents.py:198-230 handles YAML serialization with default_flow_style=False and sort_keys=False to preserve human readability and key ordering.
When specify preset remove is executed, the registered commands are read from the registry metadata, and corresponding files are deleted from each agent directory. This includes Copilot companion .prompt.md files, ensuring complete cleanup without orphan artifacts.
The extension system provides a comprehensive API for creating, registering, and managing extensions. The manifest schema and Python API are documented in extensions/EXTENSION-API-REFERENCE.md:1-115 and extensions/EXTENSION-API-REFERENCE.md:117-178.
The extension.yml manifest follows schema version 1.0 with the following structure:
yaml1schema_version: "1.0" 2 3extension: 4 id: string # Pattern: ^[a-z0-9-]+$ 5 name: string 6 version: string # Semantic version (X.Y.Z) 7 description: string # <200 chars 8 author: string 9 repository: string # Valid URL 10 license: string 11 homepage: string # Optional 12 13requires: 14 speckit_version: string # Version specifier (>=X.Y.Z) 15 tools: # Optional array 16 - name: string 17 version: string 18 required: boolean 19 20provides: 21 commands: # At least one required 22 - name: string # Pattern: ^speckit\.[a-z0-9-]+\.[a-z0-9-]+$ 23 file: string 24 description: string 25 aliases: [string] 26 27hooks: # Optional event hooks 28 event_name: 29 command: string 30 optional: boolean 31 prompt: string 32 description: string 33 condition: string
The ExtensionManifest class provides properties for accessing manifest data:
python1from specify_cli.extensions import ExtensionManifest 2 3manifest = ExtensionManifest(Path("extension.yml")) 4manifest.id # str: Extension ID 5manifest.name # str: Extension name 6manifest.version # str: Version 7manifest.requires_speckit_version # str: Required spec-kit version 8manifest.commands # List[Dict]: Command definitions 9manifest.hooks # Dict: Hook definitions 10manifest.get_hash() # str: SHA256 hash of manifest
The ExtensionRegistry class manages installed extensions:
python1from specify_cli.extensions import ExtensionRegistry 2 3registry = ExtensionRegistry(extensions_dir) 4registry.add(extension_id: str, metadata: dict) 5registry.remove(extension_id: str) 6metadata = registry.get(extension_id: str) # Optional[dict] 7extensions = registry.list() # Dict[str, dict]
The preset catalog system, documented in presets/ARCHITECTURE.md:92-115, manages template discovery through a hierarchical configuration:
SPECKIT_PRESET_CATALOG_URL overrides all other sources.specify/preset-catalogs.yml for project-specific catalogs~/.specify/preset-catalogs.yml for user-wide catalogsCatalogs are fetched with a 1-hour cache using SHA256-hashed cache files. Each catalog entry includes a priority field for merge ordering and an install_allowed flag to control installation permissions.
The test suite validates the system's behavior through integration tests, static analysis, and unit tests. Key test patterns are found in tests/test_cursor_frontmatter.py:37-100, tests/test_merge.py:8-50, and tests/test_presets.py:50-78.
The TestCursorFrontmatterIntegration class in tests/test_cursor_frontmatter.py:76-263 uses pytest fixtures to create minimal git repositories with spec-kit structure. The git_repo fixture:
.specify/config.yaml with project metadata.specify/templates/Tests verify that .mdc files receive YAML frontmatter with alwaysApply: true, while non-.mdc files (like Claude's CLAUDE.md) do not receive frontmatter. The tests also ensure that existing frontmatter is not duplicated on updates.
The merge tests in tests/test_merge.py:8-140 validate the "polite merge policy" that preserves user settings:
NoneThis defensive approach prevents data loss during template updates.
The TestPresetCatalog class in tests/test_presets.py:1102-1120 validates catalog URL configuration and cache management:
presets/catalog.jsonpresets/catalog.community.jsonFalse when no cache existsThe valid preset manifest data structure for testing is defined in tests/test_presets.py:50-78, providing a complete example with schema version, preset metadata, requirements, and provided templates.
The following sequence diagram illustrates the end-to-end flow when a user installs a preset with command entries:
正在加载图表渲染器...
The sequence demonstrates the conditional logic for extension safety checks and the multi-agent rendering process. Each command is validated against installed extensions before being rendered in agent-specific formats.
The four-layer resolution stack (overrides → presets → extensions → core) provides flexibility at the cost of complexity. This design allows projects to customize templates without forking, but requires careful documentation to ensure developers understand the precedence rules.
Implementing resolution logic in Python, Bash, and PowerShell ensures broad compatibility but introduces maintenance overhead. Changes to resolution behavior must be synchronized across three codebases. The trade-off favors accessibility over simplicity.
The JSON merge strategy prioritizes data preservation over template completeness. When type mismatches occur, user data wins. This prevents data loss but may leave stale configuration values if template semantics change.
The requirement that extension commands verify the extension's presence prevents orphan files but adds a filesystem check to the registration hot path. The performance impact is minimal given the typical number of commands, but could become noticeable with hundreds of extension commands.
The 1-hour cache TTL balances freshness against API rate limits. For most development workflows, this provides adequate responsiveness while protecting GitHub's infrastructure. The SHA256-based cache key ensures correct invalidation when catalog URLs change.
Supporting multiple agent formats (Markdown, TOML, dual-file Copilot) increases implementation complexity but ensures compatibility across the AI assistant ecosystem. The CommandRegistrar abstraction isolates format-specific logic, making it easier to add new agents.
| Technology | Purpose | Rationale | Alternatives Considered |
|---|---|---|---|
| Python 3.x | Core CLI implementation | Rich ecosystem, cross-platform | Node.js, Go |
| Typer | CLI framework | Type hints, automatic help generation | Click, argparse |
| httpx | HTTP client | Async support, streaming | requests, aiohttp |
| PyYAML | YAML parsing | Standard library for YAML | ruamel.yaml |
| Rich | Terminal formatting | Progress bars, panels | colorama, termcolor |
| pytest | Testing framework | Fixtures, parametrization | unittest, nose |
| Mermaid | Architecture diagrams | Text-based, GitHub native | PlantUML, Graphviz |
| JSON | Catalog format | Universal parsing | YAML, TOML |
| SHA256 | Cache key generation | Cryptographic strength | MD5, simple hashing |
| Semantic Versioning | Version constraints | Industry standard | CalVer, custom scheme |
正在加载图表渲染器...
The dependency graph shows the unidirectional flow from CLI entry point through preset and extension systems to the shared command registration infrastructure. The test suite depends on all modules, validating integration points.
The system reads configuration from multiple sources in the following order:
SPECKIT_PRESET_CATALOG_URL, GH_TOKEN, GITHUB_TOKEN.specify/config.yaml~/.specify/preset-catalogs.ymlOn startup, the CLI:
Error handling includes detailed rate limit messages with reset times, retry-after headers, and troubleshooting guidance for authentication scenarios.