Workflow catalogs
Workflow catalogs control where search and add look for workflows. Catalogs are checked in priority order.
Workflow and step catalogs cache fetched JSON and freshness metadata for one
hour in .specify/workflows/.cache/ and .specify/workflows/steps/.cache/,
respectively. Cache I/O does not follow symlinked directory components or
cache files. Writes atomically replace cache files rather than truncate their
referents, so a pre-existing cache-file symlink can be replaced without changing
its target. If a cache cannot be safely written, a warning is logged and
discovery continues using the fetched catalog.
A project's
.specify/workflow-catalogs.ymlcan pointaddandsearchat a catalog you didn't choose. Before running a workflow from an unfamiliar project, runspecify workflow catalog list(andspecify workflow step catalog listfor the step catalogs its steps can pull in) — a project supplying that config is not evidence its workflows or steps were vetted. Maintainers do not audit workflow code; review bothrunandenvin its shell steps yourself, including strict steps (see Reviewing shell execution and Who maintains workflows?).
Discovery and trust
Workflow catalogs advertise workflow.yml files or complete packages. Step catalogs advertise executable Python packages through individual file URLs. They are independent stacks with built-in default (installation allowed) and community (discovery-only) sources. Users must vet sources before installation and use; maintainers do not audit or endorse component code.
An explicit direct-URL install chooses a source without catalog lookup. It does not make unreviewed content safe. A direct custom-step archive install asks for trust confirmation before making a network request.
Catalog configuration
| Level | Workflows | Step types |
|---|---|---|
| Environment override | SPECKIT_WORKFLOW_CATALOG_URL |
SPECKIT_STEP_CATALOG_URL |
| Project | .specify/workflow-catalogs.yml |
.specify/step-catalogs.yml |
| User | ~/.specify/workflow-catalogs.yml |
~/.specify/step-catalogs.yml |
| Default | Official and community workflow catalogs | Official and community step catalogs |
The first usable level supplies the whole stack, not an additive layer. An environment override selects one install-allowed source. Empty configurations fall through; malformed YAML and invalid configured URLs/priorities report errors.
catalogs:
- name: my-org
url: https://catalog.example.com/workflows.json
priority: 5
install_allowed: true
description: Our vetted workflows
Use the same entry shape for a step catalog in its separate file. url requires HTTPS (loopback HTTP is allowed for development). Lower numeric priorities win; the first source wins ties. install_allowed defaults to false in hand-authored configuration.
specify workflow catalog add and specify workflow step catalog add create project entries with installation allowed and a priority after existing entries. They do not expose preset-style --install-allowed or --priority flags. Add only vetted sources; edit the configuration when a discovery-only source is intended. Adding a project stack replaces implicit defaults unless you include them explicitly.
Workflow entry schema
Catalog JSON contains schema_version and a workflows mapping keyed by workflow ID. Entries carry id, name, description, author, version, url, and optional sha256, requires, repository, license, tags, and timestamps. A download can be raw YAML or a complete workflow archive. First-party entries marked bundled: true use packaged definitions rather than a network download.
Workflow releases
Catalog entries keep the current release's version, url, optional sha256,
and optional requires at the top level. An optional releases mapping
advertises historical versions without changing what unqualified add,
search, info, or update select:
{
"id": "example",
"version": "2.0.0",
"url": "https://example.com/example-2.0.0.zip",
"releases": {
"1.0.0": {
"url": "https://example.com/example-1.0.0.zip",
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"requires": {"speckit_version": ">=1.0.0"}
}
}
}
Each historical release needs its own URL and SHA-256 digest; requires is
optional and, when present, must match the downloaded workflow definition.
Advertised versions use the workflow definition's X.Y.Z version format;
--version also accepts equivalent spellings such as v1.0 when selecting an
advertised 1.0.0 release.
The requested version must exist in the highest-priority catalog that provides
the workflow. A missing version does not fall back to another source, and
discovery-only catalogs cannot be installed from. The downloaded workflow ID,
version, and declared digest are verified before installation. --version does
not apply to local paths, direct URLs, or --from installations.
Step releases
specify workflow step info <id> --versions lists the current and historical
releases in the winning catalog. specify workflow step add <id> --version <v>
selects the exact catalog release; without --version, add installs the
advertised current release. The requested version never falls back to a
lower-priority catalog, and discovery-only sources remain non-installable.
--version cannot be combined with direct --dev or --from installs.
Existing single-version catalog entries continue to work. Keep the current
release's version, step_yml_url (or url), init_url, and optional files
at the top level. An optional releases mapping adds historical versions:
{
"steps": {
"my-step": {
"version": "2.0",
"step_yml_url": "https://example.com/my-step/2.0/step.yml",
"releases": {
"1.0": {
"step_yml_url": "https://example.com/my-step/1.0/step.yml",
"init_url": "https://example.com/my-step/1.0/__init__.py",
"extra_files": {"helper.py": "https://example.com/my-step/1.0/helper.py"},
"sha256": {
"step.yml": "<64 hex digits>",
"__init__.py": "<64 hex digits>",
"helper.py": "<64 hex digits>"
}
}
}
}
}
}
Each historical release must supply its own step URL and SHA-256 digest for
every downloaded file. init_url can be omitted when derived from a
step_yml_url ending in step.yml. To select the current version explicitly,
its top-level entry must likewise supply the per-file sha256 mapping.
Release-specific files and requirements are not inherited from the current
release. Repeated or malformed versions are rejected; equivalent PEP 440
spellings such as v1.0 and 1.0 select the same advertised release. The
downloaded step.yml must declare the selected step ID and version. An
unqualified legacy catalog install does not require digests or a step version.
Only one version of each step ID can be installed at a time; use --force to
replace a previous installation after reviewing the selected package.
Resolution and failures
Workflow and step lookups merge all active catalogs, including for an exact ID. They do not stop after finding an ID. Sources are processed in reverse priority order so higher-precedence entries overwrite lower-precedence entries; each source may be fetched or read from cache even when another provides the ID. Vet every active source, not just the source expected to win.
The winning entry supplies its metadata, releases, and installation policy together. A lower-priority entry cannot supply a missing version or override a winning discovery-only decision. However, a source that fails to fetch contributes no entries, so a lower-priority source can supply the ID when the preferred source is unavailable. Fetch failures remaining after cache fallback are skipped when another source succeeds; if every configured catalog fails, lookup reports an error.
A fetched catalog must be a JSON object. Within that object, workflows and
steps accept mapping or list forms; unsupported collection shapes and
non-mapping entries are skipped. These ignored contents do not count as fetch
failures, so a successfully fetched object can contribute no entries and lookup
can return no results rather than a structure-validation error. Step catalogs
additionally reject duplicate JSON fields and duplicate step IDs in list form.
Release metadata is validated separately and can still produce errors.
Cache and private sources
Workflow and step catalog caches live under .specify/workflows/.cache/ and .specify/workflows/steps/.cache/, with a one-hour lifetime. Payload and freshness files are keyed by URL hash. Unusable cache entries trigger a fetch; unsafe cache writes log warnings without discarding the fetched discovery result.
Private catalog and package downloads use shared opt-in authentication from ~/.specify/auth.json. A token environment variable alone does not enable it. Configure only authorized destination hosts; never embed credentials in catalog JSON or URLs.