This document describes the four-layer configuration cascade system for Spec Kit extensions. The configuration system enables flexible extension behavior through multiple configuration sources with well-defined precedence rules. This allows defaults to be overridden at the project level, customized per developer without affecting version control, and dynamically adjusted via environment variables.
For information about extension installation and management, see Extension Management Commands. For details on extension architecture and manifests, see Extension Architecture. For creating extensions that use configuration, see Creating Extensions.
The extension configuration system implements a four-layer cascade where each layer can override values from lower-priority layers. The system provides a balance between sensible defaults, project-wide standardization, developer-specific customization, and runtime flexibility.
The configuration cascade operates with the following precedence (highest to lowest):
| Layer | Priority | Source | Versioned | Use Case |
|---|---|---|---|---|
| Environment Variables | 1 (highest) | SPECKIT_{EXT_ID}_{KEY} | No | CI/CD, secrets, runtime overrides |
| Local Configuration | 2 | .specify/extensions/{ext-id}/local-config.yml | No (gitignored) | Developer-specific settings |
| Project Configuration | 3 | .specify/extensions/{ext-id}/{ext-id}-config.yml | Yes | Team-wide defaults |
| Extension Defaults | 4 (lowest) | extension.yml (manifest) | Yes | Baseline configuration |
Configuration Layer Cascade Diagram
Sources: CHANGELOG.md78-87
Extension defaults are defined in the extension.yml manifest file within each extension's package. These defaults provide baseline configuration that works out-of-the-box and serve as documentation for available configuration options.
The default_config section in extension.yml defines default values:
Defaults reside within the extension package directory structure, not in the user's project:
{extension-package-root}/extension.ymlSources: CHANGELOG.md79
Project configuration provides team-wide settings that are committed to version control. This layer standardizes extension behavior across all developers working on a project.
Project configuration files are stored in the .specify/extensions/ directory:
.specify/extensions/{ext-id}/{ext-id}-config.ymlExample for the jira extension:
Project configuration files can be created:
Sources: CHANGELOG.md80
Local configuration enables developer-specific customization without affecting other team members. These files are gitignored to prevent sensitive data or personal preferences from being committed.
Local configuration files parallel project configuration but with a different filename:
.specify/extensions/{ext-id}/local-config.ymlExample for developer-specific overrides:
Local configuration files are automatically added to .gitignore by the extension system to prevent accidental credential exposure. However, for highly sensitive values like API tokens, environment variables (Layer 4) are recommended.
Sources: CHANGELOG.md81
Environment variables provide the highest-priority configuration layer, enabling runtime overrides and secure handling of sensitive values. This layer is essential for CI/CD pipelines and containerized deployments.
Environment variables follow a structured naming pattern:
SPECKIT_{EXT_ID}_{CONFIG_KEY}
Where:
SPECKIT_ is the fixed prefix{EXT_ID} is the extension identifier in uppercase with hyphens replaced by underscores{CONFIG_KEY} is the configuration key in uppercase with dots replaced by underscores| Configuration Path | Environment Variable |
|---|---|
jira.api_url | SPECKIT_JIRA_API_URL |
jira.project_key | SPECKIT_JIRA_PROJECT_KEY |
jira.custom_field_mapping.story_points | SPECKIT_JIRA_CUSTOM_FIELD_MAPPING_STORY_POINTS |
For nested configuration objects, the path is flattened using underscores:
Sources: CHANGELOG.md82
The configuration system performs recursive deep merging of all four layers, with higher-priority layers overwriting values from lower-priority layers.
Configuration Merging Process
null values override lower layersGiven these four layers:
Final merged configuration:
Sources: CHANGELOG.md83
The ConfigManager class provides programmatic access to the merged configuration cascade. Extensions use this class to retrieve configuration values with proper precedence handling.
ConfigManager Class Diagram
get_config()Returns the fully merged configuration dictionary for the extension.
get_value(key_path, default=None)Retrieves a specific configuration value using dot-notation path traversal.
has_value(key_path)Checks if a configuration key exists in the merged configuration.
The configuration system supports nested path traversal using dot notation:
| Key Path | Traversal |
|---|---|
jira.api_url | config['jira']['api_url'] |
jira.custom_field_mapping.story_points | config['jira']['custom_field_mapping']['story_points'] |
database.connection.pool.max_size | config['database']['connection']['pool']['max_size'] |
Sources: CHANGELOG.md84-86
Extensions store configuration in a predictable directory hierarchy:
.specify/
└── extensions/
├── {ext-id}/
│ ├── {ext-id}-config.yml # Project configuration (versioned)
│ ├── local-config.yml # Local configuration (gitignored)
│ └── ... # Extension files
├── {another-ext-id}/
│ ├── {another-ext-id}-config.yml
│ ├── local-config.yml
│ └── ...
└── .registry # Extension registry (versioned)
| Extension ID | Project Config Path | Local Config Path |
|---|---|---|
jira | .specify/extensions/jira/jira-config.yml | .specify/extensions/jira/local-config.yml |
github-actions | .specify/extensions/github-actions/github-actions-config.yml | .specify/extensions/github-actions/local-config.yml |
my-custom-ext | .specify/extensions/my-custom-ext/my-custom-ext-config.yml | .specify/extensions/my-custom-ext/local-config.yml |
The extension system automatically ensures that local-config.yml files are gitignored to prevent sensitive data from being committed. The pattern **/local-config.yml is added to .gitignore during extension installation.
Sources: CHANGELOG.md80-81
For configuration values that must be present:
For configuration values that have sensible defaults:
For configuration-driven feature flags:
For complex configuration structures:
Sources: CHANGELOG.md84-86
A development team works across multiple environments:
Each developer uses their preferred environment:
CI/CD pipeline uses production:
Sensitive credentials are never committed:
Developers set tokens locally:
CI/CD injects tokens at runtime:
Teams can enable/disable experimental features per developer:
Individual developers opt in:
Project-wide standards with personal overrides:
A developer working on legacy code:
Sources: CHANGELOG.md78-87
Extensions should validate configuration during initialization to provide clear error messages:
Sources: CHANGELOG.md84-86
Refresh this wiki