Workflow step catalogs
Step catalogs control where specify workflow step search and add look for
custom step packages. They are independent of workflow catalogs.
Discovery and trust
Step catalogs advertise executable Python packages through individual file
URLs. Built-in sources include default (installation allowed) and community
(discovery-only). Users must vet sources before installation and use;
maintainers do not audit or endorse component code.
A project's .specify/step-catalogs.yml can select sources you did not choose.
Inspect them with specify workflow step catalog list before installing or
loading custom steps. A direct archive URL bypasses catalog lookup, not source
review; direct URL installation asks for trust confirmation before making a
network request.
Catalog configuration
| Level | Step types |
|---|---|
| Environment override | SPECKIT_STEP_CATALOG_URL |
| Project | .specify/step-catalogs.yml |
| User | ~/.specify/step-catalogs.yml |
| Default | 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/steps.json
priority: 5
install_allowed: true
description: Our vetted workflow steps
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 step catalog add creates project entries with installation
allowed and a priority after existing entries. It does 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.
Step entry schema
Catalog JSON contains schema_version and a steps collection. Entries identify
the type and version, its step_yml_url (or url), init_url, optional
extra_files, and per-file sha256 digests. Catalog installation downloads
individual package files rather than the archive used by --from.
The community submission guide defines the additional metadata and pinned-file requirements for community entries.
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
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. Its steps collection accepts 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
Step catalogs cache fetched JSON and freshness metadata for one hour in
.specify/workflows/steps/.cache/. Payload and freshness files are keyed by URL
hash. Unusable cache entries trigger a fetch. 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. 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.