# Spec Kit Extension System Architecture and Publishing Guide

> Explore the Spec Kit extension system architecture powered by seven core components. Learn how to publish your own third-party extensions for the github spec kit with this comprehensive guide.

- Repository: [GitHub/spec-kit](https://github.com/github/spec-kit)
- Tags: architecture
- Published: 2026-03-05

---

**The Spec Kit extension system is a modular plug-in architecture built on seven core components—ExtensionManifest, ExtensionRegistry, ExtensionManager, CommandRegistrar, HookExecutor, ExtensionCatalog, and ConfigManager—that enables third-party commands, configuration schemas, and lifecycle hooks without core framework modifications.**

The `github/spec-kit` repository implements this extension system to provide a clean separation between core functionality and community contributions. Developers can distribute new capabilities through GitHub releases and the community catalog while the system handles compatibility checks, command registration, and layered configuration management automatically.

## Core Architecture Components

The Spec Kit extension system architecture centers on seven specialized classes defined in [`src/specify_cli/extensions.py`](https://github.com/github/spec-kit/blob/main/src/specify_cli/extensions.py), each handling a distinct lifecycle phase.

### ExtensionManifest

The **ExtensionManifest** class parses and validates the [`extension.yml`](https://github.com/github/spec-kit/blob/main/extension.yml) file (schema version 1.0) according to the specification in [`EXTENSION-API-REFERENCE.md`](https://github.com/github/spec-kit/blob/main/EXTENSION-API-REFERENCE.md). Located at `src/specify_cli/extensions.py#L39-L78`, it guarantees correct IDs, semantic versions, required fields, command definitions, and hook blocks before any installation proceeds.

### ExtensionRegistry

**ExtensionRegistry** (`src/specify_cli/extensions.py#L164-L244`) maintains a JSON database at `.specify/extensions/.registry` tracking every installed extension's metadata. It handles add, remove, and list queries while persisting version, source, hash, and registered command names to disk.

### ExtensionManager

The **ExtensionManager** (`src/specify_cli/extensions.py#L258-L508`) orchestrates the full extension lifecycle. It performs compatibility checks against the current Spec Kit version using `packaging.specifiers`, copies source directories into `.specify/extensions/<extension-id>/`, and manages clean removal while optionally preserving `*-config.yml` files.

### CommandRegistrar

**CommandRegistrar** (`src/specify_cli/extensions.py#L845-L985`) converts extension-provided command definitions into agent-specific formats. It rewrites placeholders like `$ARGUMENTS` into agent-specific tokens and writes final command files to per-agent locations such as `.claude/commands/` or `.gemini/commands/`, using the `AGENT_CONFIG` dictionary defined in [`src/specify_cli/__init__.py`](https://github.com/github/spec-kit/blob/main/src/specify_cli/__init__.py).

### HookExecutor

The **HookExecutor** (`src/specify_cli/extensions.py#L1025-L1057`) registers and executes event hooks defined in the manifest (`after_tasks`, `before_commit`, etc.). It injects hook definitions into the project-level [`.specify/extensions.yml`](https://github.com/github/spec-kit/blob/main/.specify/extensions.yml) and manages their deregistration during uninstallation.

### ExtensionCatalog

**ExtensionCatalog** (`src/specify_cli/extensions.py#L969-L1070`) functions as the remote catalog client. It fetches [`catalog.json`](https://github.com/github/spec-kit/blob/main/catalog.json) (or the community variant [`catalog.community.json`](https://github.com/github/spec-kit/blob/main/catalog.community.json)) from GitHub, caches results under `.specify/extensions/.cache`, and provides search helpers used by the `specify extension search` CLI command.

### ConfigManager

The **ConfigManager** (`src/specify_cli/extensions.py#L1240-L1310`) merges layered configuration sources—defaults, project settings, local overrides, and environment variables—exposing `get_config()` for full dictionaries and `get_value()` for dot-notation access to specific settings.

## Extension Installation Lifecycle

When running `specify extension install`, the ExtensionManager executes a six-phase process:

1. **Manifest validation** – `ExtensionManifest` validates the [`extension.yml`](https://github.com/github/spec-kit/blob/main/extension.yml) structure and required fields.

2. **Compatibility verification** – `ExtensionManager.check_compatibility()` ensures the extension's `requires.speckit_version` range matches the current installation using semantic versioning specifiers.

3. **File deployment** – The entire source directory copies into `.specify/extensions/<extension-id>/`.

4. **Command registration** – `CommandRegistrar` scans `provides.commands`, rewrites front-matter, adjusts script paths, and writes files like [`.claude/commands/speckit.myext.mycmd.md`](https://github.com/github/spec-kit/blob/main/.claude/commands/speckit.myext.mycmd.md).

5. **Hook registration** – `HookExecutor.register_hooks()` injects definitions into [`.specify/extensions.yml`](https://github.com/github/spec-kit/blob/main/.specify/extensions.yml).

6. **Registry persistence** – `ExtensionRegistry.add()` records the installation metadata.

During removal via `specify extension remove`, the manager reverses these steps, with optional preservation of configuration files.

## Publishing Extensions to the Community Catalog

Publishing a Spec Kit extension requires five specific steps:

1. **Repository creation** – Create a public GitHub repository following the directory layout specified in [`EXTENSION-PUBLISHING-GUIDE.md`](https://github.com/github/spec-kit/blob/main/EXTENSION-PUBLISHING-GUIDE.md).

2. **Manifest authoring** – Write a valid [`extension.yml`](https://github.com/github/spec-kit/blob/main/extension.yml) containing fields: `id`, `name`, `version`, `requires.speckit_version`, `provides.commands`, optional `hooks`, `tags`, and `defaults`. Reference the schema in [`EXTENSION-API-REFERENCE.md`](https://github.com/github/spec-kit/blob/main/EXTENSION-API-REFERENCE.md).

3. **Release tagging** – Tag a semantic version (`git tag vX.Y.Z && git push origin vX.Y.Z`) and publish a GitHub Release. The generated zip URL (e.g., `https://github.com/your-org/spec-kit-myext/archive/refs/tags/v1.0.0.zip`) serves as the distribution endpoint.

4. **Catalog submission** – Fork `github/spec-kit`, edit [`extensions/catalog.community.json`](https://github.com/github/spec-kit/blob/main/extensions/catalog.community.json) to insert metadata including download URL and version requirements, and update [`extensions/README.md`](https://github.com/github/spec-kit/blob/main/extensions/README.md) to list the extension in the Available Extensions table. Submit a pull request against the upstream repository.

5. **Verification** – Maintainers execute automated manifest validation and URL accessibility checks, followed by manual security and functionality reviews. Upon approval, `verified: true` is set, making the extension appear in `specify extension search --verified` results.

## Programmatic Extension Management

The Spec Kit extension system exposes Python APIs for automation and integration workflows.

### Installing from a Local Directory

```python
from pathlib import Path
from specify_cli.extensions import ExtensionManager

project_root = Path.cwd()
manager = ExtensionManager(project_root)

# Assumes `my-extension/` contains a valid extension.yml

manifest = manager.install_from_directory(
    source_dir=Path("my-extension"),
    speckit_version="0.1.0",
    register_commands=True
)

print(f"Installed {manifest.id} v{manifest.version}")

```

### Installing from a Remote ZIP Archive

```python
from pathlib import Path
from specify_cli.extensions import ExtensionCatalog, ExtensionManager

project_root = Path.cwd()
catalog = ExtensionCatalog(project_root)

# Download the zip for extension ID "jira"

zip_path = catalog.download_extension("jira")
manager = ExtensionManager(project_root)

manifest = manager.install_from_zip(zip_path, speckit_version="0.1.0")
print(f"Installed {manifest.id} from {zip_path}")

```

### Registering Commands for Specific Agents

```python
from pathlib import Path
from specify_cli.extensions import CommandRegistrar, ExtensionManifest

registrar = CommandRegistrar()
manifest = ExtensionManifest(Path("my-extension/extension.yml"))

registered = registrar.register_commands_for_agent(
    agent_name="claude",
    manifest=manifest,
    extension_dir=Path("my-extension"),
    project_root=Path.cwd()
)
print("Claude commands registered:", registered)

```

### Accessing Layered Configuration

```python
from pathlib import Path
from specify_cli.extensions import ConfigManager

cfg = ConfigManager(project_root=Path.cwd(), extension_id="jira")
full_cfg = cfg.get_config()

print(full_cfg["connection"]["url"])       # Merged from defaults → env

print(cfg.get_value("features.enabled"))   # Dot-notation shortcut

```

## Summary

- The Spec Kit extension system architecture comprises seven specialized classes handling manifests, registries, lifecycle management, command translation, hook execution, remote catalogs, and configuration.
- Installation follows a strict six-phase validation and registration process that ensures compatibility before modifying the project structure.
- Extensions publish through GitHub Releases and community catalog pull requests, with automated verification ensuring quality and security.
- All core functionality resides in [`src/specify_cli/extensions.py`](https://github.com/github/spec-kit/blob/main/src/specify_cli/extensions.py), with documentation in [`EXTENSION-API-REFERENCE.md`](https://github.com/github/spec-kit/blob/main/EXTENSION-API-REFERENCE.md) and [`EXTENSION-PUBLISHING-GUIDE.md`](https://github.com/github/spec-kit/blob/main/EXTENSION-PUBLISHING-GUIDE.md).
- The system supports programmatic installation from local directories, remote ZIP archives, and provides layered configuration management with dot-notation access.

## Frequently Asked Questions

### How does the Spec Kit extension system validate extension compatibility?

The `ExtensionManager.check_compatibility()` method uses the `packaging.specifiers` library to compare the current Spec Kit version against the `requires.speckit_version` range defined in the extension's [`extension.yml`](https://github.com/github/spec-kit/blob/main/extension.yml) manifest. This check occurs before any files are copied to prevent incompatible installations.

### Where are extension commands stored after registration?

The `CommandRegistrar` class writes agent-specific command files to per-agent directories such as `.claude/commands/` or `.gemini/commands/`. It rewrites placeholders like `$ARGUMENTS` into agent-specific tokens using the `AGENT_CONFIG` dictionary defined in [`src/specify_cli/__init__.py`](https://github.com/github/spec-kit/blob/main/src/specify_cli/__init__.py), ensuring commands match each agent's expected format and location.

### What is the purpose of the ExtensionCatalog class?

`ExtensionCatalog` (`src/specify_cli/extensions.py#L969-L1070`) fetches remote extension metadata from [`catalog.community.json`](https://github.com/github/spec-kit/blob/main/catalog.community.json), caches it locally under `.specify/extensions/.cache`, and provides search and download functionality. It enables the `specify extension search` command and handles ZIP downloads from GitHub release URLs during remote installations.

### How do I submit a new extension to the verified community catalog?

Create a public GitHub repository with a valid [`extension.yml`](https://github.com/github/spec-kit/blob/main/extension.yml), tag a semantic version release, then fork `github/spec-kit` and submit a pull request modifying [`extensions/catalog.community.json`](https://github.com/github/spec-kit/blob/main/extensions/catalog.community.json) and [`extensions/README.md`](https://github.com/github/spec-kit/blob/main/extensions/README.md). Maintainers will verify the manifest schema, test URL accessibility, and perform security reviews before setting `verified: true` in the catalog entry.