From 272aeeaeb99e6d99c6954ba38445b15f88c0f12e Mon Sep 17 00:00:00 2001 From: Manfred Riem <15701806+mnriem@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:07:56 -0500 Subject: [PATCH 1/3] docs(scripts): document the 'py' script type and sh/ps migration plan (#3284) Bring remaining docs up to date with the Python (`py`) workflow-script variant introduced in #3277, and record the retention/deprecation plan for the shell variants. - AGENTS.md: document the `scripts:` frontmatter (sh/ps/py), clarify the `{SCRIPT}` placeholder resolution, and add a "Script Types and Migration" section (why py is recommended, defaults, phased sh/ps deprecation path). Note the Python agent-context variant. - docs/quickstart.md, docs/local-development.md: mention the `py` variant and `--script sh|ps|py`. - docs/reference/integrations.md: add `py` to the `--script` rows for install/switch/upgrade. - .devcontainer/devcontainer.json: auto-approve `.specify/scripts/python/`. Closes #3284. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 298d6ec2-a330-49bc-9394-fe2b77f25ff3 --- .devcontainer/devcontainer.json | 3 +- AGENTS.md | 50 +++++++++++++++++++++++++++++++-- docs/local-development.md | 2 +- docs/quickstart.md | 2 +- docs/reference/integrations.md | 6 ++-- 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 89c090a828..e0720dd78e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -65,7 +65,8 @@ }, "chat.tools.terminal.autoApprove": { ".specify/scripts/bash/": true, - ".specify/scripts/powershell/": true + ".specify/scripts/powershell/": true, + ".specify/scripts/python/": true } } } diff --git a/AGENTS.md b/AGENTS.md index 8b5afd4e82..df95b67901 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -187,7 +187,7 @@ context_markers: end: "" ``` -- The Specify CLI does **not** write this config. When `context_file` is empty, the extension's bundled scripts self-seed it by looking up the active integration's key in the extension's own `agent-context-defaults.json` map (`extensions/agent-context/scripts/bash/update-agent-context.sh` and `.ps1`). The CLI registry is never consulted — all agent→context-file knowledge lives inside the extension. +- The Specify CLI does **not** write this config. When `context_file` is empty, the extension's bundled scripts self-seed it by looking up the active integration's key in the extension's own `agent-context-defaults.json` map (`extensions/agent-context/scripts/bash/update-agent-context.sh`, `.ps1`, and `scripts/python/update_agent_context.py`). The CLI registry is never consulted — all agent→context-file knowledge lives inside the extension. - `context_markers.{start,end}` are read solely by the extension's scripts; they default to the Spec Kit markers shown above and can be customized by editing `agent-context-config.yml` directly. Existing projects created by older Spec Kit versions keep working: any previously written managed section or extension config is left intact and is only ever updated by the extension when run. @@ -268,6 +268,25 @@ echo "✅ Done" ## Command File Formats +### Script References (`scripts:` frontmatter) + +Command templates that invoke a helper script declare it in a `scripts:` frontmatter block with one line per supported script type. The `{SCRIPT}` placeholder in the command body is replaced at install time with the entry matching the project's selected script type (`--script sh|ps|py`): + +```yaml +scripts: + sh: scripts/bash/setup-plan.sh --json + ps: scripts/powershell/setup-plan.ps1 -Json + py: scripts/python/setup_plan.py --json +``` + +| Key | Script type | Location | +| ---- | ---------------------- | -------------------------- | +| `sh` | POSIX shell (bash/zsh) | `scripts/bash/*.sh` | +| `ps` | PowerShell | `scripts/powershell/*.ps1` | +| `py` | Python | `scripts/python/*.py` | + +All three entries must be present and behaviorally equivalent — agents parse the same stdout contract (`FEATURE_DIR:…`, `AVAILABLE_DOCS:…`, `--json` shapes) regardless of which one runs. See [Script Types and Migration](#script-types-and-migration). + ### Markdown Format **Standard format:** @@ -328,9 +347,36 @@ Different agents use different argument placeholders. The placeholder used in co - **TOML-based**: `{{args}}` (e.g., Gemini) - **YAML-based**: `{{args}}` (e.g., Goose) - **Custom**: some agents override the default (e.g., Forge uses `{{parameters}}`) -- **Script placeholders**: `{SCRIPT}` (replaced with actual script path) +- **Script placeholders**: `{SCRIPT}` (replaced with the resolved command from the template's `scripts:` frontmatter, per the project's `--script sh|ps|py` selection) - **Agent placeholders**: `__AGENT__` (replaced with agent name) +## Script Types and Migration + +Spec Kit ships every workflow script in three interchangeable variants — POSIX shell (`sh`), PowerShell (`ps`), and Python (`py`) — selected per project with `specify init --script sh|ps|py`. Each command template carries all three in its `scripts:` frontmatter (see [Script References](#script-references-scripts-frontmatter)). + +### Why Python is recommended + +- **No extra runtime.** The `specify` CLI is already Python, so the interpreter is guaranteed present — `py` adds no new dependency. +- **Single source of truth.** The shell variants require paired `.sh` + `.ps1` maintenance and diverge on JSON handling (`jq` vs manual parsing). The Python port removes that dual-maintenance and the `jq` dependency. +- **Parity-tested.** Every Python script has output-parity tests against its shell counterparts, so the stdout contract agents rely on is identical. + +### Defaults and availability + +- `py` is available today for all commands and both bundled extensions (`agent-context`, `git`). +- The interactive/auto default is still OS-based: `sh` on Linux/macOS, `ps` on Windows. `py` is opt-in via `--script py`. +- `sh` and `ps` remain fully supported. Nothing is removed. + +### Deprecation path + +`sh`/`ps` are **retained for now**. Removal is gated on adoption, not just parity, and proceeds in phases: + +1. **Now** — all three variants ship; `py` documented as recommended; OS default unchanged. +2. **Next** — `py` becomes the default once it has shipped for several releases with no parity regressions. +3. **Then** — `sh`/`ps` receive a soft-deprecation notice (still installed, marked legacy). +4. **Eventually** — `sh`/`ps` are removed in a future major release. + +Until step 4, treat all three script types as first-class: any change to a workflow script must update `sh`, `ps`, and `py` together and keep their parity tests green. + ## Special Processing Requirements Some agents require custom processing beyond the standard template transformations: diff --git a/docs/local-development.md b/docs/local-development.md index 6c94be46df..3dd922579b 100644 --- a/docs/local-development.md +++ b/docs/local-development.md @@ -2,7 +2,7 @@ This guide shows how to iterate on the `specify` CLI locally without publishing a release or committing to `main` first. -> Scripts now have both Bash (`.sh`) and PowerShell (`.ps1`) variants. The CLI auto-selects based on OS unless you pass `--script sh|ps`. +> Scripts are available as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. The CLI auto-selects a shell variant based on OS unless you pass `--script sh|ps|py`. ## 1. Clone and Switch Branches diff --git a/docs/quickstart.md b/docs/quickstart.md index 582163a371..b186f43b48 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -3,7 +3,7 @@ This guide will help you get started with Spec-Driven Development using Spec Kit. Throughout, we illustrate each step with a running example: **Taskify**, a small team productivity platform. > [!NOTE] -> Automation scripts are provided as both Bash (`.sh`) and PowerShell (`.ps1`) variants. The `specify` CLI auto-selects based on your OS unless you pass `--script sh|ps`. +> Automation scripts are provided as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. The `specify` CLI auto-selects a shell variant based on your OS unless you pass `--script sh|ps|py`. > [!NOTE] > Commands are shown here in `/speckit.*` form, but the exact invocation depends on your agent. Some skills-based agents use `$speckit-*` (e.g. Codex, ZCode) or `/skill:speckit-*` (e.g. Kimi). Use whichever form your agent exposes — the steps are otherwise identical. diff --git a/docs/reference/integrations.md b/docs/reference/integrations.md index 662c0b5e5c..311c88386d 100644 --- a/docs/reference/integrations.md +++ b/docs/reference/integrations.md @@ -86,7 +86,7 @@ specify integration install | Option | Description | | ------------------------ | ------------------------------------------------------------------------ | -| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) | +| `--script sh\|ps\|py` | Script type: `sh` (bash/zsh), `ps` (PowerShell), or `py` (Python) | | `--force` | Opt in to installing alongside integrations that are not declared multi-install safe | | `--integration-options` | Integration-specific options (e.g. `--integration-options="--commands-dir .myagent/cmds"`) | @@ -122,7 +122,7 @@ specify integration switch | Option | Description | | ------------------------ | ------------------------------------------------------------------------ | -| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) | +| `--script sh\|ps\|py` | Script type: `sh` (bash/zsh), `ps` (PowerShell), or `py` (Python) | | `--force` | Force removal of modified files during uninstall; when the target is already installed, overwrite managed shared templates while changing the default | | `--refresh-shared-infra` | Also overwrite shared infrastructure files even if you customized them (otherwise customizations are preserved) | | `--integration-options` | Options for the target integration when it is not already installed | @@ -150,7 +150,7 @@ specify integration upgrade [] | Option | Description | | ------------------------ | ------------------------------------------------------------------------ | | `--force` | Overwrite files even if they have been modified | -| `--script sh\|ps` | Script type: `sh` (bash/zsh) or `ps` (PowerShell) | +| `--script sh\|ps\|py` | Script type: `sh` (bash/zsh), `ps` (PowerShell), or `py` (Python) | | `--integration-options` | Options for the integration | Reinstalls an installed integration with updated templates and commands (e.g., after upgrading Spec Kit). Defaults to the default integration; if a key is provided, it must be one of the installed integrations. Detects locally modified files and blocks the upgrade unless `--force` is used. Stale files from the previous install that are no longer needed are removed automatically. Shared templates stay aligned with the default integration even when upgrading a non-default integration. From 66c4c67903f63ef939358fd1215f03f1ef27c294 Mon Sep 17 00:00:00 2001 From: Manfred Riem <15701806+mnriem@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:16:58 -0500 Subject: [PATCH 2/3] =?UTF-8?q?docs(scripts):=20address=20review=20?= =?UTF-8?q?=E2=80=94=20accurate=20paths,=20prompt=20behavior,=20scoped=20p?= =?UTF-8?q?y=20claims?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the review on PR #3653: - AGENTS.md: fix the agent-context Python path to its real `extensions/agent-context/scripts/python/` location. - AGENTS.md: qualify that only templates that invoke a helper script carry `scripts:` frontmatter (constitution/specify do not). - AGENTS.md: narrow the availability claim — `py` covers the core command templates; the bundled extensions ship Python scripts on disk but their command templates still invoke shell variants, so `--script py` does not yet route extension commands to Python. - AGENTS.md / quickstart / local-development: describe the interactive prompt vs. non-interactive OS default instead of "auto-selects". - local-development: add `--script py` to the wrong-script-type fix. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 298d6ec2-a330-49bc-9394-fe2b77f25ff3 --- AGENTS.md | 8 ++++---- docs/local-development.md | 4 ++-- docs/quickstart.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index df95b67901..d34bcd98cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -187,7 +187,7 @@ context_markers: end: "" ``` -- The Specify CLI does **not** write this config. When `context_file` is empty, the extension's bundled scripts self-seed it by looking up the active integration's key in the extension's own `agent-context-defaults.json` map (`extensions/agent-context/scripts/bash/update-agent-context.sh`, `.ps1`, and `scripts/python/update_agent_context.py`). The CLI registry is never consulted — all agent→context-file knowledge lives inside the extension. +- The Specify CLI does **not** write this config. When `context_file` is empty, the extension's bundled scripts self-seed it by looking up the active integration's key in the extension's own `agent-context-defaults.json` map (`extensions/agent-context/scripts/bash/update-agent-context.sh`, `.ps1`, and `extensions/agent-context/scripts/python/update_agent_context.py`). The CLI registry is never consulted — all agent→context-file knowledge lives inside the extension. - `context_markers.{start,end}` are read solely by the extension's scripts; they default to the Spec Kit markers shown above and can be customized by editing `agent-context-config.yml` directly. Existing projects created by older Spec Kit versions keep working: any previously written managed section or extension config is left intact and is only ever updated by the extension when run. @@ -352,7 +352,7 @@ Different agents use different argument placeholders. The placeholder used in co ## Script Types and Migration -Spec Kit ships every workflow script in three interchangeable variants — POSIX shell (`sh`), PowerShell (`ps`), and Python (`py`) — selected per project with `specify init --script sh|ps|py`. Each command template carries all three in its `scripts:` frontmatter (see [Script References](#script-references-scripts-frontmatter)). +Spec Kit ships every workflow script in three interchangeable variants — POSIX shell (`sh`), PowerShell (`ps`), and Python (`py`) — selected per project with `specify init --script sh|ps|py`. Every command template that invokes a helper script carries all three in its `scripts:` frontmatter (templates that don't call a script, e.g. `constitution`/`specify`, have no `scripts:` block); see [Script References](#script-references-scripts-frontmatter). ### Why Python is recommended @@ -362,8 +362,8 @@ Spec Kit ships every workflow script in three interchangeable variants — POSIX ### Defaults and availability -- `py` is available today for all commands and both bundled extensions (`agent-context`, `git`). -- The interactive/auto default is still OS-based: `sh` on Linux/macOS, `ps` on Windows. `py` is opt-in via `--script py`. +- `py` is available today for the core command templates (via their `scripts:` frontmatter). The bundled extensions (`agent-context`, `git`) ship Python script variants on disk, but their command templates still hard-code the Bash/PowerShell invocations, so `--script py` does not yet route those extension commands to Python — wiring `py` into the extension command templates is tracked separately. +- Selection is per project: interactive `specify init` prompts for the script type, while non-interactive runs default to a shell variant by OS (`sh` on Linux/macOS, `ps` on Windows). `py` is chosen at the prompt or via `--script py`. - `sh` and `ps` remain fully supported. Nothing is removed. ### Deprecation path diff --git a/docs/local-development.md b/docs/local-development.md index 3dd922579b..22e08fbbe7 100644 --- a/docs/local-development.md +++ b/docs/local-development.md @@ -2,7 +2,7 @@ This guide shows how to iterate on the `specify` CLI locally without publishing a release or committing to `main` first. -> Scripts are available as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. The CLI auto-selects a shell variant based on OS unless you pass `--script sh|ps|py`. +> Scripts are available as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. Interactive `specify init` prompts you to choose one; non-interactive runs default to a shell variant for your OS. Pass `--script sh|ps|py` to select explicitly. ## 1. Clone and Switch Branches @@ -189,7 +189,7 @@ rm -rf .venv dist build *.egg-info | `ModuleNotFoundError: typer` | Run `uv pip install -e .` | | Scripts not executable (Linux) | Re-run init or `chmod +x scripts/*.sh` | | Git commands unavailable | Install the git extension with `specify extension add git` | -| Wrong script type downloaded | Pass `--script sh` or `--script ps` explicitly | +| Wrong script type downloaded | Pass `--script sh`, `--script ps`, or `--script py` explicitly | | TLS errors on corporate network | Configure your environment's certificate store or proxy. The `--skip-tls` flag is deprecated and has no effect. | ## 14. Next Steps diff --git a/docs/quickstart.md b/docs/quickstart.md index b186f43b48..ddf6337356 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -3,7 +3,7 @@ This guide will help you get started with Spec-Driven Development using Spec Kit. Throughout, we illustrate each step with a running example: **Taskify**, a small team productivity platform. > [!NOTE] -> Automation scripts are provided as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. The `specify` CLI auto-selects a shell variant based on your OS unless you pass `--script sh|ps|py`. +> Automation scripts are provided as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. Interactive `specify init` prompts you to choose one; non-interactive runs default to a shell variant for your OS. Pass `--script sh|ps|py` to select explicitly. > [!NOTE] > Commands are shown here in `/speckit.*` form, but the exact invocation depends on your agent. Some skills-based agents use `$speckit-*` (e.g. Codex, ZCode) or `/skill:speckit-*` (e.g. Kimi). Use whichever form your agent exposes — the steps are otherwise identical. From 1a37275358f14d0012aac97117de2ad2f7f78531 Mon Sep 17 00:00:00 2001 From: Manfred Riem <15701806+mnriem@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:35:21 -0500 Subject: [PATCH 3/3] docs(scripts): trim deprecation timeline, correct parity/scope claims (review) Addresses the second review on PR #3653: - Remove the speculative four-phase deprecation timeline from AGENTS.md. A forward-looking removal schedule is roadmap content, not contributor guidance, and its phases lacked an actionable adoption signal. Replace it with the concrete contributor parity rule plus a one-line current-posture note pointing removal work to the #3277 epic. - Stop stating dual-maintenance as already eliminated: reframe "single source of truth" as the intended direction, noting all three variants are still maintained in parallel today. - Correct the parity-coverage claim: Python ports have output-parity tests where the contract is stdout-based and unit tests elsewhere, rather than every file being compared to every shell counterpart. - Scope the `scripts:` frontmatter rule to core command templates and note the agent-context/git extension templates don't use it yet. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 298d6ec2-a330-49bc-9394-fe2b77f25ff3 --- AGENTS.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d34bcd98cb..040eb07a63 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -270,7 +270,7 @@ echo "✅ Done" ### Script References (`scripts:` frontmatter) -Command templates that invoke a helper script declare it in a `scripts:` frontmatter block with one line per supported script type. The `{SCRIPT}` placeholder in the command body is replaced at install time with the entry matching the project's selected script type (`--script sh|ps|py`): +Core command templates (`templates/commands/*.md`) that invoke a helper script declare it in a `scripts:` frontmatter block with one line per supported script type. The `{SCRIPT}` placeholder in the command body is replaced at install time with the entry matching the project's selected script type (`--script sh|ps|py`): ```yaml scripts: @@ -285,7 +285,7 @@ scripts: | `ps` | PowerShell | `scripts/powershell/*.ps1` | | `py` | Python | `scripts/python/*.py` | -All three entries must be present and behaviorally equivalent — agents parse the same stdout contract (`FEATURE_DIR:…`, `AVAILABLE_DOCS:…`, `--json` shapes) regardless of which one runs. See [Script Types and Migration](#script-types-and-migration). +All three entries must be present and behaviorally equivalent — agents parse the same stdout contract (`FEATURE_DIR:…`, `AVAILABLE_DOCS:…`, `--json` shapes) regardless of which one runs. (The bundled `agent-context` and `git` extension command templates also invoke helpers but do not yet use `scripts:` frontmatter — see [Script Types and Migration](#script-types-and-migration).) ### Markdown Format @@ -352,30 +352,23 @@ Different agents use different argument placeholders. The placeholder used in co ## Script Types and Migration -Spec Kit ships every workflow script in three interchangeable variants — POSIX shell (`sh`), PowerShell (`ps`), and Python (`py`) — selected per project with `specify init --script sh|ps|py`. Every command template that invokes a helper script carries all three in its `scripts:` frontmatter (templates that don't call a script, e.g. `constitution`/`specify`, have no `scripts:` block); see [Script References](#script-references-scripts-frontmatter). +Spec Kit ships every core workflow script in three interchangeable variants — POSIX shell (`sh`), PowerShell (`ps`), and Python (`py`) — selected per project with `specify init --script sh|ps|py`. Each core command template that invokes a helper script carries all three in its `scripts:` frontmatter (templates that don't call a script, e.g. `constitution`/`specify`, have no `scripts:` block); see [Script References](#script-references-scripts-frontmatter). ### Why Python is recommended - **No extra runtime.** The `specify` CLI is already Python, so the interpreter is guaranteed present — `py` adds no new dependency. -- **Single source of truth.** The shell variants require paired `.sh` + `.ps1` maintenance and diverge on JSON handling (`jq` vs manual parsing). The Python port removes that dual-maintenance and the `jq` dependency. -- **Parity-tested.** Every Python script has output-parity tests against its shell counterparts, so the stdout contract agents rely on is identical. +- **Path toward a single source of truth.** The shell variants require paired `.sh` + `.ps1` maintenance and diverge on JSON handling (`jq` vs manual parsing). The Python variant avoids `jq` and is intended to eventually replace that dual-maintenance — but that consolidation has not happened yet: all three variants are still maintained in parallel (see the parity rule below). +- **Parity-tested.** The Python ports are covered by tests — output-parity tests against the shell scripts where the contract is stdout-based, and direct unit tests elsewhere — so the stdout contract agents rely on stays stable. ### Defaults and availability - `py` is available today for the core command templates (via their `scripts:` frontmatter). The bundled extensions (`agent-context`, `git`) ship Python script variants on disk, but their command templates still hard-code the Bash/PowerShell invocations, so `--script py` does not yet route those extension commands to Python — wiring `py` into the extension command templates is tracked separately. - Selection is per project: interactive `specify init` prompts for the script type, while non-interactive runs default to a shell variant by OS (`sh` on Linux/macOS, `ps` on Windows). `py` is chosen at the prompt or via `--script py`. -- `sh` and `ps` remain fully supported. Nothing is removed. +- `sh` and `ps` remain fully supported. Nothing is removed, and `py` is not yet the default. -### Deprecation path +### Parity rule for contributors -`sh`/`ps` are **retained for now**. Removal is gated on adoption, not just parity, and proceeds in phases: - -1. **Now** — all three variants ship; `py` documented as recommended; OS default unchanged. -2. **Next** — `py` becomes the default once it has shipped for several releases with no parity regressions. -3. **Then** — `sh`/`ps` receive a soft-deprecation notice (still installed, marked legacy). -4. **Eventually** — `sh`/`ps` are removed in a future major release. - -Until step 4, treat all three script types as first-class: any change to a workflow script must update `sh`, `ps`, and `py` together and keep their parity tests green. +All three script types are first-class: any change to a workflow script must update `sh`, `ps`, and `py` together and keep their tests (parity and unit) green. Making `py` the default and eventually retiring `sh`/`ps` is future work gated on adoption, tracked under the script-unification epic ([#3277](https://github.com/github/spec-kit/issues/3277)) — not something to act on from this doc. ## Special Processing Requirements