mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 12:28:06 +08:00
* docs: dogfood Spec Kit — bundler SDD artifacts + constitution Scaffold Spec Kit (--integration copilot) and run the full SDD workflow against the `specify bundle` subcommand feature: - spec.md (4 user stories, 31 FRs, 8 success criteria) + clarifications - plan.md, research.md, data-model.md, contracts/, quickstart.md - tasks.md (43 dependency-ordered tasks, organized by user story) - Spec Kit Constitution v1.0.0 (code quality, testing, UX, performance, dependency/security principles) derived from deep codebase analysis - plan Constitution Check + tasks grounded against the ratified principles Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(bundler): add `specify bundle` subcommand for role-based setups Implements the Spec Kit Bundler as a `specify bundle ...` subcommand group that calls existing primitive machinery in-process with zero new dependencies, per the v1.0.0 constitution (Principles I-V). Adds the `specify_cli.bundler` package (models, services, lib helpers) and the `commands/bundle` Typer group wiring search, info, list, install, update, remove, validate, build, init, and catalog list/add/remove (with --json and --offline). Includes manifest/catalog schemas, version + integration-clash gating, discovery-only refusal, idempotent install with atomic rollback, non-collateral removal, and offline-first catalog resolution. Ships an 82-test suite (contract/unit/integration), four sample role bundles (product-manager, business-analyst, security-researcher, developer), README "Bundles" docs, and an AGENTS.md pitfall on the test-venv gotcha. Marks tasks T001-T043 complete and records follow-ups T044 (live in-process primitive dispatch) and T045 (install from a local artifact path). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(contributing): document running the full test suite via project .venv Add a "Running the full test suite" subsection under Automated checks covering `uv pip install -e ".[test]"` + `.venv/bin/python -m pytest`, with the shared/global editable-install contamination caveat that mirrors the AGENTS.md pitfall. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(bundler): wire real in-process primitive install + local-artifact install Closes the two follow-ups left after the initial bundler landing. T044 — DefaultPrimitiveInstaller now performs real installs through existing machinery instead of raising "use the primitive command" errors: - presets/extensions install via their reusable managers (install_from_directory / install_from_zip); bundled assets install fully offline, catalog assets are fetched only when the network is allowed. - workflows/steps delegate to the existing `workflow add` / `workflow step add` command callables in-process (project root as cwd), avoiding any duplicated download/validation logic (Principle I). - `--offline` is threaded through DefaultPrimitiveInstaller(allow_network=…) so network-only kinds refuse with an actionable message rather than silently reaching out. T045 — `specify bundle install` now accepts a local path (a built .zip artifact, a bundle directory, or a bundle.yml) and installs directly without consulting the catalog stack; bundle-ids still resolve via the stack. Adds 13 tests (routing, offline gating, local-source resolution, and an end-to-end offline build → install → list → remove of the bundled agent-context extension). Bundler suite: 95 passing; ruff clean. Marks T044 and T045 complete in tasks.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(bundler): append Phase 8 convergence tasks from converge assessment Ran the converge command: assessed the codebase against spec.md, plan.md, tasks.md, and the v1.0.0 constitution. Appended 7 traceable gap-closure tasks (T046–T052) as a new "Phase 8: Convergence" section. Append-only — no existing tasks were modified and no application code was changed. Findings: 1 CRITICAL (Constitution III — bundle group undocumented under docs/reference/), 3 HIGH (FR-005/SC-007 validate references; FR-009/SC-002 info expansion; FR-012 install-time init), 3 MEDIUM (FR-013 integration precedence; FR-020 surface overlaps; FR-028 update refresh). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Implement Phase 8 convergence tasks (T046–T052) Close the gaps the converge command found between the bundler spec/plan/ constitution and the code: - T046: add docs/reference/bundles.md documenting the full `specify bundle` command group; link it from docs/reference/overview.md (Constitution III). - T047: wire a reference checker into `bundle validate` (services/references.py); online runs fail and name unresolved component references, offline runs warn. - T048: expand `bundle info` to enumerate the full component set (versions, preset priority/strategy) plus the bundle integration — info == install. - T049/T050: `bundle install`/`bundle init` now scaffold an uninitialized project via the existing `specify init` machinery, choosing the integration by precedence (override → bundle-declared → Copilot + OS default script type). - T051: surface foreseeable component overlaps during info and install. - T052: `bundle update` refreshes already-installed components via a new refresh path in install_bundle, preserving primitive-level overrides. Adds unit/contract/integration coverage (107 tests pass). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * converge: append Phase 9 (T053) — surface bundle trust indicator Re-run of converge after Phase 8. The seven Phase 8 tasks are verified closed. One residual partial gap remains: the `verified`/trust indicator (FR-010, FR-027) is exposed only in `bundle info --json`, absent from `bundle search` (the primary discovery surface) and `bundle info` text. Appended as a single new task for implement to complete. Append-only; no code changed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Implement T053 — surface bundle trust indicator in discovery `bundle search` (text + JSON) and `bundle info` (text + JSON) now expose each catalog entry's verification/trust level (verified vs community), so users can judge a bundle's trust before installing, per FR-010 / FR-027. Previously `verified` was only present in `bundle info --json`. Adds contract coverage; 108 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: dogfood Spec Kit — bundler SDD artifacts + constitution Scaffold Spec Kit (--integration copilot) and run the full SDD workflow against the `specify bundle` subcommand feature: - spec.md (4 user stories, 31 FRs, 8 success criteria) + clarifications - plan.md, research.md, data-model.md, contracts/, quickstart.md - tasks.md (43 dependency-ordered tasks, organized by user story) - Spec Kit Constitution v1.0.0 (code quality, testing, UX, performance, dependency/security principles) derived from deep codebase analysis - plan Constitution Check + tasks grounded against the ratified principles Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(bundler): add `specify bundle` subcommand for role-based setups Implements the Spec Kit Bundler as a `specify bundle ...` subcommand group that calls existing primitive machinery in-process with zero new dependencies, per the v1.0.0 constitution (Principles I-V). Adds the `specify_cli.bundler` package (models, services, lib helpers) and the `commands/bundle` Typer group wiring search, info, list, install, update, remove, validate, build, init, and catalog list/add/remove (with --json and --offline). Includes manifest/catalog schemas, version + integration-clash gating, discovery-only refusal, idempotent install with atomic rollback, non-collateral removal, and offline-first catalog resolution. Ships an 82-test suite (contract/unit/integration), four sample role bundles (product-manager, business-analyst, security-researcher, developer), README "Bundles" docs, and an AGENTS.md pitfall on the test-venv gotcha. Marks tasks T001-T043 complete and records follow-ups T044 (live in-process primitive dispatch) and T045 (install from a local artifact path). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(contributing): document running the full test suite via project .venv Add a "Running the full test suite" subsection under Automated checks covering `uv pip install -e ".[test]"` + `.venv/bin/python -m pytest`, with the shared/global editable-install contamination caveat that mirrors the AGENTS.md pitfall. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(bundler): wire real in-process primitive install + local-artifact install Closes the two follow-ups left after the initial bundler landing. T044 — DefaultPrimitiveInstaller now performs real installs through existing machinery instead of raising "use the primitive command" errors: - presets/extensions install via their reusable managers (install_from_directory / install_from_zip); bundled assets install fully offline, catalog assets are fetched only when the network is allowed. - workflows/steps delegate to the existing `workflow add` / `workflow step add` command callables in-process (project root as cwd), avoiding any duplicated download/validation logic (Principle I). - `--offline` is threaded through DefaultPrimitiveInstaller(allow_network=…) so network-only kinds refuse with an actionable message rather than silently reaching out. T045 — `specify bundle install` now accepts a local path (a built .zip artifact, a bundle directory, or a bundle.yml) and installs directly without consulting the catalog stack; bundle-ids still resolve via the stack. Adds 13 tests (routing, offline gating, local-source resolution, and an end-to-end offline build → install → list → remove of the bundled agent-context extension). Bundler suite: 95 passing; ruff clean. Marks T044 and T045 complete in tasks.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(bundler): append Phase 8 convergence tasks from converge assessment Ran the converge command: assessed the codebase against spec.md, plan.md, tasks.md, and the v1.0.0 constitution. Appended 7 traceable gap-closure tasks (T046–T052) as a new "Phase 8: Convergence" section. Append-only — no existing tasks were modified and no application code was changed. Findings: 1 CRITICAL (Constitution III — bundle group undocumented under docs/reference/), 3 HIGH (FR-005/SC-007 validate references; FR-009/SC-002 info expansion; FR-012 install-time init), 3 MEDIUM (FR-013 integration precedence; FR-020 surface overlaps; FR-028 update refresh). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Implement Phase 8 convergence tasks (T046–T052) Close the gaps the converge command found between the bundler spec/plan/ constitution and the code: - T046: add docs/reference/bundles.md documenting the full `specify bundle` command group; link it from docs/reference/overview.md (Constitution III). - T047: wire a reference checker into `bundle validate` (services/references.py); online runs fail and name unresolved component references, offline runs warn. - T048: expand `bundle info` to enumerate the full component set (versions, preset priority/strategy) plus the bundle integration — info == install. - T049/T050: `bundle install`/`bundle init` now scaffold an uninitialized project via the existing `specify init` machinery, choosing the integration by precedence (override → bundle-declared → Copilot + OS default script type). - T051: surface foreseeable component overlaps during info and install. - T052: `bundle update` refreshes already-installed components via a new refresh path in install_bundle, preserving primitive-level overrides. Adds unit/contract/integration coverage (107 tests pass). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * converge: append Phase 9 (T053) — surface bundle trust indicator Re-run of converge after Phase 8. The seven Phase 8 tasks are verified closed. One residual partial gap remains: the `verified`/trust indicator (FR-010, FR-027) is exposed only in `bundle info --json`, absent from `bundle search` (the primary discovery surface) and `bundle info` text. Appended as a single new task for implement to complete. Append-only; no code changed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Implement T053 — surface bundle trust indicator in discovery `bundle search` (text + JSON) and `bundle info` (text + JSON) now expose each catalog entry's verification/trust level (verified vs community), so users can judge a bundle's trust before installing, per FR-010 / FR-027. Previously `verified` was only present in `bundle info --json`. Adds contract coverage; 108 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): address PR review — annotations, Windows paths, HTTPS, errors, reproducible builds Resolves automated review feedback on github/spec-kit#3070: - validator: drop redundant string-quoting on ReferenceChecker's `str | None` return so the annotation evaluates as a real union under `from __future__ import annotations`. - adapters: normalize Windows drive-letter paths (e.g. C:\...) to the local-file branch so offline file catalogs resolve on Windows. - adapters: enforce HTTPS (HTTP only for localhost) and require a host on remote catalog URLs before any network call, mirroring specify_cli.catalogs URL validation (MITM/downgrade protection). - adapters: pass `origin` to loads_json for local files and HTTP payloads so JSON parse errors name the real source instead of <string>. - manifest: parse component `priority` defensively, raising an actionable BundlerError on non-integer values instead of a raw ValueError. - packager: write zip members with a fixed timestamp + permissions so identical inputs yield byte-for-byte identical artifacts (genuinely reproducible builds), and strengthen the determinism test accordingly. Adds regression tests for priority validation, plain-HTTP/host rejection, and byte-level artifact reproducibility (111 bundler tests pass; ruff clean). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): address PR review round 2 — nested output dir + file:// URLs - packager: when --output points inside the bundle directory, exclude the whole output subtree from collection so previously-built artifacts are never re-packaged (prevents broken reproducibility and unbounded growth). - adapters: resolve file:// catalog URLs via url2pathname and preserve netloc, so Windows file URLs (file:///C:/...) and UNC shares (file://server/share) resolve correctly instead of dropping the host or producing /C:/x. Adds regression tests for nested-output exclusion and file:// resolution (113 bundler tests pass; ruff clean). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): address PR review round 3 — discovery UX + hardening - bundle search/info: fall back to the built-in/user catalog stack instead of requiring a Spec Kit project, so discovery works in a fresh directory (and the README/quickstart examples now match actual behavior). install still auto-initializes a project as before. - packager: traverse with os.walk(followlinks=False) and prune symlinked directories before descending, so a symlink-to-dir can no longer pull in out-of-tree files (which previously turned "skip symlinks" into a hard ensure_within() failure and did extra filesystem work). - records: parse contributed-component priority defensively, raising an actionable BundlerError on a corrupt records file instead of leaking a raw ValueError/traceback. - installer: give install_bundle's manifest parameter an explicit BundleManifest | None type for a clearer, safer service API. Adds regression tests for project-less search/info, symlinked-dir pruning, and corrupt-priority records (117 bundler tests pass; ruff clean). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): address PR review round 4 + markdownlint exclusions Review fixes: - bundle info: expand the manifest regardless of install policy so discovery-only bundles remain inspectable (only install is refused). - _download_manifest: handle local .zip download_url by extracting bundle.yml (via _local_manifest_source), and add a real remote HTTPS fetch path using the shared authenticated, redirect-validated open_url client (HTTPS enforced on the initial URL and every redirect; offline still refuses). - _run_init: thread the --offline flag through to the init callback so `bundle install/init --offline` never performs network init. - conflict.ConflictReport: use field(default_factory=list) and drop the None + __post_init__ workaround. - CatalogSource.from_dict: parse priority defensively, raising an actionable BundlerError naming the source + offending value instead of a raw ValueError. markdownlint: - Exclude .specify/, .github/, and specs/ (and their subdirectories) from markdownlint so the in-flight dogfooding scaffolding doesn't trip the linter. Adds regression tests for discovery-only info, local-zip download_url, and non-integer catalog priority (120 bundler tests pass; ruff clean; the PR's own markdown lints clean). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): address PR review round 5 + ignore generated files in whitespace check Review fixes: - packager: exclude any prior build artifact for this bundle (matching <id>-*.zip), not just the current output path, so older artifacts next to bundle.yml are never re-packaged. - docs(bundles): correct the note — `search` and `info` work without a project (they fall back to the built-in/user catalog stack); only list/update/remove/ catalog require an initialized project. CI / generated files: - .gitattributes: mark the generated dogfooding scaffolding (.specify/**, the speckit .github agent/prompt files, copilot-instructions.md, specs/**) with -whitespace so `git diff --check` (the Lint workflow's whitespace gate) stops flagging emitted trailing whitespace. These files are produced by `specify init` and are scrubbed before merge. Adds a regression test for prior-artifact exclusion (121 bundler tests pass; ruff clean). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): collision-resistant catalog ids, canonical local paths, explicit uninstalled result Addresses review round 6 (PR #3070): - catalog_config._derive_id now combines host label with the URL path stem so multiple catalogs from the same host get distinct, stable default ids. - add_source canonicalizes local file paths to absolute before persisting, so project config no longer depends on the caller's cwd. - InstallResult gains a dedicated `uninstalled` list; remove_bundle no longer overloads `installed` for removals, and the CLI prints from `uninstalled`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): confine config writes, guard indeterminate integration, fix validate docs Addresses review round 7 (PR #3070): - save_records and catalog_config._write now pass within=project_root to dump_json/dump_yaml, refusing symlinked .specify paths that escape the project (defense-in-depth, matching the rest of the codebase). - resolve_install_plan now fails when a bundle pins an integration but the project's active integration cannot be determined and no explicit --integration override was given, instead of silently adopting the bundle's required integration (FR-019 guard). CLI passes integration_explicit. - docs/reference/bundles.md: corrected the validate semantics to describe the actual best-effort online behavior (unreachable catalogs warn, not fail). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): Windows path handling + review round 8 hardening Fix Windows CI failures: - is_safe_relpath now rejects POSIX-absolute (/abs) and Windows drive-absolute (C:\x, UNC) paths on every OS, instead of passing them through on Windows where os.path.isabs('/abs') is False and Path('/abs').parts yields '\\'. - _download_manifest treats a Windows drive-letter download_url (C:\bundle.yml, which urlparse reads as scheme 'c') as a local file, fixing the empty component set in `bundle info` on Windows. Address review round 8 (PR #3070): - Bundled workflows now install under --offline (locate via _locate_bundled_workflow) instead of being refused unconditionally. - bundle update preserves the original installed_at timestamp on refresh (import find_record; reuse the existing record's timestamp). - _derive_id lowercases the host label so 'Example.com' and 'example.com' produce the same deterministic id. - CatalogEntry.from_dict validates 'tags' is a list and 'verified' is a real boolean, raising BundlerError on invalid untrusted shapes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): normalize SemVer prerelease spellings before version parsing Addresses review round 9 (PR #3070): parse_version and is_semver now apply the same prerelease normalization (mirroring specify_cli._version._normalize_tag) so SemVer spellings like 1.2.3-rc1 / 1.2.3-alpha1 validate and compare consistently across is_semver, parse_version, and satisfies. Leading 'v' is also stripped. Keeps the manifest validator and constraint checks in agreement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): no collateral removal + enforce manifest-pinned versions Addresses review round 10 (PR #3070): - install_bundle records only the components this bundle actually contributed: freshly-installed components, plus pre-existing ones already owned by this bundle (refresh) or a sibling bundle (shared/refcounted). A component that is installed on disk but tracked by no bundle was installed independently and is no longer attributed, so `bundle remove` won't uninstall it (FR-022). - preset/extension/workflow install paths now verify the active catalog's advertised version matches the manifest-pinned component.version before downloading/installing, raising BundlerError on mismatch so bundles stay reproducible. When a catalog advertises no version the pin can't be enforced and installation proceeds. Added regression tests: independent pre-existing component survives removal; version-mismatch refusal (helper + workflow path). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(scripts): add SPECIFY_INIT_DIR to target a member project from the repo root (#2892) * feat(scripts): add SPECIFY_INIT_DIR to target a member project from the repo root Resolve an explicit SPECIFY_INIT_DIR project override once in the core get_repo_root / Get-RepoRoot, so a non-interactive / CI caller can target a member project (the directory containing .specify/) from a monorepo root without cd. Strict by design: the path must exist and contain .specify/, otherwise it hard-errors with no silent fallback. - Single resolver in core; the git feature-branch script inherits it by sourcing core, with no per-extension copies. - PS resolver verifies the resolved path is a directory (Resolve-Path also succeeds for files) so a file value errors as "not an existing directory". - get_feature_paths splits decl/assignment so a SPECIFY_INIT_DIR failure propagates instead of being masked by `local`. - create-new-feature-branch: when core is absent (only git-common loaded) and SPECIFY_INIT_DIR is set, hard-error rather than silently using the git root. - Document SPECIFY_INIT_DIR and SPECIFY_FEATURE_DIRECTORY in the core reference. - Tests for valid/relative/trailing-slash/file/missing/no-.specify targets, feature-axis composition, the no-core guard, and a PowerShell mirror. * fix: guard SPECIFY_INIT_DIR with stale core scripts * docs: clarify SPECIFY_FEATURE_DIRECTORY precedence wording * fix: normalize trailing slash in PowerShell SPECIFY_INIT_DIR resolver Resolve-Path preserves a trailing separator from its input, so a SPECIFY_INIT_DIR ending in a slash returned a root that didn't match the bash resolver (whose `cd && pwd` strips it). That broke test_ps_trailing_slash_tolerated on the CI runners, which do have pwsh. Trim it with TrimEndingDirectorySeparator (no-op on a bare root or a path with no trailing separator). Also fix the misleading test comment: the PowerShell mirror runs on the CI ubuntu/windows runners (they ship pwsh), it is not skipped there. * test: normalize bash path expectations on Windows * docs: clarify SPECIFY_INIT_DIR root helpers * chore: sync dogfooded .specify core scripts with SPECIFY_INIT_DIR Mirror the SPECIFY_INIT_DIR resolver (resolve_specify_init_dir in common.sh) into the committed dogfooding .specify/scripts/bash copies so the git extension's create-new-feature-branch.sh finds an up-to-date common.sh instead of failing with "requires updated Spec Kit core scripts". Fixes the test_init_dir.py CI failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): harden remote catalog fetch and config parsing - adapters: route catalog HTTP fetches through the shared authenticated client (authentication.http.open_url) so auth.json tokens apply and the Authorization header is stripped on cross-host/downgrade redirects. Reject any redirect that leaves HTTPS via a redirect_validator and re-validate the final URL after redirects, closing the urlopen auto-redirect MITM/downgrade gap. - catalog_config._read: raise an actionable BundlerError when the config top level is not a mapping, 'catalogs' is not a list, or an entry is not a mapping, instead of letting list(<str>) produce a downstream AttributeError. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): tighten record read confinement, policy gate, and precedence Addresses review 4534504799: - records.load_records: confine the read via ensure_within(project_root, ...) so a symlinked/traversal-escaping .specify cannot read arbitrary files outside the project (matches the write path's within= guard). - catalog_config._slug: lowercase so derived catalog ids are deterministic across platforms and case-variant duplicates can't slip past the case-sensitive dup check. - installer.install_bundle: reword the docstring's misleading "atomic on failure" claim to describe the real scoped guarantee (record written only on full success; rollback limited to newly-installed components). - bundle update: enforce the source install_policy like install, refusing to update from a discovery-only source (FR-025). - catalog source precedence: the CLI now passes ~/.specify as the user config dir so project > user > built-in precedence is actually reachable (previously the user scope was silently ignored). - .gitattributes: scope the specs whitespace exemption to the generated dogfooding feature dir (specs/001-spec-kit-bundler/**) instead of all of specs/**. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): no collateral refresh, catalog id integrity, loud info Addresses review 4534571362: - installer: in refresh mode (bundle update) only re-apply already- installed components that this bundle (or a sibling) owns. Components installed independently and tracked by no bundle are now skipped, never refreshed, so update cannot make collateral changes (FR-022). - catalog.load_catalog_payload: validate each entry's own id is present and matches its enclosing bundles key, rejecting catalogs that would otherwise list a spoofed or unresolvable id. - bundle info: stop swallowing manifest download failures. If the manifest can't be resolved (e.g. --offline against an https download_url or a download failure), surface the error and exit non-zero instead of silently degrading to catalog `provides` counts, preserving the "info == what install applies" guarantee. Added regressions: refresh leaves independently-installed components untouched, catalog id key/field mismatch + missing id rejection, and info exits non-zero when the manifest is unresolvable offline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): confine catalog-config and integration-marker reads Addresses review 4534716790: two more state reads bypassed the symlink/path-escape confinement that records and the write paths already enforce. - catalog_config._read: validate the config path with ensure_within(project_root, ...) before exists()/read, so a symlinked .specify resolving outside project_root is rejected instead of read. - lib.project.active_integration: confine the .specify/integration.json read the same way; an out-of-tree escape is treated as "not determinable" (returns None) rather than followed. Added regressions covering both via a symlinked .specify pointing outside the project root. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): validate manifest tags, disambiguate derived ids by full host Addresses review 4534768419: - manifest.from_dict: reject a non-list `tags` (e.g. a bare string) instead of splitting it character-by-character, matching the catalog parser and the schema contract (tags = list of strings). - catalog_config._derive_id: derive ids from the full host (TLD included) so example.com and example.net no longer collide on the same id. Updated the affected id assertions. - CHANGELOG: call out the new `specify bundle` command group in the unreleased section (the PR's headline user-facing feature). - .gitattributes: clarify the specs whitespace exemption — the dogfooding feature dir is scrubbed before merge (not retained), so it doesn't weaken checks for kept docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(gitattributes): retain whitespace exemption for constitution.md The project constitution (.specify/memory/constitution.md) is the one dogfooding artifact carried forward past the pre-merge scrub. Give it its own standalone whitespace exemption so it survives removal of the broader .specify/** generated-scaffolding exemption. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): accurate uninstall count, confine catalog read, safe bundle id Addresses review 4534812056: - installer.remove_bundle: only count a component as uninstalled when installer.remove() actually ran; components already absent on disk are reported as skipped, keeping the uninstalled count accurate. - catalog.load_source_stack: confine the project-scoped .specify config read with ensure_within, so a symlinked .specify/ resolving outside the project root is refused (consistent with the bundler's other guarded reads). - manifest: enforce a filesystem-safe slug for bundle.id in structural validation; packager.build_bundle adds an ensure_within defense-in-depth check so a crafted id can never push the artifact outside the output dir. Also reverts the CHANGELOG entry (the changelog is updated separately). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): validate requires/provides shapes in manifest and catalog Addresses review 4534855443: - manifest: validate requires.tools and requires.mcp as list-of-strings via a shared _parse_str_list helper (also reused for tags), so a bare string like `tools: docker` is rejected with an actionable BundlerError instead of being split character-by-character. - catalog.CatalogEntry.from_dict: validate that `requires` and `provides` are mappings before accessing them, so an untrusted catalog payload with `requires: "..."` raises a named BundlerError rather than escaping as a raw AttributeError traceback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): require README.md when building a bundle artifact Addresses review 4534938014: build_bundle now fails early with an actionable error when README.md is missing, matching the documented artifact contract (manifest + README) instead of silently producing a bundle with no human-facing description. Also reverts CHANGELOG.md to the upstream/main copy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): validate record shapes; drop stale install --refresh claim Addresses review 4534969692: - records.InstalledBundleRecord.from_dict: hard-error when contributed_components is not a list, instead of iterating a corrupt bare string character-by-character. - records.load_records: validate the top-level 'bundles' field is a list and fail with a clear BundlerError when a corrupt file makes it a mapping/string. - PR description: remove the inaccurate "supports --refresh" note from `bundle install` (refresh is the `bundle update` path); docs already omit it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): refuse symlinked .specify, reject bad url schemes, IPv6 ids Addresses review 4534997724: - lib.project.find_project_root: a symlinked .specify is no longer accepted as a project root (is_dir() follows symlinks), matching the confinement the rest of the CLI applies and avoiding confusing downstream failures. - catalog_config.add_source: reject unsupported url schemes (ssh://, ftp://, ...) up front instead of silently treating them as local paths; local paths containing ':' but not '://' are still allowed. - catalog_config._derive_id: derive the host via urlparse().hostname so IPv6 literals, credentials, and ports no longer corrupt the derived id. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): strict semver, narrow artifact skip, preserve priority 0 Addresses review 4535084048: - versioning.is_semver: enforce a full MAJOR.MINOR.PATCH SemVer (with optional pre-release/build) via a dedicated regex, instead of accepting any packaging.version.Version-parseable string (e.g. "1", "1.0"). This makes BundleManifest.structural_errors() reject non-semver versions. - packager: narrow the prior-artifact skip pattern to semver-named zips (<id>-<x.y.z>.zip) so legitimate assets like <id>-assets.zip are still packaged. - primitives (preset + extension install): use an explicit `is None` check so an intentional priority of 0 is preserved instead of being replaced by the default. Adds regressions: non-semver rejection ("1"/"1.0"/"1.2.3.4"), asset-not- excluded vs semver-artifact-excluded, and priority-0 pass-through. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): artifact regex for prerelease+build; clarify integration/priority docs Addresses review 4535132279: - packager: the prior-artifact skip regex now matches semver names carrying both a prerelease and build-metadata segment (e.g. 1.0.0-rc1+build5), so such an existing artifact is excluded rather than re-packaged — keeping builds bounded/deterministic, consistent with is_semver(). - docs/reference/bundles.md: correct the install integration wording. --integration selects the integration when initializing a new project and confirms the target when a pinned bundle's active integration can't be determined; it does NOT override a bundle that targets a specific integration (a mismatch aborts with no changes). - examples/security-researcher README: reword the preset priority note in terms of the numeric comparison (ascending priority order) to avoid inverting the meaning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): --integration can't bypass clash guard; honest rollback docs Addresses review 4535159341: - bundle install: for an already-initialized project, the project's recorded active integration is now authoritative. --integration no longer overrides it (which let a copilot project install a claude-pinned bundle via `--integration claude`, bypassing the FR-019 clash guard). The override still selects the integration at init time and confirms the target only when the active integration cannot be determined. - docs/reference/bundles.md: reword the install guarantee to match the implementation — no provenance record is written unless the install fully succeeds, and rollback of this run's components is best-effort (removal errors are swallowed, so partial on-disk state may remain). Dropped the inaccurate "atomic / rolls back everything" claim. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): validate component kind/id when loading records Addresses review 4535194606: _component_from_dict now rejects a contributed component whose 'kind' is not a supported component kind or whose 'id' is empty, raising a BundlerError that explicitly flags the records file as corrupt. Previously such a record loaded successfully and only failed later (e.g. in primitive_manager() during bundle remove/update) with a less actionable error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): address review 4535234003 (7 findings) - versioning: tolerate an uppercase `V` prefix in `_normalize_semver` and `is_semver`, mirroring specify_cli._version tag normalization (V -> v) so `V1.2.3` parses and validates consistently. - validator: import BundlerError and narrow the speckit_version constraint except clause to `BundlerError` only, so programming errors are no longer masked behind an "invalid constraint" message. - bundle update: accept `--integration` and thread it through resolve_install_plan the same way `bundle install` does (override used only when the active integration can't be auto-detected), so integration-pinned bundles can be updated where `.specify/integration.json` is missing/unreadable. - bundle validate: fold reference warnings into `report.warnings` so the ValidationReport is the single warning channel at the CLI layer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(bundler): make update --integration help assertion ANSI-safe Rich can split the "--integration" option label with ANSI escape codes between the two leading dashes, so the literal substring check failed under CI's terminal settings. Match the un-split option word instead, mirroring how test_bundle_help_lists_all_commands checks bare command names. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): preserve exec bits in artifacts; document install-time pins Addresses review 4535280786: - packager.build_bundle: no longer forces every ZIP member to 0644, which stripped the executable bit from bundled scripts (e.g. extension hook scripts) and could break them after extraction. Permissions are now normalized reproducibly to 0755 when the source file has any execute bit set, otherwise 0644 — identical inputs still yield byte-for-byte identical artifacts. - installer.install_bundle + docs/reference/bundles.md: document that version pins are enforced install-time only. Because primitive is_installed checks are id-based (not version-aware), an already-present component is skipped during install without comparing its on-disk version to the manifest pin; pins are guaranteed applied only on a real install or `bundle update` refresh. Added a regression asserting executable sources map to 0755 and plain files to 0644 in the built artifact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(bundler): skip exec-bit packager test on Windows Windows filesystems do not carry Unix execute bits, so chmod(0o755) is a no-op and the source file reports no execute bit — the packager then correctly stores the member as 0644. The assertion that an executable source maps to 0755 is only meaningful on POSIX, so skip it on nt rather than asserting platform-specific behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): normalize prerelease spellings inside version constraints Addresses review 4535327154: parse_version() normalized SemVer prerelease spellings (e.g. 1.2.3-rc1 -> 1.2.3rc1) but parse_constraint() passed the constraint to packaging.SpecifierSet unmodified, so ">=1.2.3-rc1" raised InvalidSpecifier even though the same spelling is accepted for installed versions. parse_constraint() now normalizes the version portion of each comma-separated clause via the shared _normalize_semver helper, so prerelease handling is consistent across versions and constraints. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bundler): validate schema versions and required record identity fields Addresses review 4535351596: - records.load_records: validate the on-disk 'schema_version' (required; forward-compatible across same-major minor bumps) and fail fast with an actionable error on a missing/unknown version, rather than silently parsing a possibly-incompatible format and risking incorrect bundle attribution/removal. - records.InstalledBundleRecord.from_dict: treat missing 'bundle_id' or 'version' as corruption and raise BundlerError, instead of coercing them to empty strings that let later list/remove/update operations behave unpredictably. - catalog_config._read: validate 'schema_version' when present (same-major compatibility) and fail fast on an unsupported version so an incompatible future config shape can't be mis-parsed into a wrong effective catalog stack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(bundler): scrub generated dogfooding scaffold before merge The bundler feature was developed by dogfooding Spec Kit on itself. Now that the work is complete, remove all generated scaffolding so it does not land in the repository on merge: - specs/001-spec-kit-bundler/** (spec, plan, research, data-model, contracts, quickstart, tasks, checklists) - .specify/** (extensions, integrations, scripts, templates, workflows, feature/init/integration metadata) - .github/agents/speckit.*.agent.md, .github/prompts/speckit.*.prompt.md, and .github/copilot-instructions.md (Copilot integration scaffold) Retained: .specify/memory/constitution.md — the single dogfooding artifact carried forward — with its whitespace exemption in .gitattributes. .gitattributes and .markdownlint-cli2.jsonc are reverted to the upstream baseline (plus the constitution whitespace exemption), dropping the now-moot exemptions for the removed scaffold. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Pascal THUET <pascal.thuet@arte.tv>
657 lines
36 KiB
Markdown
657 lines
36 KiB
Markdown
<div align="center">
|
||
<img src="./media/logo_large.webp" alt="Spec Kit Logo" width="200" height="200"/>
|
||
<h1>🌱 Spec Kit</h1>
|
||
<h3><em>Build high-quality software faster.</em></h3>
|
||
</div>
|
||
|
||
<p align="center">
|
||
<strong>An open source toolkit that allows you to focus on product scenarios and predictable outcomes instead of vibe coding every piece from scratch.</strong>
|
||
</p>
|
||
|
||
<p align="center">
|
||
<a href="https://github.com/github/spec-kit/releases/latest"><img src="https://img.shields.io/github/v/release/github/spec-kit" alt="Latest Release"/></a>
|
||
<a href="https://github.com/github/spec-kit/stargazers"><img src="https://img.shields.io/github/stars/github/spec-kit?style=social" alt="GitHub stars"/></a>
|
||
<a href="https://github.com/github/spec-kit/blob/main/LICENSE"><img src="https://img.shields.io/github/license/github/spec-kit" alt="License"/></a>
|
||
<a href="https://github.github.io/spec-kit/"><img src="https://img.shields.io/badge/docs-GitHub_Pages-blue" alt="Documentation"/></a>
|
||
</p>
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [🤔 What is Spec-Driven Development?](#-what-is-spec-driven-development)
|
||
- [⚡ Get Started](#-get-started)
|
||
- [📽️ Video Overview](#️-video-overview)
|
||
- [🌍 Community](#-community)
|
||
- [🤖 Supported AI Coding Agent Integrations](#-supported-ai-coding-agent-integrations)
|
||
- [🔧 Specify CLI Reference](#-specify-cli-reference)
|
||
- [🧩 Making Spec Kit Your Own: Extensions & Presets](#-making-spec-kit-your-own-extensions--presets)
|
||
- [📦 Bundles: Role-Based Setups](#-bundles-role-based-setups)
|
||
- [📚 Core Philosophy](#-core-philosophy)
|
||
- [🌟 Development Phases](#-development-phases)
|
||
- [🎯 Experimental Goals](#-experimental-goals)
|
||
- [🔧 Prerequisites](#-prerequisites)
|
||
- [📖 Learn More](#-learn-more)
|
||
- [📋 Detailed Process](#-detailed-process)
|
||
- [💬 Support](#-support)
|
||
- [🙏 Acknowledgements](#-acknowledgements)
|
||
- [📄 License](#-license)
|
||
|
||
## 🤔 What is Spec-Driven Development?
|
||
|
||
Spec-Driven Development **flips the script** on traditional software development. For decades, code has been king — specifications were just scaffolding we built and discarded once the "real work" of coding began. Spec-Driven Development changes this: **specifications become executable**, directly generating working implementations rather than just guiding them.
|
||
|
||
## ⚡ Get Started
|
||
|
||
### 1. Install Specify CLI
|
||
|
||
Requires **[uv](https://docs.astral.sh/uv/)** ([install uv](./docs/install/uv.md)). Replace `vX.Y.Z` with the latest tag from [Releases](https://github.com/github/spec-kit/releases):
|
||
|
||
```bash
|
||
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@vX.Y.Z
|
||
```
|
||
|
||
See the [Installation Guide](./docs/installation.md) for alternative methods, verification, upgrade, and troubleshooting.
|
||
|
||
### 2. Initialize a project
|
||
|
||
```bash
|
||
specify init my-project --integration copilot
|
||
cd my-project
|
||
```
|
||
|
||
To check for updates or upgrade the installed CLI, use the self-management commands. See the [Upgrade Guide](./docs/upgrade.md) for detailed scenarios and customization options.
|
||
|
||
```bash
|
||
# Check whether a newer release is available (read-only — does not modify anything)
|
||
specify self check
|
||
|
||
# Preview what would run, without actually upgrading
|
||
specify self upgrade --dry-run
|
||
|
||
# Upgrade in place to the latest stable release (auto-detects uv tool vs pipx install)
|
||
specify self upgrade
|
||
|
||
# Or pin a specific release tag (replace vX.Y.Z[suffix] with your desired release tag)
|
||
specify self upgrade --tag vX.Y.Z[suffix]
|
||
```
|
||
|
||
Bare `specify self upgrade` executes immediately, matching the no-prompt behavior of commands like `pip install -U` and `npm update`. For `uv tool` installs, it runs `uv tool install specify-cli --force --from <git ref>` under the hood so pinned release tags work, including dev, alpha/beta/rc, or build metadata suffixes. `uvx` (ephemeral) runs and source checkouts are detected and produce path-specific guidance instead of running an installer. Set `SPECIFY_UPGRADE_TIMEOUT_SECS` to cap how long the installer subprocess may run (default: no timeout — interrupt with `Ctrl+C` if needed).
|
||
|
||
### 3. Establish project principles
|
||
|
||
Launch your coding agent in the project directory. Most agents expose spec-kit as `/speckit.*` slash commands; Codex CLI in skills mode uses `$speckit-*` instead; GitHub Copilot CLI uses `/agents` to select the agent or address it directly in a prompt.
|
||
|
||
Use the **`/speckit.constitution`** command to create your project's governing principles and development guidelines that will guide all subsequent development.
|
||
|
||
```bash
|
||
/speckit.constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements
|
||
```
|
||
|
||
### 4. Create the spec
|
||
|
||
Use the **`/speckit.specify`** command to describe what you want to build. Focus on the **what** and **why**, not the tech stack.
|
||
|
||
```bash
|
||
/speckit.specify Build an application that can help me organize my photos in separate photo albums. Albums are grouped by date and can be re-organized by dragging and dropping on the main page. Albums are never in other nested albums. Within each album, photos are previewed in a tile-like interface.
|
||
```
|
||
|
||
### 5. Create a technical implementation plan
|
||
|
||
Use the **`/speckit.plan`** command to provide your tech stack and architecture choices.
|
||
|
||
```bash
|
||
/speckit.plan The application uses Vite with minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible. Images are not uploaded anywhere and metadata is stored in a local SQLite database.
|
||
```
|
||
|
||
### 6. Break down into tasks
|
||
|
||
Use **`/speckit.tasks`** to create an actionable task list from your implementation plan.
|
||
|
||
```bash
|
||
/speckit.tasks
|
||
```
|
||
|
||
### 7. Execute implementation
|
||
|
||
Use **`/speckit.implement`** to execute all tasks and build your feature according to the plan.
|
||
|
||
```bash
|
||
/speckit.implement
|
||
```
|
||
|
||
For detailed step-by-step instructions, see our [comprehensive guide](./spec-driven.md).
|
||
|
||
## 📽️ Video Overview
|
||
|
||
Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.com/watch?v=a9eR1xsfvHg&pp=0gcJCckJAYcqIYzv)!
|
||
|
||
[](https://www.youtube.com/watch?v=a9eR1xsfvHg&pp=0gcJCckJAYcqIYzv)
|
||
|
||
## 🌍 Community
|
||
|
||
Explore community-contributed resources on the [Spec Kit docs site](https://github.github.io/spec-kit/):
|
||
|
||
- [Extensions](https://github.github.io/spec-kit/community/extensions.html) — commands, hooks, and capabilities
|
||
- [Presets](https://github.github.io/spec-kit/community/presets.html) — template and terminology overrides
|
||
- [Walkthroughs](https://github.github.io/spec-kit/community/walkthroughs.html) — end-to-end SDD scenarios
|
||
- [Friends](https://github.github.io/spec-kit/community/friends.html) — projects that extend or build on Spec Kit
|
||
|
||
> [!NOTE]
|
||
> Community contributions are independently created and maintained by their respective authors. Review source code before installation and use at your own discretion.
|
||
|
||
Want to contribute? See the [Extension Publishing Guide](extensions/EXTENSION-PUBLISHING-GUIDE.md) or the [Presets Publishing Guide](presets/PUBLISHING.md).
|
||
|
||
## 🤖 Supported AI Coding Agent Integrations
|
||
|
||
Spec Kit works with 30+ AI coding agents — both CLI tools and IDE-based assistants. See the full list with notes and usage details in the [Supported AI Coding Agent Integrations](https://github.github.io/spec-kit/reference/integrations.html) guide.
|
||
|
||
Run `specify integration list` to see all available integrations in your installed version.
|
||
|
||
## Available Slash Commands
|
||
|
||
After running `specify init`, your AI coding agent will have access to these slash commands for structured development. For integrations that support skills mode, passing `--integration <agent> --integration-options="--skills"` installs agent skills instead of slash-command prompt files.
|
||
|
||
### Core Commands
|
||
|
||
Essential commands for the Spec-Driven Development workflow:
|
||
|
||
| Command | Agent Skill | Description |
|
||
| ------------------------ | ---------------------- | -------------------------------------------------------------------------- |
|
||
| `/speckit.constitution` | `speckit-constitution` | Create or update project governing principles and development guidelines |
|
||
| `/speckit.specify` | `speckit-specify` | Define what you want to build (requirements and user stories) |
|
||
| `/speckit.plan` | `speckit-plan` | Create technical implementation plans with your chosen tech stack |
|
||
| `/speckit.tasks` | `speckit-tasks` | Generate actionable task lists for implementation |
|
||
| `/speckit.taskstoissues` | `speckit-taskstoissues`| Convert generated task lists into GitHub issues for tracking and execution |
|
||
| `/speckit.implement` | `speckit-implement` | Execute all tasks to build the feature according to the plan |
|
||
| `/speckit.converge` | `speckit-converge` | Assess the codebase against spec/plan/tasks and append remaining work as new tasks |
|
||
|
||
### Optional Commands
|
||
|
||
Additional commands for enhanced quality and validation:
|
||
|
||
| Command | Agent Skill | Description |
|
||
| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||
| `/speckit.clarify` | `speckit-clarify` | Clarify underspecified areas (recommended before `/speckit.plan`; formerly `/quizme`) |
|
||
| `/speckit.analyze` | `speckit-analyze` | Cross-artifact consistency & coverage analysis (run after `/speckit.tasks`, before `/speckit.implement`) |
|
||
| `/speckit.checklist` | `speckit-checklist` | Generate custom quality checklists that validate requirements completeness, clarity, and consistency (like "unit tests for English") |
|
||
|
||
## 🔧 Specify CLI Reference
|
||
|
||
For full command details, options, and examples, see the [CLI Reference](https://github.github.io/spec-kit/reference/overview.html).
|
||
|
||
## 🧩 Making Spec Kit Your Own: Extensions & Presets
|
||
|
||
Spec Kit can be tailored to your needs through two complementary systems — **extensions** and **presets** — plus project-local overrides for one-off adjustments:
|
||
|
||
| Priority | Component Type | Location |
|
||
| -------: | ------------------------------------------------- | -------------------------------- |
|
||
| ⬆ 1 | Project-Local Overrides | `.specify/templates/overrides/` |
|
||
| 2 | Presets — Customize core & extensions | `.specify/presets/templates/` |
|
||
| 3 | Extensions — Add new capabilities | `.specify/extensions/templates/` |
|
||
| ⬇ 4 | Spec Kit Core — Built-in SDD commands & templates | `.specify/templates/` |
|
||
|
||
- **Templates** are resolved at **runtime** — Spec Kit walks the stack top-down and uses the first match.
|
||
- Project-local overrides (`.specify/templates/overrides/`) let you make one-off adjustments for a single project without creating a full preset.
|
||
- **Extension/preset commands** are applied at **install time** — when you run `specify extension add` or `specify preset add`, command files are written into agent directories (e.g., `.claude/commands/`).
|
||
- If multiple presets or extensions provide the same command, the highest-priority version wins. On removal, the next-highest-priority version is restored automatically.
|
||
- If no overrides or customizations exist, Spec Kit uses its core defaults.
|
||
|
||
### Extensions — Add New Capabilities
|
||
|
||
Use **extensions** when you need functionality that goes beyond Spec Kit's core. Extensions introduce new commands and templates — for example, adding domain-specific workflows that are not covered by the built-in SDD commands, integrating with external tools, or adding entirely new development phases. They expand *what Spec Kit can do*.
|
||
|
||
```bash
|
||
# Search available extensions
|
||
specify extension search
|
||
|
||
# Install an extension
|
||
specify extension add <extension-name>
|
||
```
|
||
|
||
For example, extensions could add Jira integration, post-implementation code review, V-Model test traceability, or project health diagnostics.
|
||
|
||
See the [Extensions reference](https://github.github.io/spec-kit/reference/extensions.html) for the full command guide. Browse the [community extensions](https://github.github.io/spec-kit/community/extensions.html) for what's available.
|
||
|
||
### Presets — Customize Existing Workflows
|
||
|
||
Use **presets** when you want to change *how* Spec Kit works without adding new capabilities. Presets override the templates and commands that ship with the core *and* with installed extensions — for example, enforcing a compliance-oriented spec format, using domain-specific terminology, or applying organizational standards to plans and tasks. They customize the artifacts and instructions that Spec Kit and its extensions produce.
|
||
|
||
```bash
|
||
# Search available presets
|
||
specify preset search
|
||
|
||
# Install a preset
|
||
specify preset add <preset-name>
|
||
```
|
||
|
||
For example, presets could restructure spec templates to require regulatory traceability, adapt the workflow to fit the methodology you use (e.g., Agile, Kanban, Waterfall, jobs-to-be-done, or domain-driven design), add mandatory security review gates to plans, enforce test-first task ordering, or localize the entire workflow to a different language. The [pirate-speak demo](https://github.com/mnriem/spec-kit-pirate-speak-preset-demo) shows just how deep the customization can go. Multiple presets can be stacked with priority ordering.
|
||
|
||
See the [Presets reference](https://github.github.io/spec-kit/reference/presets.html) for the full command guide, including resolution order and priority stacking.
|
||
|
||
## 📦 Bundles: Role-Based Setups
|
||
|
||
Extensions and presets are individual building blocks. A **bundle** packages a
|
||
curated set of them — extensions, presets, steps, and workflows — into a single,
|
||
versioned, role-oriented setup so a whole team persona (product manager, business
|
||
analyst, security researcher, developer, …) can be provisioned with one command.
|
||
|
||
A bundle is described by a hand-written `bundle.yml` manifest. It pins each
|
||
component to a version and, optionally, targets a specific integration; a bundle
|
||
with no `integration` is **agnostic** and inherits whatever integration the
|
||
project already uses.
|
||
|
||
```bash
|
||
# Discover bundles in the active catalog stack
|
||
specify bundle search [<query>]
|
||
|
||
# Inspect the exact component set a bundle will add (equals what install does)
|
||
specify bundle info <bundle-id>
|
||
|
||
# Install a bundle's full component set in one operation
|
||
specify bundle install <bundle-id>
|
||
|
||
# See what's installed, then update or remove non-destructively
|
||
specify bundle list
|
||
specify bundle update <bundle-id> # or --all
|
||
specify bundle remove <bundle-id> # removes only this bundle's components
|
||
```
|
||
|
||
Bundles resolve from a **priority-ordered catalog stack** (project > user >
|
||
built-in). Each source carries an install policy: `install-allowed` sources can
|
||
be installed from, while `discovery-only` sources are visible in `search`/`info`
|
||
but refuse installation. Manage the stack with `specify bundle catalog list|add|remove`.
|
||
|
||
Authors validate and package bundles locally — there is no first-class publish;
|
||
distribution is hosting the built artifact and adding a catalog entry:
|
||
|
||
```bash
|
||
specify bundle validate --path ./my-bundle # structural + reference checks
|
||
specify bundle build --path ./my-bundle # produce a versioned .zip artifact
|
||
```
|
||
|
||
Four ready-to-read example manifests live under
|
||
[`examples/bundles/`](examples/bundles/) (product manager, business analyst,
|
||
security researcher, developer).
|
||
|
||
Key guarantees: `info` shows exactly what `install` adds (transparency);
|
||
installs are idempotent and confined to the project root; `remove` never touches
|
||
components another installed bundle still needs; and all consume/author commands
|
||
work **offline** against local or pinned sources.
|
||
|
||
### When to Use Which
|
||
|
||
| Goal | Use |
|
||
| --- | --- |
|
||
| Add a brand-new command or workflow | Extension |
|
||
| Customize the format of specs, plans, or tasks | Preset |
|
||
| Integrate an external tool or service | Extension |
|
||
| Enforce organizational or regulatory standards | Preset |
|
||
| Ship reusable domain-specific templates | Either — presets for template overrides, extensions for templates bundled with new commands |
|
||
| Provision a complete role-based setup in one command | Bundle |
|
||
|
||
## 📚 Core Philosophy
|
||
|
||
Spec-Driven Development is a structured process that emphasizes:
|
||
|
||
- **Intent-driven development** where specifications define the "*what*" before the "*how*"
|
||
- **Rich specification creation** using guardrails and organizational principles
|
||
- **Multi-step refinement** rather than one-shot code generation from prompts
|
||
- **Heavy reliance** on advanced AI model capabilities for specification interpretation
|
||
|
||
## 🌟 Development Phases
|
||
|
||
| Phase | Focus | Key Activities |
|
||
| ---------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||
| **0-to-1 Development** ("Greenfield") | Generate from scratch | <ul><li>Start with high-level requirements</li><li>Generate specifications</li><li>Plan implementation steps</li><li>Build production-ready applications</li></ul> |
|
||
| **Creative Exploration** | Parallel implementations | <ul><li>Explore diverse solutions</li><li>Support multiple technology stacks & architectures</li><li>Experiment with UX patterns</li></ul> |
|
||
| **Iterative Enhancement** ("Brownfield") | Brownfield modernization | <ul><li>Add features iteratively</li><li>Modernize legacy systems</li><li>Adapt processes</li></ul> |
|
||
|
||
For existing projects, keep Spec Kit tooling updates separate from feature
|
||
artifact evolution: refresh managed project files when upgrading, and update
|
||
`specs/` artifacts when intended behavior changes. The
|
||
[Evolving Specs guide](./docs/guides/evolving-specs.md) describes the
|
||
recommended brownfield loop.
|
||
|
||
## 🎯 Experimental Goals
|
||
|
||
Our research and experimentation focus on:
|
||
|
||
### Technology independence
|
||
|
||
- Create applications using diverse technology stacks
|
||
- Validate the hypothesis that Spec-Driven Development is a process not tied to specific technologies, programming languages, or frameworks
|
||
|
||
### Enterprise constraints
|
||
|
||
- Demonstrate mission-critical application development
|
||
- Incorporate organizational constraints (cloud providers, tech stacks, engineering practices)
|
||
- Support enterprise design systems and compliance requirements
|
||
|
||
### User-centric development
|
||
|
||
- Build applications for different user cohorts and preferences
|
||
- Support various development approaches (from vibe-coding to AI-native development)
|
||
|
||
### Creative & iterative processes
|
||
|
||
- Validate the concept of parallel implementation exploration
|
||
- Provide robust iterative feature development workflows
|
||
- Extend processes to handle upgrades and modernization tasks
|
||
|
||
## 🔧 Prerequisites
|
||
|
||
- **Linux/macOS/Windows**
|
||
- [Supported](#-supported-ai-coding-agent-integrations) AI coding agent.
|
||
- [uv](https://docs.astral.sh/uv/) for package management (recommended) or [pipx](https://pipx.pypa.io/) for persistent installation
|
||
- [Python 3.11+](https://www.python.org/downloads/)
|
||
- [Git](https://git-scm.com/downloads)
|
||
|
||
If you encounter issues with an agent, please open an issue so we can refine the integration.
|
||
|
||
## 📖 Learn More
|
||
|
||
- **[Complete Spec-Driven Development Methodology](./spec-driven.md)** - Deep dive into the full process
|
||
- **[Detailed Walkthrough](#-detailed-process)** - Step-by-step implementation guide
|
||
|
||
---
|
||
|
||
## 📋 Detailed Process
|
||
|
||
<details>
|
||
<summary>Click to expand the detailed step-by-step walkthrough</summary>
|
||
|
||
You can use the Specify CLI to bootstrap your project, which will bring in the required artifacts in your environment. Run:
|
||
|
||
```bash
|
||
specify init <project_name>
|
||
```
|
||
|
||
Or initialize in the current directory:
|
||
|
||
```bash
|
||
specify init .
|
||
# or use the --here flag
|
||
specify init --here
|
||
# Skip confirmation when the directory already has files
|
||
specify init . --force
|
||
# or
|
||
specify init --here --force
|
||
```
|
||
|
||

|
||
|
||
In an interactive terminal, you will be prompted to select the coding agent integration you are using. In non-interactive sessions, such as CI or piped runs, `specify init` defaults to GitHub Copilot unless you pass `--integration`. You can also proactively specify the integration directly in the terminal:
|
||
|
||
```bash
|
||
specify init <project_name> --integration copilot
|
||
specify init <project_name> --integration gemini
|
||
specify init <project_name> --integration codex
|
||
|
||
# Or in current directory:
|
||
specify init . --integration copilot
|
||
specify init . --integration codex --integration-options="--skills"
|
||
|
||
# or use --here flag
|
||
specify init --here --integration copilot
|
||
specify init --here --integration codex --integration-options="--skills"
|
||
|
||
# Force merge into a non-empty current directory
|
||
specify init . --force --integration copilot
|
||
|
||
# or
|
||
specify init --here --force --integration copilot
|
||
```
|
||
|
||
The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, Kiro CLI, Pi, Forge, Goose, or Mistral Vibe installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
|
||
|
||
```bash
|
||
specify init <project_name> --integration copilot --ignore-agent-tools
|
||
```
|
||
|
||
### **STEP 1:** Establish project principles
|
||
|
||
Go to the project folder and run your coding agent. In our example, we're using `claude`.
|
||
|
||

|
||
|
||
You will know that things are configured correctly if you see the `/speckit.constitution`, `/speckit.specify`, `/speckit.plan`, `/speckit.tasks`, and `/speckit.implement` commands available.
|
||
|
||
The first step should be establishing your project's governing principles using the `/speckit.constitution` command. This helps ensure consistent decision-making throughout all subsequent development phases:
|
||
|
||
```text
|
||
/speckit.constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements. Include governance for how these principles should guide technical decisions and implementation choices.
|
||
```
|
||
|
||
This step creates or updates the `.specify/memory/constitution.md` file with your project's foundational guidelines that the coding agent will reference during specification, planning, and implementation phases.
|
||
|
||
### **STEP 2:** Create project specifications
|
||
|
||
With your project principles established, you can now create the functional specifications. Use the `/speckit.specify` command and then provide the concrete requirements for the project you want to develop.
|
||
|
||
> [!IMPORTANT]
|
||
> Be as explicit as possible about *what* you are trying to build and *why*. **Do not focus on the tech stack at this point**.
|
||
|
||
An example prompt:
|
||
|
||
```text
|
||
Develop Taskify, a team productivity platform. It should allow users to create projects, add team members,
|
||
assign tasks, comment and move tasks between boards in Kanban style. In this initial phase for this feature,
|
||
let's call it "Create Taskify," let's have multiple users but the users will be declared ahead of time, predefined.
|
||
I want five users in two different categories, one product manager and four engineers. Let's create three
|
||
different sample projects. Let's have the standard Kanban columns for the status of each task, such as "To Do,"
|
||
"In Progress," "In Review," and "Done." There will be no login for this application as this is just the very
|
||
first testing thing to ensure that our basic features are set up. For each task in the UI for a task card,
|
||
you should be able to change the current status of the task between the different columns in the Kanban work board.
|
||
You should be able to leave an unlimited number of comments for a particular card. You should be able to, from that task
|
||
card, assign one of the valid users. When you first launch Taskify, it's going to give you a list of the five users to pick
|
||
from. There will be no password required. When you click on a user, you go into the main view, which displays the list of
|
||
projects. When you click on a project, you open the Kanban board for that project. You're going to see the columns.
|
||
You'll be able to drag and drop cards back and forth between different columns. You will see any cards that are
|
||
assigned to you, the currently logged in user, in a different color from all the other ones, so you can quickly
|
||
see yours. You can edit any comments that you make, but you can't edit comments that other people made. You can
|
||
delete any comments that you made, but you can't delete comments anybody else made.
|
||
```
|
||
|
||
After this prompt is entered, you should see Claude Code kick off the planning and spec drafting process. Claude Code will also trigger some of the built-in scripts to set up the repository.
|
||
|
||
Once this step is completed, you should have a new branch created (e.g., `001-create-taskify`), as well as a new specification in the `specs/001-create-taskify` directory.
|
||
|
||
The produced specification should contain a set of user stories and functional requirements, as defined in the template.
|
||
|
||
At this stage, your project folder contents should resemble the following:
|
||
|
||
```text
|
||
.
|
||
├── .specify
|
||
│ ├── memory
|
||
│ │ └── constitution.md
|
||
│ ├── scripts
|
||
│ │ └── bash
|
||
│ │ ├── check-prerequisites.sh
|
||
│ │ ├── common.sh
|
||
│ │ ├── create-new-feature.sh
|
||
│ │ ├── setup-plan.sh
|
||
│ │ └── setup-tasks.sh
|
||
│ └── templates
|
||
│ ├── plan-template.md
|
||
│ ├── spec-template.md
|
||
│ └── tasks-template.md
|
||
└── specs
|
||
└── 001-create-taskify
|
||
└── spec.md
|
||
```
|
||
|
||
### **STEP 3:** Functional specification clarification (required before planning)
|
||
|
||
With the baseline specification created, you can go ahead and clarify any of the requirements that were not captured properly within the first shot attempt.
|
||
|
||
You should run the structured clarification workflow **before** creating a technical plan to reduce rework downstream.
|
||
|
||
Preferred order:
|
||
|
||
1. Use `/speckit.clarify` (structured) – sequential, coverage-based questioning that records answers in a Clarifications section.
|
||
2. Optionally follow up with ad-hoc free-form refinement if something still feels vague.
|
||
|
||
If you intentionally want to skip clarification (e.g., spike or exploratory prototype), explicitly state that so the agent doesn't block on missing clarifications.
|
||
|
||
Example free-form refinement prompt (after `/speckit.clarify` if still needed):
|
||
|
||
```text
|
||
For each sample project or project that you create there should be a variable number of tasks between 5 and 15
|
||
tasks for each one randomly distributed into different states of completion. Make sure that there's at least
|
||
one task in each stage of completion.
|
||
```
|
||
|
||
You should also ask Claude Code to validate the **Review & Acceptance Checklist**, checking off the things that are validated/pass the requirements, and leave the ones that are not unchecked. The following prompt can be used:
|
||
|
||
```text
|
||
Read the review and acceptance checklist, and check off each item in the checklist if the feature spec meets the criteria. Leave it empty if it does not.
|
||
```
|
||
|
||
It's important to use the interaction with Claude Code as an opportunity to clarify and ask questions around the specification - **do not treat its first attempt as final**.
|
||
|
||
### **STEP 4:** Generate a plan
|
||
|
||
You can now be specific about the tech stack and other technical requirements. You can use the `/speckit.plan` command that is built into the project template with a prompt like this:
|
||
|
||
```text
|
||
We are going to generate this using .NET Aspire, using Postgres as the database. The frontend should use
|
||
Blazor server with drag-and-drop task boards, real-time updates. There should be a REST API created with a projects API,
|
||
tasks API, and a notifications API.
|
||
```
|
||
|
||
The output of this step will include a number of implementation detail documents, with your directory tree resembling this:
|
||
|
||
```text
|
||
.
|
||
├── CLAUDE.md
|
||
├── .specify
|
||
│ ├── memory
|
||
│ │ └── constitution.md
|
||
│ ├── scripts
|
||
│ │ └── bash
|
||
│ │ ├── check-prerequisites.sh
|
||
│ │ ├── common.sh
|
||
│ │ ├── create-new-feature.sh
|
||
│ │ ├── setup-plan.sh
|
||
│ │ └── setup-tasks.sh
|
||
│ └── templates
|
||
│ ├── CLAUDE-template.md
|
||
│ ├── plan-template.md
|
||
│ ├── spec-template.md
|
||
│ └── tasks-template.md
|
||
└── specs
|
||
└── 001-create-taskify
|
||
├── contracts
|
||
│ ├── api-spec.json
|
||
│ └── signalr-spec.md
|
||
├── data-model.md
|
||
├── plan.md
|
||
├── quickstart.md
|
||
├── research.md
|
||
└── spec.md
|
||
```
|
||
|
||
Check the `research.md` document to ensure that the right tech stack is used, based on your instructions. You can ask Claude Code to refine it if any of the components stand out, or even have it check the locally-installed version of the platform/framework you want to use (e.g., .NET).
|
||
|
||
Additionally, you might want to ask Claude Code to research details about the chosen tech stack if it's something that is rapidly changing (e.g., .NET Aspire, JS frameworks), with a prompt like this:
|
||
|
||
```text
|
||
I want you to go through the implementation plan and implementation details, looking for areas that could
|
||
benefit from additional research as .NET Aspire is a rapidly changing library. For those areas that you identify that
|
||
require further research, I want you to update the research document with additional details about the specific
|
||
versions that we are going to be using in this Taskify application and spawn parallel research tasks to clarify
|
||
any details using research from the web.
|
||
```
|
||
|
||
During this process, you might find that Claude Code gets stuck researching the wrong thing - you can help nudge it in the right direction with a prompt like this:
|
||
|
||
```text
|
||
I think we need to break this down into a series of steps. First, identify a list of tasks
|
||
that you would need to do during implementation that you're not sure of or would benefit
|
||
from further research. Write down a list of those tasks. And then for each one of these tasks,
|
||
I want you to spin up a separate research task so that the net results is we are researching
|
||
all of those very specific tasks in parallel. What I saw you doing was it looks like you were
|
||
researching .NET Aspire in general and I don't think that's gonna do much for us in this case.
|
||
That's way too untargeted research. The research needs to help you solve a specific targeted question.
|
||
```
|
||
|
||
> [!NOTE]
|
||
> Claude Code might be over-eager and add components that you did not ask for. Ask it to clarify the rationale and the source of the change.
|
||
|
||
### **STEP 5:** Have Claude Code validate the plan
|
||
|
||
With the plan in place, you should have Claude Code run through it to make sure that there are no missing pieces. You can use a prompt like this:
|
||
|
||
```text
|
||
Now I want you to go and audit the implementation plan and the implementation detail files.
|
||
Read through it with an eye on determining whether or not there is a sequence of tasks that you need
|
||
to be doing that are obvious from reading this. Because I don't know if there's enough here. For example,
|
||
when I look at the core implementation, it would be useful to reference the appropriate places in the implementation
|
||
details where it can find the information as it walks through each step in the core implementation or in the refinement.
|
||
```
|
||
|
||
This helps refine the implementation plan and helps you avoid potential blind spots that Claude Code missed in its planning cycle. Once the initial refinement pass is complete, ask Claude Code to go through the checklist once more before you can get to the implementation.
|
||
|
||
You can also ask Claude Code (if you have the [GitHub CLI](https://docs.github.com/en/github-cli/github-cli) installed) to go ahead and create a pull request from your current branch to `main` with a detailed description, to make sure that the effort is properly tracked.
|
||
|
||
> [!NOTE]
|
||
> Before you have the agent implement it, it's also worth prompting Claude Code to cross-check the details to see if there are any over-engineered pieces (remember - it can be over-eager). If over-engineered components or decisions exist, you can ask Claude Code to resolve them. Ensure that Claude Code follows the constitution in `.specify/memory/constitution.md` as the foundational piece that it must adhere to when establishing the plan.
|
||
|
||
### **STEP 6:** Generate task breakdown with /speckit.tasks
|
||
|
||
With the implementation plan validated, you can now break down the plan into specific, actionable tasks that can be executed in the correct order. Use the `/speckit.tasks` command to automatically generate a detailed task breakdown from your implementation plan:
|
||
|
||
```text
|
||
/speckit.tasks
|
||
```
|
||
|
||
This step creates a `tasks.md` file in your feature specification directory that contains:
|
||
|
||
- **Task breakdown organized by user story** - Each user story becomes a separate implementation phase with its own set of tasks
|
||
- **Dependency management** - Tasks are ordered to respect dependencies between components (e.g., models before services, services before endpoints)
|
||
- **Parallel execution markers** - Tasks that can run in parallel are marked with `[P]` to optimize development workflow
|
||
- **File path specifications** - Each task includes the exact file paths where implementation should occur
|
||
- **Test-driven development structure** - If tests are requested, test tasks are included and ordered to be written before implementation
|
||
- **Checkpoint validation** - Each user story phase includes checkpoints to validate independent functionality
|
||
|
||
The generated tasks.md provides a clear roadmap for the `/speckit.implement` command, ensuring systematic implementation that maintains code quality and allows for incremental delivery of user stories.
|
||
|
||
### **STEP 7:** Implementation
|
||
|
||
Once ready, use the `/speckit.implement` command to execute your implementation plan:
|
||
|
||
```text
|
||
/speckit.implement
|
||
```
|
||
|
||
The `/speckit.implement` command will:
|
||
|
||
- Validate that all prerequisites are in place (constitution, spec, plan, and tasks)
|
||
- Parse the task breakdown from `tasks.md`
|
||
- Execute tasks in the correct order, respecting dependencies and parallel execution markers
|
||
- Follow the TDD approach defined in your task plan
|
||
- Provide progress updates and handle errors appropriately
|
||
|
||
> [!IMPORTANT]
|
||
> The coding agent will execute local CLI commands (such as `dotnet`, `npm`, etc.) - make sure you have the required tools installed on your machine.
|
||
|
||
Once the implementation is complete, test the application and resolve any runtime errors that may not be visible in CLI logs (e.g., browser console errors). You can copy and paste such errors back to your coding agent for resolution.
|
||
|
||
</details>
|
||
|
||
---
|
||
|
||
## 💬 Support
|
||
|
||
For support, please open a [GitHub issue](https://github.com/github/spec-kit/issues/new). We welcome bug reports, feature requests, and questions about using Spec-Driven Development.
|
||
|
||
## 🙏 Acknowledgements
|
||
|
||
This project is heavily influenced by and based on the work and research of [John Lam](https://github.com/jflam).
|
||
|
||
## 📄 License
|
||
|
||
This project is licensed under the terms of the MIT open source license. Please refer to the [LICENSE](./LICENSE) file for the full terms.
|