Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ contact_links:
url: https://github.com/github/spec-kit/blob/main/README.md
about: Read the Spec Kit documentation and guides
- name: 🛠️ Extension Development Guide
url: https://github.com/github/spec-kit/blob/main/extensions/EXTENSION-DEVELOPMENT-GUIDE.md
url: https://github.github.io/spec-kit/extensions/developing.html
about: Learn how to develop and publish Spec Kit extensions
- name: 🤝 Contributing Guide
url: https://github.com/github/spec-kit/blob/main/CONTRIBUTING.md
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Extension Development Guide
# Developing extensions

A guide for creating Spec Kit extensions.
A guide for creating Spec Kit extensions using GitHub Copilot's skills layout.
Invoke skills in Copilot chat with hyphenated names such as
`/speckit-my-ext-hello`. Extension manifests still use dotted command identifiers
such as `speckit.my-ext.hello`; Spec Kit renders them as Copilot skills during
installation.

---

Expand Down Expand Up @@ -69,7 +73,7 @@ mkdir commands

**File**: `commands/hello.md`

```markdown
````markdown
---
description: "Say hello command"
tools: # Optional: AI tools this command uses
Expand Down Expand Up @@ -100,14 +104,22 @@ echo "Arguments: $ARGUMENTS"
## Extension Configuration

Load extension config from `.specify/extensions/my-ext/my-ext-config.yml`.
````

### 5. Test Locally

```bash
cd /path/to/spec-kit-project
specify integration install copilot --integration-options="--skills"
specify extension add --dev /path/to/my-extension
```

For a new project, initialize it with
`specify init my-project --integration copilot --integration-options="--skills"`.
If Copilot is already installed in a commands layout, follow the
[Copilot migration guidance](../integrations/copilot.md#commands-layout)
instead of installing it again.

### 6. Verify Installation

```bash
Expand All @@ -119,16 +131,17 @@ specify extension list
# Commands: 1 | Hooks: 1 | Status: Enabled
```

### 7. Test Command
### 7. Test Skill

If using Claude:
Open GitHub Copilot chat and invoke the skill:

```bash
claude
> /speckit.my-ext.hello world
```text
/speckit-my-ext-hello world
```

The command will be available in `.claude/commands/speckit.my-ext.hello.md`.
The generated skill is available in
`.github/skills/speckit-my-ext-hello/SKILL.md`. This invocation belongs in
Copilot chat, not in your terminal.

---

Expand Down Expand Up @@ -293,9 +306,13 @@ echo "Running with args: $args"

### Referencing other commands

A command body is a *template* that Spec Kit renders once per agent. Different agents invoke commands with different surface syntax — for example `/speckit.plan` (dot separator) or `/speckit-plan` (hyphen separator). Some agents also use different prefixes in skills mode (e.g. Kimi `/skill:speckit-plan`, Codex/ZCode `$speckit-plan`). So when you reference a sibling command from a body, **do not hard-code a literal invocation** like `/speckit.my-ext.prepare`. A literal is correct for exactly one agent and breaks on the rest.
A command body is a *template* that Spec Kit renders as a Copilot skill.
When referencing another command from that body, **do not hard-code its
invocation**. Use a command-reference token so Spec Kit renders the correct
skill syntax and the extension remains portable.

Instead use the agent-neutral token `__SPECKIT_COMMAND_<NAME>__`. Spec Kit resolves it to a `/speckit<separator>...` invocation using the active integration's `invoke_separator` (and integrations may post-process that further in skills output).
Use the token `__SPECKIT_COMMAND_<NAME>__`. In Copilot's skills layout,
Spec Kit resolves it to a `/speckit-...` invocation.

Encode the command name in upper case, dropping the `speckit.` prefix and turning each dotted segment separator into an underscore. A hyphen inside a segment is kept as a hyphen:

Expand All @@ -306,29 +323,23 @@ Encode the command name in upper case, dropping the `speckit.` prefix and turnin
| `speckit.git.commit.md` | `__SPECKIT_COMMAND_GIT_COMMIT__` |
| `speckit.agent-context.update.md` | `__SPECKIT_COMMAND_AGENT-CONTEXT_UPDATE__` |

