Developing bundles

A bundle distributes an existing component stack through a manifest and usage documentation. Start with the role or team outcome, select components that provide it, and test their combined installation. A bundle does not replace extension, preset, workflow, or step authoring.

Create a bundle directory

Keep the manifest and README at the directory root:

team-setup/
  bundle.yml
  README.md
  LICENSE

This minimal example uses the packaged bug extension and workflow:

schema_version: "1.0"
bundle:
  id: team-setup
  name: Team setup
  version: 1.0.0
  role: developer
  description: A bug-fixing setup for the team
  author: Example team
  license: MIT
requires:
  speckit_version: ">=0.9.0"
provides:
  extensions:
    - id: bug
      version: 1.0.2
  workflows:
    - id: bugfix
      version: 1.0.0
tags: [developer, bugfix]

Choose pins from releases you have tested. Compatible newer stable packaged patches may satisfy these pins with warnings; explicit component catalog sources retain exact-pin enforcement.

The README should explain the intended role, installed components, integration requirements, catalogs users need to register, installation commands, and how to use the installed setup. For community publication, include a license file.

Select components and their sources

Extension, preset, and workflow references require exact versions. Steps may omit a version, in which case installation selects the current step catalog release. Pin steps too when reproducibility matters.

Presets must declare an integer priority of at least 1 and a composition strategy. Extensions can also declare priority; their default is 10. Use the API reference for the complete field contract.

An optional component source names the expected winning component catalog. It is not a URL, a directory, or a mechanism to change catalog precedence. Before selecting sources, inspect the effective catalogs:

specify extension catalog list
specify preset catalog list
specify workflow catalog list
specify workflow step catalog list

Document every non-default catalog needed by the bundle, with its appropriate catalog add command. Catalogs remain separate: adding a bundle catalog does not add component catalogs. Users must vet them before granting installation. Use unique component catalog names; an explicit source that matches multiple active catalogs is ambiguous and rejected.

Local bundle assets are packaged for distribution but are not automatically installed as component payloads. In particular, copying a custom step under steps/<id>/ does not make it resolvable. Publish it through an accessible step catalog and document that dependency.

Compose existing bundles

Use schema 1.1 and provides.bundles to reference exact releases of other bundles. For example, after checking the release is available in your catalog:

schema_version: "1.1"
bundle:
  id: team-setup
  name: Team setup
  version: 1.0.0
  role: developer
  description: A composed team setup
  author: Example team
  license: MIT
requires:
  speckit_version: ">=0.9.0"
provides:
  bundles:
    - id: bugfix
      version: 1.0.2
      source: default

References resolve through the effective bundle catalog, including when the parent is a local manifest. They are not local path references and are not embedded by build. The parent's own component declarations can override referenced declarations; incompatible sibling declarations need an explicit parent resolution. The API reference defines ordering, deduplication, and limits.

First-party bundle catalogs currently keep no historical releases. An exact reference can stop resolving when the catalog advances to its next release. For long-lived composition, use a catalog that preserves the required history.

Validate and build

From the repository or directory containing your bundle:

specify bundle validate --path ./team-setup
specify bundle build --path ./team-setup --output ./dist

Read warnings as well as errors. Online validation checks component resolution and expands references, but it does not enforce the running CLI's Spec Kit version gate. Offline validation cannot confirm network-only components or expand bundle references.

Build requires a regular README.md and bundle.yml and checks manifest structure. It does not confirm that references resolve or that installation succeeds. The resulting ZIP contains root-level files and local assets, not downloaded component payloads or referenced bundles.

Build output is reproducible for identical inputs: files are sorted by their POSIX archive paths, timestamps are fixed, and permissions normalize to executable or non-executable modes. Symlinks, .git, __pycache__, .DS_Store, previous versioned build artifacts for this bundle, and a nested output directory are excluded.

Test installation and changes

Use a clean project with the intended integration. Register any vetted dependency catalogs, then install the exact artifact users will receive:

specify init --here --integration copilot
specify bundle install /path/to/dist/team-setup-1.0.0.zip
specify bundle list --json

Inspect delivered commands and run the installed workflows or other intended capabilities. Repeat the installation to confirm that unchanged components and local edits are preserved. Test removal while independent or other-bundle components remain installed.

For local development, ordinary reinstall is not an update operation. Apply revised versions, changed owned-component settings, or removed components with:

specify bundle install /path/to/team-setup/bundle.yml --refresh

Refresh can overwrite owned components through their update paths and is not fully rolled back on failure. Use a disposable project for this test. Test both valid installs and relevant rejected cases, such as unavailable pins, integration mismatches, and conflicts with another bundle's requirements.

If distributing through a catalog, test ID installation from that install-allowed catalog too. A successful direct-artifact install does not verify catalog precedence, download metadata, or historical release selection.

See also