Files
github-spec-kit/presets
Manfred Riem 43a54bf2d6 feat(presets): add opt-in constitution-sync preset (#3873)
* feat(presets): add opt-in constitution-sync preset

Follow-up to #3790, which removed the consistency-propagation pass from the
core /constitution command in favor of runtime resolution. Teams that treat
materialized plan/spec/tasks templates as reviewed, committed artifacts lost
the auto-sync of amended constitutional guidance on a non-forced upgrade.

Add a bundled, opt-in `constitution-sync` preset that restores that behavior
via a wrap-strategy override of speckit.constitution (composes on {CORE_TEMPLATE}
so it stays forward-compatible). It only writes into the project's own
.specify/templates scaffolds and installed command files, never into
stack-owned template layers.

- presets/constitution-sync/: preset.yml (requires >=0.14.4), wrap command,
  README documenting the tension between auto-propagation and the resolution stack
- presets/catalog.json: bundled entry
- docs/upgrade.md: document the 0.14.4 behavior change and the opt-in
- tests/test_presets.py: structural + composition coverage (TestConstitutionSyncPreset)

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* fix(presets): ship constitution-sync in wheel, clarify scope guard, assert composition

Address review feedback on #3873:

- pyproject.toml: force-include presets/constitution-sync into the wheel's
  core_pack so `_locate_bundled_preset` resolves it in a released install; the
  bundled advertisement was otherwise unshippable.
- tests/contract/test_wheel_bundled_presets.py: new contract test asserting
  every bundled preset in presets/catalog.json is force-included (guards lean too).
- commands/speckit.constitution.md: explicitly state the propagation section
  supersedes the core Scope Guard, which otherwise says dependent templates are
  not modified here.
- tests/test_presets.py: assert resolve_content substitutes {CORE_TEMPLATE} and
  the effective command embeds both the core body and the sync pass.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* test(presets): parse frontmatter as YAML in constitution-sync wrapper test

Address review feedback on #3873: assert `strategy: wrap` structurally by
parsing the Markdown frontmatter as YAML (instead of a substring match that
could false-positive on body text), and assert {CORE_TEMPLATE} in the body
section only.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* docs(presets): reframe constitution-sync README around behavior and caveats

Rework the preset's user-facing docs to describe what it does, what it does
not do, and the caveats you take on — rather than leading with version/origin
history. The preset stack is the project's forward direction, so the README no
longer positions this as "restoring pre-0.14.4 behavior."

Also make the edit-in-place vs. composition conflict explicit and consistent
across the wrapper command and docs: propagation into command files/templates
that are provided or wrapped by a preset/extension is clobbered on stack
reconciliation (integration use/upgrade, preset/extension install/remove), so
the wrapper restricts propagation to project-local artifacts the team owns.

- README: forward-looking "What it does / does not do / When to use / Caveats"
- speckit.constitution.md: step 4 no longer hand-edits composed command files;
  closing caveat covers command files too
- docs/upgrade.md: note the composition-model conflict in the opt-in section
- tests: assert the updated closing-caveat wording

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* docs(presets): tweak constitution-sync README default-behavior wording

Phrase the default-behavior note as "the current version of Spec Kit" and
rewrap the opening paragraph.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* docs(presets): keep emphasis spans on one line in constitution-sync README

Avoid **bold** spans broken across soft line breaks (runtime resolution,
reviewed committed artifacts) so they render consistently.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* docs(presets): refocus constitution-sync README on what it restores

Reframe the intro around what the preset restores and what the user opts
into, rather than describing current Spec Kit default behavior. Be honest
that propagation was removed deliberately (duplicates the source of truth,
fights composition) and this preset knowingly reintroduces it and its
tradeoffs. Minor flow fixes (comma splice, terse bullet).

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* docs(upgrade): de-pin version from /constitution behavior-change section

The upgrade guide always describes the latest version, so hard-pinning
"0.14.4" in the heading and "Starting in 0.14.4" in the body added no
value. Keep the #3790 provenance link and the "no longer propagates"
framing; the machine-readable version gate stays in preset.yml.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

* docs(upgrade): clarify non-breaking nuance and presets direction

Note that the /constitution scope change is only noticeable if you relied
on the old edit-in-place behavior, and add the forward-looking framing:
presets and extensions — not in-place file edits — are how Spec Kit now
governs, versions, and audits shared assets across repositories.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: afa7c1d2-147b-4f62-a6fc-a2cc824cfa3e
2026-07-30 13:36:13 -05:00
..

Presets

Presets are stackable, priority-ordered collections of template and command overrides for Spec Kit. They let you customize both the artifacts produced by the Spec-Driven Development workflow (specs, plans, tasks, checklists, constitutions) and the commands that guide the LLM in creating them — without forking or modifying core files.

How It Works

When Spec Kit needs a template (e.g. spec-template), it walks a resolution stack:

  1. .specify/templates/overrides/ — project-local one-off overrides
  2. .specify/presets/<preset-id>/templates/ — installed presets (sorted by priority)
  3. .specify/extensions/<ext-id>/templates/ — extension-provided templates
  4. .specify/templates/ — core templates shipped with Spec Kit

If no preset is installed, core templates are used — exactly the same behavior as before presets existed.

Template resolution happens at runtime — although preset files are copied into .specify/presets/<id>/ during installation, Spec Kit walks the resolution stack on every template lookup rather than merging templates into a single location.

For detailed resolution and command registration flows, see ARCHITECTURE.md.

Command Overrides

Presets can also override the commands that guide the SDD workflow. Templates define what gets produced (specs, plans, constitutions); commands define how the LLM produces them (the step-by-step instructions).

Unlike templates, command overrides are applied at install time. When a preset includes type: "command" entries, the commands are registered into all detected agent directories (.claude/commands/, .gemini/commands/, etc.) in the correct format (Markdown or TOML with appropriate argument placeholders). When the preset is removed, the registered commands are cleaned up.

Quick Start

# Search available presets
specify preset search

# Install a preset from the catalog
specify preset add healthcare-compliance

# Install from a local directory (for development)
specify preset add --dev ./my-preset

# Install with a specific priority (lower = higher precedence)
specify preset add healthcare-compliance --priority 5

# List installed presets
specify preset list

# See which template a name resolves to
specify preset resolve spec-template

# Get detailed info about a preset
specify preset info healthcare-compliance

# Remove a preset
specify preset remove healthcare-compliance

Stacking Presets

Multiple presets can be installed simultaneously. The --priority flag controls which one wins when two presets provide the same template (lower number = higher precedence):

specify preset add enterprise-safe --priority 10      # base layer
specify preset add healthcare-compliance --priority 5  # overrides enterprise-safe
specify preset add pm-workflow --priority 1            # overrides everything

Presets override by default, they don't merge. If two presets both provide spec-template with the default replace strategy, the one with the lowest priority number wins entirely. However, presets can use composition strategies to augment rather than replace content.

Composition Strategies

Presets can declare a strategy per template to control how content is combined. The name field identifies which template to compose with in the priority stack, while file points to the actual content file (which can differ from the convention path templates/<name>.md):

provides:
  templates:
    - type: "template"
      name: "spec-template"
      file: "templates/spec-addendum.md"
      strategy: "append"        # adds content after the core template
Strategy Description
replace (default) Fully replaces the lower-priority template
prepend Places content before the resolved lower-priority template, separated by a blank line
append Places content after the resolved lower-priority template, separated by a blank line
wrap Content contains {CORE_TEMPLATE} placeholder (or $CORE_SCRIPT for scripts) replaced with the lower-priority content

Supported combinations:

Type replace prepend append wrap
template ✓ (default)
command ✓ (default)
script ✓ (default)

Multiple composing presets chain recursively. For example, a security preset with prepend and a compliance preset with append will produce: security header + core content + compliance footer.

Catalog Management

Presets are discovered through catalogs. By default, Spec Kit uses the official and community catalogs:

Note

Community presets are independently created and maintained by their respective authors. Maintainers only verify that catalog entries are complete and correctly formatted — they do not review, audit, endorse, or support the preset code itself. Review preset source code before installation and use at your own discretion.

# List active catalogs
specify preset catalog list

# Add a custom catalog
specify preset catalog add https://example.com/catalog.json --name my-org --install-allowed

# Remove a catalog
specify preset catalog remove my-org

Creating a Preset

See scaffold/ for a scaffold you can copy to create your own preset.

  1. Copy scaffold/ to a new directory
  2. Edit preset.yml with your preset's metadata
  3. Add or replace templates in templates/
  4. Test locally with specify preset add --dev .
  5. Verify with specify preset resolve spec-template

Environment Variables

Variable Description Default
SPECKIT_PRESET_CATALOG_URL Override the full catalog stack with a single URL (replaces all defaults) Built-in default stack
GH_TOKEN / GITHUB_TOKEN GitHub token for authenticated requests to GitHub-hosted URLs (raw.githubusercontent.com, github.com, api.github.com, codeload.github.com). Required when your catalog JSON or preset ZIPs are hosted in a private GitHub repository. None

Example: Using a private GitHub-hosted catalog

# Authenticate with a token (gh CLI, PAT, or GITHUB_TOKEN in CI)
export GITHUB_TOKEN=$(gh auth token)

# Search a private catalog added via `specify preset catalog add`
specify preset search my-template

# Install from a private catalog
specify preset add my-template

The token is attached automatically to requests targeting GitHub domains. Non-GitHub catalog URLs are always fetched without credentials.

Configuration Files

File Scope Description
.specify/preset-catalogs.yml Project Custom catalog stack for this project
~/.specify/preset-catalogs.yml User Custom catalog stack for all projects

Future Considerations

The following enhancements are under consideration for future releases:

  • Structural merge strategies — Parsing Markdown sections for per-section granularity (e.g., "replace only ## Security").
  • Conflict detectionspecify preset lint / specify preset doctor for detecting composition conflicts.