The resolver maps each underscore back to the active agent's separator. An underscore separates segments and a hyphen belongs to the segment it sits in, so `AGENT-CONTEXT_UPDATE` is the two segments `agent-context` and `update` rather than three.
An underscore separates command segments and a hyphen belongs to the segment
it sits in, so `AGENT-CONTEXT_UPDATE` is the two segments `agent-context` and
`update` rather than three. Copilot renders this as
`/speckit-agent-context-update`.

**Example** — a command body that points the user at the next step:

```markdown
Once the assessment exists, the next step is `__SPECKIT_COMMAND_BUG_FIX__ slug=<slug>`.
```

This renders as `/speckit.bug.fix slug=<slug>` for a slash-based agent, `/speckit-bug-fix slug=<slug>` for a skills-based agent, and so on — the author writes it once and it stays portable. The first-party `bug` and `git` extensions use this token exclusively; see `extensions/bug/commands/` for working examples.

> **Skills mode.** Token resolution runs in both paths, so the token is safe to
> use either way. Command files go through the command-rendering path
> (`CommandRegistrar`). Skill bodies go through `_resolve_command_ref_tokens` in
> `_register_extension_skills`, which resolves the same token shape against the
> active skill style, so `__SPECKIT_COMMAND_BUG_FIX__` renders as:
>
> | Agent | Rendered |
> | --- | --- |
> | Codex, ZCode, Command Code | `$speckit-bug-fix` |
> | Claude, Copilot, Cursor, Devin, Droid, Grok and the other slash agents | `/speckit-bug-fix` |
> | Kimi | `/skill:speckit-bug-fix` |
>
> Anything else falls through to the integration's own `build_command_invocation`.
This renders as `/speckit-bug-fix slug=<slug>` in Copilot chat. The first-party
`bug` and `git` extensions use this token exclusively; see
`extensions/bug/commands/` for working examples.

