Files
spec-kit/presets/PUBLISHING.md
Copilot 69ee7a836e feat(presets): Pluggable preset system with catalog, resolver, and skills propagation (#1787)
* Initial plan

* feat(templates): add pluggable template system with packs, catalog, resolver, and CLI commands

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* test(templates): add comprehensive unit tests for template pack system

Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>

* feat(presets): pluggable preset system with template/command overrides, catalog, and resolver

- Rename 'template packs' to 'presets' to avoid naming collision with core templates
- PresetManifest, PresetRegistry, PresetManager, PresetCatalog, PresetResolver in presets.py
- Extract CommandRegistrar to agents.py as shared infrastructure
- CLI: specify preset list/add/remove/search/resolve/info
- CLI: specify preset catalog list/add/remove
- --preset option on specify init
- Priority-based preset stacking (--priority, lower = higher precedence)
- Command overrides registered into all detected agent directories (17+ agents)
- Extension command safety: skip registration if target extension not installed
- Multi-catalog support: env var, project config, user config, built-in defaults
- resolve_template() / Resolve-Template in bash/PowerShell scripts
- Self-test preset: overrides all 6 core templates + 1 command
- Scaffold with 4 examples: core/extension template and command overrides
- Preset catalog (catalog.json, catalog.community.json)
- Documentation: README.md, ARCHITECTURE.md, PUBLISHING.md
- 110 preset tests, 253 total tests passing

* feat(presets): propagate command overrides to skills via init-options

- Add save_init_options() / load_init_options() helpers that persist
  CLI flags from 'specify init' to .specify/init-options.json
- PresetManager._register_skills() overwrites SKILL.md files when
  --ai-skills was used during init and corresponding skill dirs exist
- PresetManager._unregister_skills() restores core template content
  on preset removal
- registered_skills stored in preset registry metadata
- 8 new tests covering skill override, skip conditions, and restore

* fix: address PR check failures (ruff F541, CodeQL URL substring)

- Remove extraneous f-prefix from two f-strings without placeholders
- Replace substring URL check in test with startswith/endswith assertions
  to satisfy CodeQL incomplete URL substring sanitization rule

* fix: address Copilot PR review comments

- Move save_init_options() before preset install so skills propagation
  works during 'specify init --preset --ai-skills'
- Clean up downloaded ZIP after successful preset install during init
- Validate --from URL scheme (require HTTPS, HTTP only for localhost)
- Expose unregister_commands() on extensions.py CommandRegistrar wrapper
  instead of reaching into private _registrar field
- Use _get_merged_packs() for search() and get_pack_info() so all
  active catalogs are searched, not just the highest-priority one
- Fix fetch_catalog() cache to verify cached URL matches current URL
- Fix PresetResolver: script resolution uses .sh extension, consistent
  file extensions throughout resolve(), and resolve_with_source()
  delegates to resolve() to honor template_type parameter
- Fix bash common.sh: fall through to directory scan when python3
  returns empty preset list
- Fix PowerShell Resolve-Template: filter out dot-folders and sort
  extensions deterministically

* fix: narrow empty except blocks and add explanatory comments

* fix: address Copilot PR review comments (round 2)

- Fix init --preset error masking: distinguish "not found" from real errors
- Fix bash resolve_template: skip hidden dirs in extensions (match Python/PS)
- Fix temp dir leaks in tests: use temp_dir fixture instead of mkdtemp
- Fix self-test catalog entry: add note that it's local-only (no download_url)
- Fix Windows path issue in resolve_with_source: use Path.relative_to()
- Fix skill restore path: use project's .specify/templates/commands/ not source tree
- Add encoding="utf-8" to all file read/write in agents.py
- Update test to set up core command templates for skill restoration

* fix: remove self-test from catalog.json (local-only preset)

* fix: address Copilot PR review comments (round 3)

- Fix PS Resolve-Template fallback to skip dot-prefixed dirs (.cache)
- Rename _catalog to _catalog_name for consistency with extension system
- Enforce install_allowed policy in CLI preset add and download_pack()
- Fix shell injection: pass registry path via env var instead of string interpolation

* fix: correct PresetError docstring from template to preset

* Removed CHANGELOG requirement

* Applying review recommendations

* Applying review recommendations

* Applying review recommendations

* Applying review recommendations

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
2026-03-13 15:09:14 -05:00

8.2 KiB

Preset Publishing Guide

This guide explains how to publish your preset to the Spec Kit preset catalog, making it discoverable by specify preset search.

Table of Contents

  1. Prerequisites
  2. Prepare Your Preset
  3. Submit to Catalog
  4. Verification Process
  5. Release Workflow
  6. Best Practices

Prerequisites

Before publishing a preset, ensure you have:

  1. Valid Preset: A working preset with a valid preset.yml manifest
  2. Git Repository: Preset hosted on GitHub (or other public git hosting)
  3. Documentation: README.md with description and usage instructions
  4. License: Open source license file (MIT, Apache 2.0, etc.)
  5. Versioning: Semantic versioning (e.g., 1.0.0)
  6. Testing: Preset tested on real projects with specify preset add --dev

Prepare Your Preset

1. Preset Structure

Ensure your preset follows the standard structure:

your-preset/
├── preset.yml                 # Required: Preset manifest
├── README.md                  # Required: Documentation
├── LICENSE                    # Required: License file
├── CHANGELOG.md               # Recommended: Version history
│
├── templates/                 # Template overrides
│   ├── spec-template.md
│   ├── plan-template.md
│   └── ...
│
└── commands/                  # Command overrides (optional)
    └── speckit.specify.md

Start from the scaffold if you're creating a new preset.

2. preset.yml Validation

Verify your manifest is valid:

schema_version: "1.0"

preset:
  id: "your-preset"               # Unique lowercase-hyphenated ID
  name: "Your Preset Name"        # Human-readable name
  version: "1.0.0"                # Semantic version
  description: "Brief description (one sentence)"
  author: "Your Name or Organization"
  repository: "https://github.com/your-org/spec-kit-preset-your-preset"
  license: "MIT"

requires:
  speckit_version: ">=0.1.0"      # Required spec-kit version

provides:
  templates:
    - type: "template"
      name: "spec-template"
      file: "templates/spec-template.md"
      description: "Custom spec template"
      replaces: "spec-template"

tags:                              # 2-5 relevant tags
  - "category"
  - "workflow"

Validation Checklist:

  • id is lowercase with hyphens only (no underscores, spaces, or special characters)
  • version follows semantic versioning (X.Y.Z)
  • description is concise (under 200 characters)
  • repository URL is valid and public
  • All template and command files exist in the preset directory
  • Template names are lowercase with hyphens only
  • Command names use dot notation (e.g. speckit.specify)
  • Tags are lowercase and descriptive

3. Test Locally

# Install from local directory
specify preset add --dev /path/to/your-preset

# Verify templates resolve from your preset
specify preset resolve spec-template

# Verify preset info
specify preset info your-preset

# List installed presets
specify preset list

# Remove when done testing
specify preset remove your-preset

If your preset includes command overrides, verify they appear in the agent directories:

# Check Claude commands (if using Claude)
ls .claude/commands/speckit.*.md

# Check Copilot commands (if using Copilot)
ls .github/agents/speckit.*.agent.md

# Check Gemini commands (if using Gemini)
ls .gemini/commands/speckit.*.toml

4. Create GitHub Release

Create a GitHub release for your preset version:

# Tag the release
git tag v1.0.0
git push origin v1.0.0

The release archive URL will be:

https://github.com/your-org/spec-kit-preset-your-preset/archive/refs/tags/v1.0.0.zip

5. Test Installation from Archive

specify preset add --from https://github.com/your-org/spec-kit-preset-your-preset/archive/refs/tags/v1.0.0.zip

Submit to Catalog

Understanding the Catalogs

Spec Kit uses a dual-catalog system:

  • catalog.json — Official, verified presets (install allowed by default)
  • catalog.community.json — Community-contributed presets (discovery only by default)

All community presets should be submitted to catalog.community.json.

1. Fork the spec-kit Repository

git clone https://github.com/YOUR-USERNAME/spec-kit.git
cd spec-kit

2. Add Preset to Community Catalog

Edit presets/catalog.community.json and add your preset.

⚠️ Entries must be sorted alphabetically by preset ID. Insert your preset in the correct position within the "presets" object.

{
  "schema_version": "1.0",
  "updated_at": "2026-03-10T00:00:00Z",
  "catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.community.json",
  "presets": {
    "your-preset": {
      "name": "Your Preset Name",
      "description": "Brief description of what your preset provides",
      "author": "Your Name",
      "version": "1.0.0",
      "download_url": "https://github.com/your-org/spec-kit-preset-your-preset/archive/refs/tags/v1.0.0.zip",
      "repository": "https://github.com/your-org/spec-kit-preset-your-preset",
      "license": "MIT",
      "requires": {
        "speckit_version": ">=0.1.0"
      },
      "provides": {
        "templates": 3,
        "commands": 1
      },
      "tags": [
        "category",
        "workflow"
      ],
      "created_at": "2026-03-10T00:00:00Z",
      "updated_at": "2026-03-10T00:00:00Z"
    }
  }
}

3. Submit Pull Request

git checkout -b add-your-preset
git add presets/catalog.community.json
git commit -m "Add your-preset to community catalog

- Preset ID: your-preset
- Version: 1.0.0
- Author: Your Name
- Description: Brief description
"
git push origin add-your-preset

Pull Request Checklist:

## Preset Submission

**Preset Name**: Your Preset Name
**Preset ID**: your-preset
**Version**: 1.0.0
**Repository**: https://github.com/your-org/spec-kit-preset-your-preset

### Checklist
- [ ] Valid preset.yml manifest
- [ ] README.md with description and usage
- [ ] LICENSE file included
- [ ] GitHub release created
- [ ] Preset tested with `specify preset add --dev`
- [ ] Templates resolve correctly (`specify preset resolve`)
- [ ] Commands register to agent directories (if applicable)
- [ ] Commands match template sections (command + template are coherent)
- [ ] Added to presets/catalog.community.json

Verification Process

After submission, maintainers will review:

  1. Manifest validation — valid preset.yml, all files exist
  2. Template quality — templates are useful and well-structured
  3. Command coherence — commands reference sections that exist in templates
  4. Security — no malicious content, safe file operations
  5. Documentation — clear README explaining what the preset does

Once verified, verified: true is set and the preset appears in specify preset search.


Release Workflow

When releasing a new version:

  1. Update version in preset.yml
  2. Update CHANGELOG.md
  3. Tag and push: git tag v1.1.0 && git push origin v1.1.0
  4. Submit PR to update version and download_url in presets/catalog.community.json

Best Practices

Template Design

  • Keep sections clear — use headings and placeholder text the LLM can replace
  • Match commands to templates — if your preset overrides a command, make sure it references the sections in your template
  • Document customization points — use HTML comments to guide users on what to change

Naming

  • Preset IDs should be descriptive: healthcare-compliance, enterprise-safe, startup-lean
  • Avoid generic names: my-preset, custom, test

Stacking

  • Design presets to work well when stacked with others
  • Only override templates you need to change
  • Document which templates and commands your preset modifies

Command Overrides

  • Only override commands when the workflow needs to change, not just the output format
  • If you only need different template sections, a template override is sufficient
  • Test command overrides with multiple agents (Claude, Gemini, Copilot)