github-actions[bot] eabfabb490 [bug-fix] Fix reinstall-overwrites-kept-config: preserve config on plain reinstall after --keep-config (#3449)
* Fix reinstall-overwrites-kept-config: preserve config on plain reinstall after --keep-config

Apply the remediation from the bug assessment on issue #3427.

Before the unconditional shutil.rmtree(dest_dir), scan dest_dir for any
*-config.yml and *-config.local.yml files and hold their contents in memory.
After shutil.copytree succeeds, write them back so user-customized values
always win over the packaged defaults.

This mirrors the existing backup/restore logic for the --force reinstall path
but handles the case where remove --keep-config left config files behind in
an unregistered extension directory.

Refs #3427

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore method decl, move config restore before registration, preserve file mode

- Restore missing `test_install_force_without_existing` method declaration in
  tests/test_extensions.py so pytest collects it as a separate test.
- Move stranded-config restoration to immediately after `copytree`, before
  command/skill/hook registration, so a failed registration step can't leave
  preserved configs permanently lost.
- Store `(bytes, mode)` tuples instead of bare bytes when rescuing stranded
  configs, and reapply the original file mode after writing so permission bits
  (e.g. 0600 for credential files) are faithfully restored.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix: mask setuid/setgid bits when restoring stranded config file mode

Only preserve user/group read-write bits (mode & 0o660) to avoid
restoring setuid, setgid, or world-writable permissions from a
user-modified config file.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix: add copytree rollback path and strengthen regression test with packaged default config

- Wrap shutil.copytree in a try/except BaseException so stranded configs
  rescued before rmtree are written back even if copytree fails mid-way
  (addresses review comment: configs were permanently lost on copy failure)
- Add a packaged default config to extension_dir in the regression test so
  a naive 'restore only when absent' implementation would fail; assert the
  user's customized values beat the packaged defaults after reinstall

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

* fix: restore configs with secure atomic writes

Assisted-by: GitHub Copilot (model: gpt-5, autonomous)

* fix: write secure temp file then chmod to preserved_mode; add copytree-failure test

- _restore_stranded_config_file: write content while temp file is at its
  secure OS-default mode (typically 0600 on POSIX), then apply the
  original preserved_mode after the file is fully written and before the
  atomic os.replace. Removes the & 0o660 mask that was silently stripping
  world-read and executable bits (e.g. 0644 → 0640).

- Add test_copytree_failure_restores_stranded_config: patches
  shutil.copytree to create a partial destination then raise OSError,
  then asserts that the preserved config bytes and file mode are restored
  by the rollback path and that the extension remains unregistered.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

* Potential fix for pull request finding 'Unused local variable'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* Potential fix for pull request finding 'Module is imported with 'import' and 'import from''

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* fix: durable staging for stranded configs and import style fix

- Stage stranded config files to a durable rescue_staging_dir
  (extensions_dir/.rescue-staging-<id>) before rmtree so original bytes
  survive partial rmtree, copytree failure, or partial restore on retry.
  On retry the staging dir is detected and its content reused instead of
  whatever mix of packaged defaults and partial restores remains on disk.
  The staging dir is cleaned up only after every restore succeeds.
- Fix CodeQL: change `import specify_cli.extensions as _ext_module` to
  `from specify_cli import extensions as _ext_module` in test file.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

* fix: harden rescue staging dir - symlink checks, secure writes, cleanup errors

- Thread 14: Change except BaseException to except Exception in the staging
  fallback block so KeyboardInterrupt/SystemExit propagate correctly
- Thread 15: Add explanatory comment to the bare pass in the chmod except
  block to satisfy static analysis
- Thread 16: Reject a symlinked staging directory and only reload
  non-symlinked files whose names match the two recognised config suffixes
- Thread 17: Create each staging file via os.open with mode 0600 and
  O_CREAT|O_EXCL before writing so preserved bytes are never transiently
  exposed to other local users
- Thread 18: Remove ignore_errors=True from the final staging-dir cleanup
  so a failed rmtree propagates rather than silently leaving a stale
  backup that could be misread on the next retry

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

* fix: mask file-type bits from chmod, harden staging dir symlink check

- Add `import stat` to imports
- Use `stat.S_IMODE(mode)` before chmod in staging write (thread 20, line 1464)
- Use `stat.S_IMODE(preserved_mode)` and make chmod best-effort in
  `_restore_stranded_config_file` (thread 18, line 1492)
- Add `not rescue_staging_dir.is_symlink()` guard to cleanup (thread 19, line 1522)

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

* fix: use completion marker for rescue staging, abort on staging failure, full os.write

Assisted-by: GitHub Copilot (model: GPT-5.3-Codex, autonomous)

* fix(extensions): make rescue staging durable

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test(extensions): fix flaky copytree regression test

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test(extensions): fix module import alias for review feedback

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(workflows): keep cleanup warnings single-line and remove dead helper

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding 'Module is imported with 'import' and 'import from''

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* Preserve rescued extension config across retry

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Clarify ignored directory fsync cleanup errors

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Fix reinstall durability and workflow cleanup warnings

Assisted-by: GitHub Copilot (model: MAI-Code-1-Flash, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Open rescue staging file in binary mode to fix Windows CRLF corruption

On Windows os.open() defaults to text mode, so os.write() of preserved
config bytes containing \r\n was translated to \r\r\n, corrupting the
staged backup and failing the retry-restore regression test. Add
O_BINARY (0 on POSIX) to the staging file open flags.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Load .extensionignore before deleting dest_dir on reinstall

The .extensionignore loader can raise ValidationError (invalid UTF-8) or
OSError. Previously it ran after dest_dir was removed, so such a failure
left the kept config only in the hidden staging directory rather than its
documented location. Load/validate it before the rmtree so every
post-deletion failure path restores the config. Adds a regression test.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Validate .extensionignore before publishing rescue staging

Loading .extensionignore after the rescue staging directory was published
meant a validation failure left a complete staging copy behind. A later
retry (after the user fixed the ignore file and edited the kept config)
would reload the stale staged bytes and silently overwrite the newer
config. Move the loader ahead of reading/creating rescue staging so a
failure aborts while the kept config is still authoritative on disk, and
extend the regression test to prove no staging is published and a retry
adopts the newer bytes.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Harden preserved-config rescue against divergence and long names

Address three review findings on the reinstall config-rescue path:

- A complete .rescue-complete marker proves only that staging finished,
  not that dest_dir was modified. A crash after staging sync but before
  the rmtree leaves the live kept config intact; if the user edits it
  before retrying, preferring the staged bytes silently overwrote the
  newer config. The two copies are indistinguishable in provenance from
  disk, so detect divergence between a complete staging copy and the live
  config and abort (preserving both) instead of unconditionally choosing
  staging.
- The staging directory embedded the full extension ID in one path
  component. Extension IDs are length-unbounded, so a valid long ID could
  install at dest_dir yet fail every reinstall-after-keep-config with
  ENAMETOOLONG. Derive the staging component from a fixed-length hash via
  a new _rescue_staging_dir() helper.
- The stranded-config restore used the full config filename as a
  NamedTemporaryFile prefix; a name already near the component limit plus
  the random suffix raised ENAMETOOLONG. Use a short fixed prefix.

Updates the retry regression test to the new divergence semantics and
adds conflict-abort, long-ID, and fixed-prefix coverage.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Harden preserved-config rescue divergence check and fix test path

Assisted-by: GitHub Copilot (model: GPT-5.6, autonomous)

* fix: reject/flag symlinked preserved configs on reinstall

Assisted-by: GitHub Copilot (model: GPT-5.6-Sol, autonomous)

* fix: include symlinks in live-dir config enumeration and address review feedback

- _recognized_config_names() now accepts follow_symlinks=False for live dir
  so symlinked *-config.yml entries are detected and treated as conflicts
  rather than being silently deleted by rmtree.
- Add explanatory comment to bare 'except OSError: pass' in
  _restore_stranded_config_file's finally block.
- Resolve CodeQL dual-import style: use 'from specify_cli import extensions
  as _ext_module' instead of 'import specify_cli.extensions as _ext_module'.

Assisted-by: GitHub Copilot (model: claude-sonnet-4, autonomous)

* test: add staging-failure fault-injection test for rescue staging block

Add test_staging_failure_aborts_before_dest_dir_removal covering three
failure modes (mkdir, os.open/O_CREAT, fsync with EIO) in the rescue
staging block. Each parametrized case verifies:
- the install aborts before dest_dir is removed
- the preserved config bytes remain authoritative
- any partial staging is cleaned up and not left as complete
- the extension stays unregistered

Addresses review feedback on PRRT_kwDOPiFCnc6R351t.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* test: add test_retry_restores_config_from_staging_when_live_absent

Exercises the retry-from-staging branch (if staging_is_complete at
line 1505 of extensions/__init__.py) in a scenario where the live
config is absent — simulating a power loss that interrupted the
rollback before it could write the config back.

When the live copy is gone, the live-dir fallback (elif dest_dir.exists())
finds no stranded configs and the packaged default would be kept. Only the
staging-complete branch can restore the original bytes and mode. This proves
staging (not the fallback) is used on retry.

Addresses review feedback on PRRT_kwDOPiFCnc6SAL3L.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix: keep staging files writable; record modes in .rescue-modes.json; fix live-only conflict message

Thread 64: Remove os.fchmod/chmod from staged files to avoid Windows
read-only attribute that prevents shutil.rmtree from cleaning up.
Original permission bits are now written to a .rescue-modes.json sidecar
in the staging dir and reloaded during retry, with a fall-back to the
staged file's own mode for backwards-compat with pre-sidecar staging dirs.

Thread 65: Split the ValidationError message for staging-vs-live conflicts
into two accurate cases: files that diverged between both locations
("Both copies have been preserved") and live-only files that have no
backup counterpart, which previously incorrectly claimed "Both copies
have been preserved" and offered a restore instruction that was impossible.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* Potential fix for pull request finding 'Empty except'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* fix: add .keep-config provenance marker to guard rescue path against partially-failed installs

When `remove --keep-config` strands config files, write a `.keep-config`
marker into the extension directory.  `install_from_directory` now only
enters the rescue path when that marker is present, preventing a partially-
failed install (which also leaves dest_dir with no registry entry but no
marker) from having its packaged default configs treated as user-preserved
data on a retry from an updated package.

Refs: https://github.com/github/spec-kit/pull/3449#discussion_r3606283457

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* refactor: extract _has_keep_config_marker helper and document empty-content choice

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix: defer rescue-backup cleanup until registry commit; validate modes sidecar shape

Assisted-by: GitHub Copilot (model: GPT-5.6, autonomous)

* fix legacy keep-config rescue and retry baseline handling

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-07-21 10:22:07 -05:00
2025-10-17 13:04:27 -07:00
2025-12-04 11:50:36 -08:00

Spec Kit Logo

🌱 Spec Kit

Define what to build before building it — with any AI coding agent.

An open source toolkit for building high-quality software with any AI coding agent — a ready-to-use spec-driven process (or bring your own), endlessly extensible, community-driven, and built for your whole organization.

Latest Release GitHub stars License Documentation


Table of Contents

🤔 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 (install uv). Replace vX.Y.Z with the latest release tag from Releases — keep the leading v (for example, v0.12.11, not 0.12.11):

uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@vX.Y.Z

Prefer installing from PyPI? The specify-cli package is also published there:

uv tool install specify-cli

See the Installation Guide for alternative methods, verification, upgrade, and troubleshooting.

2. Initialize a project

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 for detailed scenarios and customization options.

# 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.

/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.

/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.

/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.

/speckit.tasks

7. Execute implementation

Use /speckit.implement to execute all tasks and build your feature according to the plan.

/speckit.implement

For detailed step-by-step instructions, see our comprehensive guide.

📽️ Video Overview

Want to see Spec Kit in action? Watch our video overview!

Spec Kit video header

🌍 Community

Explore community-contributed resources on the Spec Kit docs site:

  • Extensions — commands, hooks, and capabilities
  • Presets — template and terminology overrides
  • Bundles — role and team stacks composed from existing components
  • Walkthroughs — end-to-end SDD scenarios
  • Friends — 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, the Presets Publishing Guide, or the Community Bundles guide.

🤖 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 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.

🧩 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.

# 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 for the full command guide. Browse the community extensions 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.

# 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 shows just how deep the customization can go. Multiple presets can be stacked with priority ordering.

See the Presets reference 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.

# 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. Distribution is hosting the built artifact and adding a catalog source; community bundle submissions use the Bundle Submission issue template so required component catalogs and install evidence can be reviewed:

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/ (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
  • Start with high-level requirements
  • Generate specifications
  • Plan implementation steps
  • Build production-ready applications
Creative Exploration Parallel implementations
  • Explore diverse solutions
  • Support multiple technology stacks & architectures
  • Experiment with UX patterns
Iterative Enhancement ("Brownfield") Brownfield modernization
  • Add features iteratively
  • Modernize legacy systems
  • Adapt processes

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 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

If you encounter issues with an agent, please open an issue so we can refine the integration.

📖 Learn More


💬 Support

For support, please open a GitHub issue. 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.

📄 License

This project is licensed under the terms of the MIT open source license. Please refer to the LICENSE file for the full terms.

Description
No description provided
Readme MIT Cite this repository 264 MiB
Languages
Python 96.5%
Shell 1.8%
PowerShell 1.7%