For other integrations' invocation formats, see the shared
[command invocation reference](../integrations/cli.md#command-invocation).

### Script Path Rewriting

Expand Down Expand Up @@ -498,7 +509,8 @@ The following `.gitignore` features are **not applicable** in this context:

### Manual Testing

1. **Create test extension**
1. **Create test extension** in a project configured for
[Copilot skills](../integrations/copilot.md#setup).
2. **Install locally**:

```bash
Expand All @@ -511,11 +523,11 @@ The following `.gitignore` features are **not applicable** in this context:
specify extension list
```

4. **Test commands** with your AI agent
5. **Check command registration**:
4. **Test skills** in Copilot chat, for example `/speckit-my-ext-hello world`.
5. **Check skill registration**:

```bash
ls .claude/commands/speckit.my-ext.*
ls .github/skills/speckit-my-ext-*/SKILL.md
```

6. **Remove extension**:
Expand Down Expand Up @@ -601,7 +613,7 @@ Submit to the community catalog for public discovery:
- Users copy the entry to their own `catalog.json`
- Users install with: `specify extension add my-ext` (from their catalog)

See the [Extension Publishing Guide](https://github.github.com/spec-kit/extensions/publishing.html) for detailed submission instructions.
See the [Extension Publishing Guide](publishing.md) for detailed submission instructions.

---

Expand Down Expand Up @@ -757,27 +769,29 @@ hooks:

**Error**: `Extension requires spec-kit >=0.2.0`

- **Fix**: Upgrade Spec Kit using the [Upgrade Guide](../docs/upgrade.md). `uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git` remains available as a source-install fallback. If you installed from PyPI and want to stay on that route, follow the [PyPI upgrade guidance](../docs/install/pypi.md#upgrade).
- **Fix**: Upgrade Spec Kit using the [Upgrade Guide](../upgrade.md). `uv tool install specify-cli --force --from git+https://github.com/github/spec-kit.git` remains available as a source-install fallback. If you installed from PyPI and want to stay on that route, follow the [PyPI upgrade guidance](../install/pypi.md#upgrade).

**Error**: `Command file not found`

- **Fix**: Ensure command files exist at paths specified in manifest

### Commands not registered
### Skills not registered

**Symptom**: Commands don't appear in AI agent
**Symptom**: Skills don't appear in GitHub Copilot chat

**Check**:

1. `.claude/commands/` directory exists
1. The generated skill exists at `.github/skills/speckit-my-ext-hello/SKILL.md`
2. Extension installed successfully
3. Commands registered in registry:

```bash
cat .specify/extensions/.registry
```

**Fix**: Reinstall extension to trigger registration
**Fix**: Confirm Copilot is configured for the
[skills layout](../integrations/copilot.md#default-skills-layout), then
reinstall the extension to trigger registration.

### Config not loading

Expand Down Expand Up @@ -805,3 +819,5 @@ hooks:
4. **Iterate** based on feedback

Happy extending! 🚀

> Agent invocation examples on this page use GitHub Copilot's default skills syntax (`/speckit-*`). For other integrations and modes, see [Command invocation](../integrations/cli.md#command-invocation).
2 changes: 1 addition & 1 deletion docs/extensions/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ After creating tasks, sync to Jira:
- **Extension Issues**: Report to extension repository (see `specify extension info`)
- **Spec Kit Issues**: <https://github.com/github/spec-kit/issues>
- **Extension Catalog**: <https://github.com/github/spec-kit/tree/main/extensions>
- **Documentation**: See the [Extension Development Guide](https://github.com/github/spec-kit/blob/main/extensions/EXTENSION-DEVELOPMENT-GUIDE.md) and [Extension Publishing Guide](publishing.md)
- **Documentation**: See [Developing extensions](developing.md) and [Extension Publishing Guide](publishing.md)

---

Expand Down
2 changes: 1 addition & 1 deletion docs/extensions/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ A: Extensions should be free and open-source. Commercial support/services are al

- **Catalog Issues**: <https://github.com/statsperform/spec-kit/issues>
- **Extension Template**: <https://github.com/statsperform/spec-kit-extension-template> (coming soon)
- **Development Guide**: See the [Extension Development Guide](https://github.com/github/spec-kit/blob/main/extensions/EXTENSION-DEVELOPMENT-GUIDE.md)
- **Development Guide**: See [Developing extensions](developing.md)
- **Community**: Discussions and Q&A

---
Expand Down
2 changes: 2 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@
items:
- name: Overview
href: extensions/overview.md
- name: Developing
href: extensions/developing.md
- name: Publishing
href: extensions/publishing.md

Expand Down
2 changes: 1 addition & 1 deletion extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ For the raw catalog data, see [`catalog.community.json`](catalog.community.json)

To add your extension to the community catalog:

1. **Prepare your extension** following the [Extension Development Guide](EXTENSION-DEVELOPMENT-GUIDE.md)
1. **Prepare your extension** following the [Extension Development Guide](https://github.github.io/spec-kit/extensions/developing.html)
2. **Create a GitHub release** for your extension
3. **File an issue** using the [Extension Submission](https://github.com/github/spec-kit/issues/new?template=extension_submission.yml) template with all required metadata
4. **Wait for review** — a maintainer will review the submission, update the catalog, and close the issue
Expand Down
2 changes: 1 addition & 1 deletion extensions/template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Starter template for creating a Spec Kit extension.

## Need Help?

- **Development Guide**: See EXTENSION-DEVELOPMENT-GUIDE.md
- **Development Guide**: See [Extension Development Guide](https://github.github.io/spec-kit/extensions/developing.html)
- **API Reference**: See EXTENSION-API-REFERENCE.md
- **Publishing Guide**: See the [Extension Publishing Guide](https://github.github.com/spec-kit/extensions/publishing.html)
- **User Guide**: See the [Extension User Guide](https://github.github.io/spec-kit/extensions/overview.html)
Expand Down
2 changes: 1 addition & 1 deletion tests/extensions/bug/test_bug_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def test_assess_ensures_bug_directory_before_hook_checks():

@pytest.mark.parametrize("path", [
ROOT / "extensions/EXTENSION-API-REFERENCE.md",
ROOT / "extensions/EXTENSION-DEVELOPMENT-GUIDE.md",
ROOT / "docs/extensions/developing.md",
ROOT / "docs/extensions/overview.md",
EXT_DIR / "README.md",
])
Expand Down
Loading