Compare commits

...

5 Commits

Author SHA1 Message Date
Manfred Riem
fc3b98ea09 fix: rename Qoder AGENT_CONFIG key from 'qoder' to 'qodercli' to match actual CLI executable (#1651)
* fix: rename Qoder CLI to QoderCLI across scripts and documentation

* Apply suggestion from @Copilot

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

* Apply suggestion from @Copilot

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

* Update .github/workflows/scripts/create-release-packages.ps1

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-20 13:30:16 -06:00
Manfred Riem
6150f1e317 Add generic agent support with customizable command directories (#1639)
- Add --ai generic option for unsupported AI agents (bring your own agent)
- Require --ai-commands-dir to specify where agent reads commands from
- Generate Markdown commands with $ARGUMENTS format (compatible with most agents)
- Rebuild CHANGELOG from GitHub releases (last 10 releases)
- Align version to 0.1.3

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-20 11:05:38 -06:00
Manfred Riem
6fca5d83b2 fix: pin click>=8.1 to prevent Python 3.14/Homebrew env isolation crash (#1648)
* fix: pin click>=8.1 to prevent Python 3.14/Homebrew env isolation failures

Fixes #1631. When uv installs specify-cli on macOS with Homebrew Python
3.14, the virtual environment can fail to fully isolate from the system
site-packages, causing Homebrew's click to be loaded instead of the one
uv installed. If that system click is older than 8.1, it lacks the `ctx`
keyword argument in `ParamType.get_metavar()`, which typer 0.24.0 requires,
resulting in:

  TypeError: ParamType.get_metavar() got an unexpected keyword argument 'ctx'

Adding an explicit `click>=8.1` dependency gives uv a hard constraint so
the correct version is always resolved and installed.

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

* Update CHANGELOG.md

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-20 10:22:16 -06:00
Manfred Riem
465acd9024 fix: include 'src/**' path in release workflow triggers (#1646)
Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com>
2026-02-20 09:46:29 -06:00
dependabot[bot]
04fc3fd1ba chore(deps): bump github/codeql-action from 3 to 4 (#1635)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-19 16:31:23 -06:00
14 changed files with 135 additions and 320 deletions

View File

@@ -22,11 +22,11 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v4
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v4
with: with:
category: "/language:${{ matrix.language }}" category: "/language:${{ matrix.language }}"

View File

@@ -6,6 +6,7 @@ on:
paths: paths:
- 'memory/**' - 'memory/**'
- 'scripts/**' - 'scripts/**'
- 'src/**'
- 'templates/**' - 'templates/**'
- '.github/workflows/**' - '.github/workflows/**'
workflow_dispatch: workflow_dispatch:
@@ -57,4 +58,12 @@ jobs:
run: | run: |
chmod +x .github/workflows/scripts/update-version.sh chmod +x .github/workflows/scripts/update-version.sh
.github/workflows/scripts/update-version.sh ${{ steps.get_tag.outputs.new_version }} .github/workflows/scripts/update-version.sh ${{ steps.get_tag.outputs.new_version }}
- name: Commit version bump to main
if: steps.check_release.outputs.exists == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add pyproject.toml
git diff --cached --quiet || git commit -m "chore: bump version to ${{ steps.get_tag.outputs.new_version }} [skip ci]"
git push

View File

@@ -40,8 +40,8 @@ gh release create "$VERSION" \
.genreleases/spec-kit-template-roo-ps-"$VERSION".zip \ .genreleases/spec-kit-template-roo-ps-"$VERSION".zip \
.genreleases/spec-kit-template-codebuddy-sh-"$VERSION".zip \ .genreleases/spec-kit-template-codebuddy-sh-"$VERSION".zip \
.genreleases/spec-kit-template-codebuddy-ps-"$VERSION".zip \ .genreleases/spec-kit-template-codebuddy-ps-"$VERSION".zip \
.genreleases/spec-kit-template-qoder-sh-"$VERSION".zip \ .genreleases/spec-kit-template-qodercli-sh-"$VERSION".zip \
.genreleases/spec-kit-template-qoder-ps-"$VERSION".zip \ .genreleases/spec-kit-template-qodercli-ps-"$VERSION".zip \
.genreleases/spec-kit-template-amp-sh-"$VERSION".zip \ .genreleases/spec-kit-template-amp-sh-"$VERSION".zip \
.genreleases/spec-kit-template-amp-ps-"$VERSION".zip \ .genreleases/spec-kit-template-amp-ps-"$VERSION".zip \
.genreleases/spec-kit-template-shai-sh-"$VERSION".zip \ .genreleases/spec-kit-template-shai-sh-"$VERSION".zip \
@@ -52,5 +52,7 @@ gh release create "$VERSION" \
.genreleases/spec-kit-template-agy-ps-"$VERSION".zip \ .genreleases/spec-kit-template-agy-ps-"$VERSION".zip \
.genreleases/spec-kit-template-bob-sh-"$VERSION".zip \ .genreleases/spec-kit-template-bob-sh-"$VERSION".zip \
.genreleases/spec-kit-template-bob-ps-"$VERSION".zip \ .genreleases/spec-kit-template-bob-ps-"$VERSION".zip \
.genreleases/spec-kit-template-generic-sh-"$VERSION".zip \
.genreleases/spec-kit-template-generic-ps-"$VERSION".zip \
--title "Spec Kit Templates - $VERSION_NO_V" \ --title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md --notes-file release_notes.md

View File

@@ -14,7 +14,7 @@
.PARAMETER Agents .PARAMETER Agents
Comma or space separated subset of agents to build (default: all) Comma or space separated subset of agents to build (default: all)
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, codex, kilocode, auggie, roo, codebuddy, amp, q, bob, qoder Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, codex, kilocode, auggie, roo, codebuddy, amp, q, bob, qodercli, shai, agy, generic
.PARAMETER Scripts .PARAMETER Scripts
Comma or space separated subset of script types to build (default: both) Comma or space separated subset of script types to build (default: both)
@@ -343,9 +343,13 @@ function Build-Variant {
$cmdDir = Join-Path $baseDir ".bob/commands" $cmdDir = Join-Path $baseDir ".bob/commands"
Generate-Commands -Agent 'bob' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script Generate-Commands -Agent 'bob' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
} }
'qoder' { 'qodercli' {
$cmdDir = Join-Path $baseDir ".qoder/commands" $cmdDir = Join-Path $baseDir ".qoder/commands"
Generate-Commands -Agent 'qoder' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script Generate-Commands -Agent 'qodercli' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
}
'generic' {
$cmdDir = Join-Path $baseDir ".speckit/commands"
Generate-Commands -Agent 'generic' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
} }
} }
@@ -356,7 +360,7 @@ function Build-Variant {
} }
# Define all agents and scripts # Define all agents and scripts
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'q', 'bob', 'qoder') $AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'q', 'bob', 'qodercli', 'shai', 'agy', 'generic')
$AllScripts = @('sh', 'ps') $AllScripts = @('sh', 'ps')
function Normalize-List { function Normalize-List {

View File

@@ -6,7 +6,7 @@ set -euo pipefail
# Usage: .github/workflows/scripts/create-release-packages.sh <version> # Usage: .github/workflows/scripts/create-release-packages.sh <version>
# Version argument should include leading 'v'. # Version argument should include leading 'v'.
# Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built. # Optionally set AGENTS and/or SCRIPTS env vars to limit what gets built.
# AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex amp shai bob (default: all) # AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex amp shai bob generic (default: all)
# SCRIPTS : space or comma separated subset of: sh ps (default: both) # SCRIPTS : space or comma separated subset of: sh ps (default: both)
# Examples: # Examples:
# AGENTS=claude SCRIPTS=sh $0 v0.2.0 # AGENTS=claude SCRIPTS=sh $0 v0.2.0
@@ -203,9 +203,9 @@ build_variant() {
codebuddy) codebuddy)
mkdir -p "$base_dir/.codebuddy/commands" mkdir -p "$base_dir/.codebuddy/commands"
generate_commands codebuddy md "\$ARGUMENTS" "$base_dir/.codebuddy/commands" "$script" ;; generate_commands codebuddy md "\$ARGUMENTS" "$base_dir/.codebuddy/commands" "$script" ;;
qoder) qodercli)
mkdir -p "$base_dir/.qoder/commands" mkdir -p "$base_dir/.qoder/commands"
generate_commands qoder md "\$ARGUMENTS" "$base_dir/.qoder/commands" "$script" ;; generate_commands qodercli md "\$ARGUMENTS" "$base_dir/.qoder/commands" "$script" ;;
amp) amp)
mkdir -p "$base_dir/.agents/commands" mkdir -p "$base_dir/.agents/commands"
generate_commands amp md "\$ARGUMENTS" "$base_dir/.agents/commands" "$script" ;; generate_commands amp md "\$ARGUMENTS" "$base_dir/.agents/commands" "$script" ;;
@@ -221,13 +221,16 @@ build_variant() {
bob) bob)
mkdir -p "$base_dir/.bob/commands" mkdir -p "$base_dir/.bob/commands"
generate_commands bob md "\$ARGUMENTS" "$base_dir/.bob/commands" "$script" ;; generate_commands bob md "\$ARGUMENTS" "$base_dir/.bob/commands" "$script" ;;
generic)
mkdir -p "$base_dir/.speckit/commands"
generate_commands generic md "\$ARGUMENTS" "$base_dir/.speckit/commands" "$script" ;;
esac esac
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . ) ( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
echo "Created $GENRELEASES_DIR/spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" echo "Created $GENRELEASES_DIR/spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
} }
# Determine agent list # Determine agent list
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q agy bob qoder) ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q agy bob qodercli generic)
ALL_SCRIPTS=(sh ps) ALL_SCRIPTS=(sh ps)
norm_list() { norm_list() {

View File

@@ -43,11 +43,12 @@ Specify supports multiple AI agents by generating agent-specific command files a
| **Auggie CLI** | `.augment/rules/` | Markdown | `auggie` | Auggie CLI | | **Auggie CLI** | `.augment/rules/` | Markdown | `auggie` | Auggie CLI |
| **Roo Code** | `.roo/rules/` | Markdown | N/A (IDE-based) | Roo Code IDE | | **Roo Code** | `.roo/rules/` | Markdown | N/A (IDE-based) | Roo Code IDE |
| **CodeBuddy CLI** | `.codebuddy/commands/` | Markdown | `codebuddy` | CodeBuddy CLI | | **CodeBuddy CLI** | `.codebuddy/commands/` | Markdown | `codebuddy` | CodeBuddy CLI |
| **Qoder CLI** | `.qoder/commands/` | Markdown | `qoder` | Qoder CLI | | **Qoder CLI** | `.qoder/commands/` | Markdown | `qodercli` | Qoder CLI |
| **Amazon Q Developer CLI** | `.amazonq/prompts/` | Markdown | `q` | Amazon Q Developer CLI | | **Amazon Q Developer CLI** | `.amazonq/prompts/` | Markdown | `q` | Amazon Q Developer CLI |
| **Amp** | `.agents/commands/` | Markdown | `amp` | Amp CLI | | **Amp** | `.agents/commands/` | Markdown | `amp` | Amp CLI |
| **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI | | **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI |
| **IBM Bob** | `.bob/commands/` | Markdown | N/A (IDE-based) | IBM Bob IDE | | **IBM Bob** | `.bob/commands/` | Markdown | N/A (IDE-based) | IBM Bob IDE |
| **Generic** | User-specified via `--ai-commands-dir` | Markdown | N/A | Bring your own agent |
### Step-by-Step Integration Guide ### Step-by-Step Integration Guide
@@ -313,7 +314,7 @@ Require a command-line tool to be installed:
- **opencode**: `opencode` CLI - **opencode**: `opencode` CLI
- **Amazon Q Developer CLI**: `q` CLI - **Amazon Q Developer CLI**: `q` CLI
- **CodeBuddy CLI**: `codebuddy` CLI - **CodeBuddy CLI**: `codebuddy` CLI
- **Qoder CLI**: `qoder` CLI - **Qoder CLI**: `qodercli` CLI
- **Amp**: `amp` CLI - **Amp**: `amp` CLI
- **SHAI**: `shai` CLI - **SHAI**: `shai` CLI

View File

@@ -2,312 +2,65 @@
<!-- markdownlint-disable MD024 --> <!-- markdownlint-disable MD024 -->
All notable changes to the Specify CLI and templates are documented here. All notable changes to the Specify CLI and templates are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.1.1] - 2026-02-13 ## [0.1.4] - Unreleased
### Added
- **Agent Skills Installation**: New `--ai-skills` CLI option to install Prompt.MD templates as agent skills following [agentskills.io specification](https://agentskills.io/specification)
- Skills are installed to agent-specific directories (e.g., `.claude/skills/`, `.gemini/skills/`, `.github/skills/`)
- Codex uses `.agents/skills/` following Codex agent directory conventions
- Default fallback directory is `.agents/skills/` for agents without a specific mapping
- Requires `--ai` flag to be specified
- Converts all 9 spec-kit command templates (specify, plan, tasks, implement, analyze, clarify, constitution, checklist, taskstoissues) to properly formatted SKILL.md files
- **New projects**: command files are not installed when `--ai-skills` is used (skills replace commands)
- **Existing repos** (`--here`): pre-existing command files are preserved — no breaking changes
- `pyyaml` dependency (already present) used for YAML frontmatter parsing
- **Unit tests** for `install_ai_skills`, `_get_skills_dir`, and `--ai-skills` CLI validation (51 test cases covering all 18 supported agents)
## [0.1.0] - 2026-01-28
### Added
- **Extension System**: Introduced modular extension architecture for Spec Kit
- Extensions are self-contained packages that add commands and functionality without bloating core
- Extension manifest schema (`extension.yml`) with validation
- Extension registry (`.specify/extensions/.registry`) for tracking installed extensions
- Extension manager module (`src/specify_cli/extensions.py`) for installation/removal
- New CLI commands:
- `specify extension list` - List installed extensions
- `specify extension add` - Install extension from local directory or URL
- `specify extension remove` - Uninstall extension
- `specify extension search` - Search extension catalog
- `specify extension info` - Show detailed extension information
- Semantic versioning compatibility checks
- Support for extension configuration files
- Command registration system for AI agents (Claude support initially)
- Added dependencies: `pyyaml>=6.0`, `packaging>=23.0`
- **Extension Catalog**: Extension discovery and distribution system
- Central catalog (`extensions/catalog.json`) for published extensions
- Extension catalog manager (`ExtensionCatalog` class) with:
- Catalog fetching from GitHub
- 1-hour local caching for performance
- Search by query, tag, author, or verification status
- Extension info retrieval
- Catalog cache stored in `.specify/extensions/.cache/`
- Search and info commands with rich console output
- Added 9 catalog-specific unit tests (100% pass rate)
- **Jira Extension**: First official extension for Jira integration
- Extension ID: `jira`
- Version: 1.0.0
- Commands:
- `/speckit.jira.specstoissues` - Create Jira hierarchy from spec and tasks
- `/speckit.jira.discover-fields` - Discover Jira custom fields
- `/speckit.jira.sync-status` - Sync task completion status
- Comprehensive documentation (README, usage guide, examples)
- MIT licensed
- **Hook System**: Extension lifecycle hooks for automation
- `HookExecutor` class for managing extension hooks
- Hooks registered in `.specify/extensions.yml`
- Hook registration during extension installation
- Hook unregistration during extension removal
- Support for optional and mandatory hooks
- Hook execution messages for AI agent integration
- Condition support for conditional hook execution (placeholder)
- **Extension Management**: Advanced extension management commands
- `specify extension update` - Check and update extensions to latest version
- `specify extension enable` - Enable a disabled extension
- `specify extension disable` - Disable extension without removing it
- Version comparison with catalog
- Update notifications
- Preserve configuration during updates
- **Multi-Agent Support**: Extensions now work with all supported AI agents (Phase 6)
- Automatic detection and registration for all agents in project
- Support for 16+ AI agents (Claude, Gemini, Copilot, Cursor, Qwen, and more)
- Agent-specific command formats (Markdown and TOML)
- Automatic argument placeholder conversion ($ARGUMENTS → {{args}})
- Commands registered for all detected agents during installation
- Multi-agent command unregistration on extension removal
- `CommandRegistrar.register_commands_for_agent()` method
- `CommandRegistrar.register_commands_for_all_agents()` method
- **Configuration Layers**: Full configuration cascade system (Phase 6)
- **Layer 1**: Defaults from extension manifest (`extension.yml`)
- **Layer 2**: Project config (`.specify/extensions/{ext-id}/{ext-id}-config.yml`)
- **Layer 3**: Local config (`.specify/extensions/{ext-id}/local-config.yml`, gitignored)
- **Layer 4**: Environment variables (`SPECKIT_{EXT_ID}_{KEY}` pattern)
- Recursive config merging with proper precedence
- `ConfigManager` class for programmatic config access
- `get_config()`, `get_value()`, `has_value()` methods
- Support for nested configuration paths with dot-notation
- **Hook Condition Evaluation**: Smart hook execution based on runtime conditions (Phase 6)
- Config conditions: `config.key.path is set`, `config.key == 'value'`, `config.key != 'value'`
- Environment conditions: `env.VAR is set`, `env.VAR == 'value'`, `env.VAR != 'value'`
- Automatic filtering of hooks based on condition evaluation
- Safe fallback behavior on evaluation errors
- Case-insensitive pattern matching
- **Hook Integration**: Agent-level hook checking and execution (Phase 6)
- `check_hooks_for_event()` method for AI agents to query hooks after core commands
- Condition-aware hook filtering before execution
- `enable_hooks()` and `disable_hooks()` methods per extension
- Formatted hook messages for agent display
- `execute_hook()` method for hook execution information
- **Documentation Suite**: Comprehensive documentation for users and developers
- **EXTENSION-USER-GUIDE.md**: Complete user guide with installation, usage, configuration, and troubleshooting
- **EXTENSION-API-REFERENCE.md**: Technical API reference with manifest schema, Python API, and CLI commands
- **EXTENSION-PUBLISHING-GUIDE.md**: Publishing guide for extension authors
- **RFC-EXTENSION-SYSTEM.md**: Extension architecture design document
- **Extension Template**: Starter template in `extensions/template/` for creating new extensions
- Fully commented `extension.yml` manifest template
- Example command file with detailed explanations
- Configuration template with all options
- Complete project structure (README, LICENSE, CHANGELOG, .gitignore)
- EXAMPLE-README.md showing final documentation format
- **Unit Tests**: Comprehensive test suite with 39 tests covering all extension system components
- Test coverage: 83% of extension module code
- Test dependencies: `pytest>=7.0`, `pytest-cov>=4.0`
- Configured pytest in `pyproject.toml`
### Changed
- Version bumped to 0.1.0 (minor release for new feature)
## [0.0.22] - 2025-11-07
- Support for VS Code/Copilot agents, and moving away from prompts to proper agents with hand-offs.
- Move to use `AGENTS.md` for Copilot workloads, since it's already supported out-of-the-box.
- Adds support for the version command. ([#486](https://github.com/github/spec-kit/issues/486))
- Fixes potential bug with the `create-new-feature.ps1` script that ignores existing feature branches when determining next feature number ([#975](https://github.com/github/spec-kit/issues/975))
- Add graceful fallback and logging for GitHub API rate-limiting during template fetch ([#970](https://github.com/github/spec-kit/issues/970))
## [0.0.21] - 2025-10-21
- Fixes [#975](https://github.com/github/spec-kit/issues/975) (thank you [@fgalarraga](https://github.com/fgalarraga)).
- Adds support for Amp CLI.
- Adds support for VS Code hand-offs and moves prompts to be full-fledged chat modes.
- Adds support for `version` command (addresses [#811](https://github.com/github/spec-kit/issues/811) and [#486](https://github.com/github/spec-kit/issues/486), thank you [@mcasalaina](https://github.com/mcasalaina) and [@dentity007](https://github.com/dentity007)).
- Adds support for rendering the rate limit errors from the CLI when encountered ([#970](https://github.com/github/spec-kit/issues/970), thank you [@psmman](https://github.com/psmman)).
## [0.0.20] - 2025-10-14
### Added
- **Intelligent Branch Naming**: `create-new-feature` scripts now support `--short-name` parameter for custom branch names
- When `--short-name` provided: Uses the custom name directly (cleaned and formatted)
- When omitted: Automatically generates meaningful names using stop word filtering and length-based filtering
- Filters out common stop words (I, want, to, the, for, etc.)
- Removes words shorter than 3 characters (unless they're uppercase acronyms)
- Takes 3-4 most meaningful words from the description
- **Enforces GitHub's 244-byte branch name limit** with automatic truncation and warnings
- Examples:
- "I want to create user authentication" → `001-create-user-authentication`
- "Implement OAuth2 integration for API" → `001-implement-oauth2-integration-api`
- "Fix payment processing bug" → `001-fix-payment-processing`
- Very long descriptions are automatically truncated at word boundaries to stay within limits
- Designed for AI agents to provide semantic short names while maintaining standalone usability
### Changed
- Enhanced help documentation for `create-new-feature.sh` and `create-new-feature.ps1` scripts with examples
- Branch names now validated against GitHub's 244-byte limit with automatic truncation if needed
## [0.0.19] - 2025-10-10
### Added
- Support for CodeBuddy (thank you to [@lispking](https://github.com/lispking) for the contribution).
- You can now see Git-sourced errors in the Specify CLI.
### Changed
- Fixed the path to the constitution in `plan.md` (thank you to [@lyzno1](https://github.com/lyzno1) for spotting).
- Fixed backslash escapes in generated TOML files for Gemini (thank you to [@hsin19](https://github.com/hsin19) for the contribution).
- Implementation command now ensures that the correct ignore files are added (thank you to [@sigent-amazon](https://github.com/sigent-amazon) for the contribution).
## [0.0.18] - 2025-10-06
### Added
- Support for using `.` as a shorthand for current directory in `specify init .` command, equivalent to `--here` flag but more intuitive for users.
- Use the `/speckit.` command prefix to easily discover Spec Kit-related commands.
- Refactor the prompts and templates to simplify their capabilities and how they are tracked. No more polluting things with tests when they are not needed.
- Ensure that tasks are created per user story (simplifies testing and validation).
- Add support for Visual Studio Code prompt shortcuts and automatic script execution.
### Changed
- All command files now prefixed with `speckit.` (e.g., `speckit.specify.md`, `speckit.plan.md`) for better discoverability and differentiation in IDE/CLI command palettes and file explorers
## [0.0.17] - 2025-09-22
### Added
- New `/clarify` command template to surface up to 5 targeted clarification questions for an existing spec and persist answers into a Clarifications section in the spec.
- New `/analyze` command template providing a non-destructive cross-artifact discrepancy and alignment report (spec, clarifications, plan, tasks, constitution) inserted after `/tasks` and before `/implement`.
- Note: Constitution rules are explicitly treated as non-negotiable; any conflict is a CRITICAL finding requiring artifact remediation, not weakening of principles.
## [0.0.16] - 2025-09-22
### Added
- `--force` flag for `init` command to bypass confirmation when using `--here` in a non-empty directory and proceed with merging/overwriting files.
## [0.0.15] - 2025-09-21
### Added
- Support for Roo Code.
## [0.0.14] - 2025-09-21
### Changed
- Error messages are now shown consistently.
## [0.0.13] - 2025-09-21
### Added
- Support for Kilo Code. Thank you [@shahrukhkhan489](https://github.com/shahrukhkhan489) with [#394](https://github.com/github/spec-kit/pull/394).
- Support for Auggie CLI. Thank you [@hungthai1401](https://github.com/hungthai1401) with [#137](https://github.com/github/spec-kit/pull/137).
- Agent folder security notice displayed after project provisioning completion, warning users that some agents may store credentials or auth tokens in their agent folders and recommending adding relevant folders to `.gitignore` to prevent accidental credential leakage.
### Changed
- Warning displayed to ensure that folks are aware that they might need to add their agent folder to `.gitignore`.
- Cleaned up the `check` command output.
## [0.0.12] - 2025-09-21
### Changed
- Added additional context for OpenAI Codex users - they need to set an additional environment variable, as described in [#417](https://github.com/github/spec-kit/issues/417).
## [0.0.11] - 2025-09-20
### Added
- Codex CLI support (thank you [@honjo-hiroaki-gtt](https://github.com/honjo-hiroaki-gtt) for the contribution in [#14](https://github.com/github/spec-kit/pull/14))
- Codex-aware context update tooling (Bash and PowerShell) so feature plans refresh `AGENTS.md` alongside existing assistants without manual edits.
## [0.0.10] - 2025-09-20
### Fixed ### Fixed
- Addressed [#378](https://github.com/github/spec-kit/issues/378) where a GitHub token may be attached to the request when it was empty. - **Qoder CLI detection**: Renamed `AGENT_CONFIG` key from `"qoder"` to `"qodercli"` to match the actual executable name, fixing `specify check` and `specify init --ai` detection failures
## [0.0.9] - 2025-09-19 ## [0.1.3] - Unreleased
### Changed
- Improved agent selector UI with cyan highlighting for agent keys and gray parentheses for full names
## [0.0.8] - 2025-09-19
### Added ### Added
- Windsurf IDE support as additional AI assistant option (thank you [@raedkit](https://github.com/raedkit) for the work in [#151](https://github.com/github/spec-kit/pull/151)) - **Generic Agent Support**: Added `--ai generic` option for unsupported AI agents ("bring your own agent")
- GitHub token support for API requests to handle corporate environments and rate limiting (contributed by [@zryfish](https://github.com/@zryfish) in [#243](https://github.com/github/spec-kit/pull/243)) - Requires `--ai-commands-dir <path>` to specify where the agent reads commands from
- Generates Markdown commands with `$ARGUMENTS` format (compatible with most agents)
- Example: `specify init my-project --ai generic --ai-commands-dir .myagent/commands/`
- Enables users to start with Spec Kit immediately while their agent awaits formal support
### Changed ## [0.0.102] - 2026-02-20
- Updated README with Windsurf examples and GitHub token usage - fix: include 'src/**' path in release workflow triggers (#1646)
- Enhanced release workflow to include Windsurf templates
## [0.0.7] - 2025-09-18 ## [0.0.101] - 2026-02-19
### Changed - chore(deps): bump github/codeql-action from 3 to 4 (#1635)
- Updated command instructions in the CLI. ## [0.0.100] - 2026-02-19
- Cleaned up the code to not render agent-specific information when it's generic.
## [0.0.6] - 2025-09-17 - Add pytest and Python linting (ruff) to CI (#1637)
- feat: add pull request template for better contribution guidelines (#1634)
### Added ## [0.0.99] - 2026-02-19
- opencode support as additional AI assistant option - Feat/ai skills (#1632)
## [0.0.5] - 2025-09-17 ## [0.0.98] - 2026-02-19
### Added - chore(deps): bump actions/stale from 9 to 10 (#1623)
- feat: add dependabot configuration for pip and GitHub Actions updates (#1622)
- Qwen Code support as additional AI assistant option ## [0.0.97] - 2026-02-18
## [0.0.4] - 2025-09-14 - Remove Maintainers section from README.md (#1618)
### Added ## [0.0.96] - 2026-02-17
- SOCKS proxy support for corporate environments via `httpx[socks]` dependency - fix: typo in plan-template.md (#1446)
### Fixed ## [0.0.95] - 2026-02-12
N/A - Feat: add a new agent: Google Anti Gravity (#1220)
### Changed ## [0.0.94] - 2026-02-11
N/A - Add stale workflow for 180-day inactive issues and PRs (#1594)
## [0.0.93] - 2026-02-10
- Add modular extension system (#1551)

View File

@@ -162,6 +162,7 @@ Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.c
| [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | | | [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | |
| [Windsurf](https://windsurf.com/) | ✅ | | | [Windsurf](https://windsurf.com/) | ✅ | |
| [Antigravity (agy)](https://agy.ai/) | ✅ | | | [Antigravity (agy)](https://agy.ai/) | ✅ | |
| Generic | ✅ | Bring your own agent — use `--ai generic --ai-commands-dir <path>` for unsupported agents |
## 🔧 Specify CLI Reference ## 🔧 Specify CLI Reference
@@ -172,14 +173,15 @@ The `specify` command supports the following options:
| Command | Description | | Command | Description |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `init` | Initialize a new Specify project from the latest template | | `init` | Initialize a new Specify project from the latest template |
| `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `qwen`, `opencode`, `codex`, `shai`, `qoder`) | | `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `qwen`, `opencode`, `codex`, `shai`, `qodercli`) |
### `specify init` Arguments & Options ### `specify init` Arguments & Options
| Argument/Option | Type | Description | | Argument/Option | Type | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`, or use `.` for current directory) | | `<project-name>` | Argument | Name for your new project directory (optional if using `--here`, or use `.` for current directory) |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `q`, `agy`, `bob`, or `qoder` | | `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `q`, `agy`, `bob`, `qodercli`, or `generic` (requires `--ai-commands-dir`) |
| `--ai-commands-dir` | Option | Directory for agent command files (required with `--ai generic`, e.g. `.myagent/commands/`) |
| `--script` | Option | Script variant to use: `sh` (bash/zsh) or `ps` (PowerShell) | | `--script` | Option | Script variant to use: `sh` (bash/zsh) or `ps` (PowerShell) |
| `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code | | `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code |
| `--no-git` | Flag | Skip git repository initialization | | `--no-git` | Flag | Skip git repository initialization |
@@ -203,7 +205,7 @@ specify init my-project --ai claude
specify init my-project --ai cursor-agent specify init my-project --ai cursor-agent
# Initialize with Qoder support # Initialize with Qoder support
specify init my-project --ai qoder specify init my-project --ai qodercli
# Initialize with Windsurf support # Initialize with Windsurf support
specify init my-project --ai windsurf specify init my-project --ai windsurf
@@ -217,6 +219,9 @@ specify init my-project --ai shai
# Initialize with IBM Bob support # Initialize with IBM Bob support
specify init my-project --ai bob specify init my-project --ai bob
# Initialize with an unsupported agent (generic / bring your own agent)
specify init my-project --ai generic --ai-commands-dir .myagent/commands/
# Initialize with PowerShell scripts (Windows/cross-platform) # Initialize with PowerShell scripts (Windows/cross-platform)
specify init my-project --ai copilot --script ps specify init my-project --ai copilot --script ps

View File

@@ -1,10 +1,11 @@
[project] [project]
name = "specify-cli" name = "specify-cli"
version = "0.1.1" version = "0.1.4"
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)." description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = [ dependencies = [
"typer", "typer",
"click>=8.1",
"rich", "rich",
"httpx[socks]", "httpx[socks]",
"platformdirs", "platformdirs",

View File

@@ -35,7 +35,7 @@
# - Creates default Claude file if no agent files exist # - Creates default Claude file if no agent files exist
# #
# Usage: ./update-agent-context.sh [agent_type] # Usage: ./update-agent-context.sh [agent_type]
# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder # Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli
# Leave empty to update all existing agent files # Leave empty to update all existing agent files
set -e set -e
@@ -619,7 +619,7 @@ update_specific_agent() {
codebuddy) codebuddy)
update_agent_file "$CODEBUDDY_FILE" "CodeBuddy CLI" update_agent_file "$CODEBUDDY_FILE" "CodeBuddy CLI"
;; ;;
qoder) qodercli)
update_agent_file "$QODER_FILE" "Qoder CLI" update_agent_file "$QODER_FILE" "Qoder CLI"
;; ;;
amp) amp)
@@ -637,9 +637,12 @@ update_specific_agent() {
bob) bob)
update_agent_file "$BOB_FILE" "IBM Bob" update_agent_file "$BOB_FILE" "IBM Bob"
;; ;;
generic)
log_info "Generic agent: no predefined context file. Use the agent-specific update script for your agent."
;;
*) *)
log_error "Unknown agent type '$agent_type'" log_error "Unknown agent type '$agent_type'"
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|amp|shai|q|agy|bob|qoder" log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|generic"
exit 1 exit 1
;; ;;
esac esac
@@ -752,7 +755,7 @@ print_summary() {
echo echo
log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder]" log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli]"
} }
#============================================================================== #==============================================================================

View File

@@ -9,7 +9,7 @@ Mirrors the behavior of scripts/bash/update-agent-context.sh:
2. Plan Data Extraction 2. Plan Data Extraction
3. Agent File Management (create from template or update existing) 3. Agent File Management (create from template or update existing)
4. Content Generation (technology stack, recent changes, timestamp) 4. Content Generation (technology stack, recent changes, timestamp)
5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, q, agy, bob, qoder) 5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, q, agy, bob, qodercli)
.PARAMETER AgentType .PARAMETER AgentType
Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist). Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
@@ -25,7 +25,7 @@ Relies on common helper functions in common.ps1
#> #>
param( param(
[Parameter(Position=0)] [Parameter(Position=0)]
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','q','agy','bob','qoder')] [ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','q','agy','bob','qodercli','generic')]
[string]$AgentType [string]$AgentType
) )
@@ -384,13 +384,14 @@ function Update-SpecificAgent {
'auggie' { Update-AgentFile -TargetFile $AUGGIE_FILE -AgentName 'Auggie CLI' } 'auggie' { Update-AgentFile -TargetFile $AUGGIE_FILE -AgentName 'Auggie CLI' }
'roo' { Update-AgentFile -TargetFile $ROO_FILE -AgentName 'Roo Code' } 'roo' { Update-AgentFile -TargetFile $ROO_FILE -AgentName 'Roo Code' }
'codebuddy' { Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI' } 'codebuddy' { Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI' }
'qoder' { Update-AgentFile -TargetFile $QODER_FILE -AgentName 'Qoder CLI' } 'qodercli' { Update-AgentFile -TargetFile $QODER_FILE -AgentName 'Qoder CLI' }
'amp' { Update-AgentFile -TargetFile $AMP_FILE -AgentName 'Amp' } 'amp' { Update-AgentFile -TargetFile $AMP_FILE -AgentName 'Amp' }
'shai' { Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI' } 'shai' { Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI' }
'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' } 'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' }
'agy' { Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity' } 'agy' { Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity' }
'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' } 'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder'; return $false } 'generic' { Write-Info 'Generic agent: no predefined context file. Use the agent-specific update script for your agent.' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|generic'; return $false }
} }
} }
@@ -427,7 +428,7 @@ function Print-Summary {
if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" } if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" }
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" } if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" }
Write-Host '' Write-Host ''
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder]' Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|generic]'
} }
function Main { function Main {

View File

@@ -191,7 +191,7 @@ AGENT_CONFIG = {
"install_url": "https://www.codebuddy.ai/cli", "install_url": "https://www.codebuddy.ai/cli",
"requires_cli": True, "requires_cli": True,
}, },
"qoder": { "qodercli": {
"name": "Qoder CLI", "name": "Qoder CLI",
"folder": ".qoder/", "folder": ".qoder/",
"install_url": "https://qoder.com/cli", "install_url": "https://qoder.com/cli",
@@ -233,6 +233,12 @@ AGENT_CONFIG = {
"install_url": None, # IDE-based "install_url": None, # IDE-based
"requires_cli": False, "requires_cli": False,
}, },
"generic": {
"name": "Generic (bring your own agent)",
"folder": None, # Set dynamically via --ai-commands-dir
"install_url": None,
"requires_cli": False,
},
} }
SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"} SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
@@ -1188,7 +1194,8 @@ def install_ai_skills(project_path: Path, selected_ai: str, tracker: StepTracker
@app.command() @app.command()
def init( def init(
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here, or use '.' for current directory)"), project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here, or use '.' for current directory)"),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, codebuddy, amp, shai, q, agy, bob, or qoder "), ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, codebuddy, amp, shai, q, agy, bob, qodercli, or generic (requires --ai-commands-dir)"),
ai_commands_dir: str = typer.Option(None, "--ai-commands-dir", help="Directory for agent command files (required with --ai generic, e.g. .myagent/commands/)"),
script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"), script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"),
ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"), ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"),
no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"), no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"),
@@ -1224,6 +1231,7 @@ def init(
specify init --here --force # Skip confirmation when current directory not empty specify init --here --force # Skip confirmation when current directory not empty
specify init my-project --ai claude --ai-skills # Install agent skills specify init my-project --ai claude --ai-skills # Install agent skills
specify init --here --ai gemini --ai-skills specify init --here --ai gemini --ai-skills
specify init my-project --ai generic --ai-commands-dir .myagent/commands/ # Unsupported agent
""" """
show_banner() show_banner()
@@ -1308,6 +1316,16 @@ def init(
"copilot" "copilot"
) )
# Validate --ai-commands-dir usage
if selected_ai == "generic":
if not ai_commands_dir:
console.print("[red]Error:[/red] --ai-commands-dir is required when using --ai generic")
console.print("[dim]Example: specify init my-project --ai generic --ai-commands-dir .myagent/commands/[/dim]")
raise typer.Exit(1)
elif ai_commands_dir:
console.print(f"[red]Error:[/red] --ai-commands-dir can only be used with --ai generic (not '{selected_ai}')")
raise typer.Exit(1)
if not ignore_agent_tools: if not ignore_agent_tools:
agent_config = AGENT_CONFIG.get(selected_ai) agent_config = AGENT_CONFIG.get(selected_ai)
if agent_config and agent_config["requires_cli"]: if agent_config and agent_config["requires_cli"]:
@@ -1383,6 +1401,18 @@ def init(
download_and_extract_template(project_path, selected_ai, selected_script, here, verbose=False, tracker=tracker, client=local_client, debug=debug, github_token=github_token) download_and_extract_template(project_path, selected_ai, selected_script, here, verbose=False, tracker=tracker, client=local_client, debug=debug, github_token=github_token)
# For generic agent, rename placeholder directory to user-specified path
if selected_ai == "generic" and ai_commands_dir:
placeholder_dir = project_path / ".speckit" / "commands"
target_dir = project_path / ai_commands_dir
if placeholder_dir.is_dir():
target_dir.parent.mkdir(parents=True, exist_ok=True)
shutil.move(str(placeholder_dir), str(target_dir))
# Clean up empty .speckit dir if it's now empty
speckit_dir = project_path / ".speckit"
if speckit_dir.is_dir() and not any(speckit_dir.iterdir()):
speckit_dir.rmdir()
ensure_executable_scripts(project_path, tracker=tracker) ensure_executable_scripts(project_path, tracker=tracker)
ensure_constitution_from_template(project_path, tracker=tracker) ensure_constitution_from_template(project_path, tracker=tracker)
@@ -1468,16 +1498,17 @@ def init(
# Agent folder security notice # Agent folder security notice
agent_config = AGENT_CONFIG.get(selected_ai) agent_config = AGENT_CONFIG.get(selected_ai)
if agent_config: if agent_config:
agent_folder = agent_config["folder"] agent_folder = ai_commands_dir if selected_ai == "generic" else agent_config["folder"]
security_notice = Panel( if agent_folder:
f"Some agents may store credentials, auth tokens, or other identifying and private artifacts in the agent folder within your project.\n" security_notice = Panel(
f"Consider adding [cyan]{agent_folder}[/cyan] (or parts of it) to [cyan].gitignore[/cyan] to prevent accidental credential leakage.", f"Some agents may store credentials, auth tokens, or other identifying and private artifacts in the agent folder within your project.\n"
title="[yellow]Agent Folder Security[/yellow]", f"Consider adding [cyan]{agent_folder}[/cyan] (or parts of it) to [cyan].gitignore[/cyan] to prevent accidental credential leakage.",
border_style="yellow", title="[yellow]Agent Folder Security[/yellow]",
padding=(1, 2) border_style="yellow",
) padding=(1, 2)
console.print() )
console.print(security_notice) console.print()
console.print(security_notice)
steps_lines = [] steps_lines = []
if not here: if not here:
@@ -1535,6 +1566,8 @@ def check():
agent_results = {} agent_results = {}
for agent_key, agent_config in AGENT_CONFIG.items(): for agent_key, agent_config in AGENT_CONFIG.items():
if agent_key == "generic":
continue # Generic is not a real agent to check
agent_name = agent_config["name"] agent_name = agent_config["name"]
requires_cli = agent_config["requires_cli"] requires_cli = agent_config["requires_cli"]

View File

@@ -647,7 +647,7 @@ class CommandRegistrar:
"args": "$ARGUMENTS", "args": "$ARGUMENTS",
"extension": ".md" "extension": ".md"
}, },
"qoder": { "qodercli": {
"dir": ".qoder/commands", "dir": ".qoder/commands",
"format": "markdown", "format": "markdown",
"args": "$ARGUMENTS", "args": "$ARGUMENTS",

View File

@@ -380,7 +380,7 @@ class TestInstallAiSkills:
# .toml commands should be untouched # .toml commands should be untouched
assert (cmds_dir / "speckit.specify.toml").exists() assert (cmds_dir / "speckit.specify.toml").exists()
@pytest.mark.parametrize("agent_key", list(AGENT_CONFIG.keys())) @pytest.mark.parametrize("agent_key", [k for k in AGENT_CONFIG.keys() if k != "generic"])
def test_skills_install_for_all_agents(self, temp_dir, agent_key): def test_skills_install_for_all_agents(self, temp_dir, agent_key):
"""install_ai_skills should produce skills for every configured agent.""" """install_ai_skills should produce skills for every configured agent."""
proj = temp_dir / f"proj-{agent_key}" proj = temp_dir / f"proj-{agent_key}"