diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index caf184c1c6..71bb0fa2eb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -53,7 +53,8 @@ // Amazon Developer Q "AmazonWebServices.amazon-q-vscode", // Claude Code - "anthropic.claude-code" + "anthropic.claude-code", + "lee2py.aider-composer" ], "settings": { "debug.javascript.autoAttachFilter": "disabled", // fix running commands in integrated terminal diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 9608a28a3d..38d3f6a8dc 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -51,6 +51,10 @@ echo -e "\nšŸ¤– Installing OpenCode CLI..." run_command "npm install -g opencode-ai@latest" echo "āœ… Done" +echo -e "\nšŸ¤– Installing Aider CLI..." +run_command "pipx install aider-chat" +echo "āœ… Done" + echo -e "\nšŸ¤– Installing Amazon Q CLI..." # šŸ‘‰šŸ¾ https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-verify-download.html diff --git a/.github/workflows/scripts/create-github-release.sh b/.github/workflows/scripts/create-github-release.sh index 29f5024f8c..dd841cf285 100644 --- a/.github/workflows/scripts/create-github-release.sh +++ b/.github/workflows/scripts/create-github-release.sh @@ -52,6 +52,8 @@ gh release create "$VERSION" \ .genreleases/spec-kit-template-agy-ps-"$VERSION".zip \ .genreleases/spec-kit-template-bob-sh-"$VERSION".zip \ .genreleases/spec-kit-template-bob-ps-"$VERSION".zip \ + .genreleases/spec-kit-template-aider-sh-"$VERSION".zip \ + .genreleases/spec-kit-template-aider-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" \ diff --git a/.github/workflows/scripts/create-release-packages.ps1 b/.github/workflows/scripts/create-release-packages.ps1 index ed04d9cd3f..c02074d9ca 100644 --- a/.github/workflows/scripts/create-release-packages.ps1 +++ b/.github/workflows/scripts/create-release-packages.ps1 @@ -14,7 +14,7 @@ .PARAMETER Agents 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, qodercli, shai, agy, generic + Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, codex, kilocode, auggie, roo, codebuddy, amp, q, bob, qodercli, shai, agy, aider, generic .PARAMETER Scripts Comma or space separated subset of script types to build (default: both) @@ -347,6 +347,10 @@ function Build-Variant { $cmdDir = Join-Path $baseDir ".qoder/commands" Generate-Commands -Agent 'qodercli' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script } + 'aider' { + $cmdDir = Join-Path $baseDir ".aider/commands" + Generate-Commands -Agent 'aider' -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 @@ -360,7 +364,7 @@ function Build-Variant { } # Define all agents and scripts -$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'q', 'bob', 'qodercli', 'shai', 'agy', 'generic') +$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'q', 'bob', 'qodercli', 'shai', 'agy', 'aider', 'generic') $AllScripts = @('sh', 'ps') function Normalize-List { diff --git a/.github/workflows/scripts/create-release-packages.sh b/.github/workflows/scripts/create-release-packages.sh index 1b2ced3ea3..f3d60c3b7f 100755 --- a/.github/workflows/scripts/create-release-packages.sh +++ b/.github/workflows/scripts/create-release-packages.sh @@ -221,6 +221,9 @@ build_variant() { bob) mkdir -p "$base_dir/.bob/commands" generate_commands bob md "\$ARGUMENTS" "$base_dir/.bob/commands" "$script" ;; + aider) + mkdir -p "$base_dir/.aider/commands" + generate_commands aider md "\$ARGUMENTS" "$base_dir/.aider/commands" "$script" ;; generic) mkdir -p "$base_dir/.speckit/commands" generate_commands generic md "\$ARGUMENTS" "$base_dir/.speckit/commands" "$script" ;; @@ -230,7 +233,7 @@ build_variant() { } # Determine agent list -ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q agy bob qodercli generic) +ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q agy bob qodercli aider generic) ALL_SCRIPTS=(sh ps) norm_list() { diff --git a/.gitignore b/.gitignore index 1688c8299e..a76723bfbf 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,11 @@ docs/dev .specify/extensions/.cache/ .specify/extensions/.backup/ .specify/extensions/*/local-config.yml + +# Custom +.python-version +.aider.* + +.mypy_cache/ +.pytest_cache/ +.coverage diff --git a/AGENTS.md b/AGENTS.md index d8dc0f08f7..0096be353e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,6 +48,7 @@ Specify supports multiple AI agents by generating agent-specific command files a | **Amp** | `.agents/commands/` | Markdown | `amp` | Amp CLI | | **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI | | **IBM Bob** | `.bob/commands/` | Markdown | N/A (IDE-based) | IBM Bob IDE | +| **Aider** | `.aider/commands/` | Markdown | `aider` | Aider CLI | | **Generic** | User-specified via `--ai-commands-dir` | Markdown | N/A | Bring your own agent | ### Step-by-Step Integration Guide @@ -322,6 +323,7 @@ Require a command-line tool to be installed: - **Qoder CLI**: `qodercli` CLI - **Amp**: `amp` CLI - **SHAI**: `shai` CLI +- **Aider CLI**: `aider` CLI ### IDE-Based Agents diff --git a/README.md b/README.md index 85a9a8f1e9..520e9a4926 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.c | Agent | Support | Notes | | ------------------------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | [Qoder CLI](https://qoder.com/cli) | āœ… | | +| [Aider CLI](https://aider.chat/) | āœ… | | | [Amazon Q Developer CLI](https://aws.amazon.com/developer/learning/q-developer-cli/) | āš ļø | Amazon Q Developer CLI [does not support](https://github.com/aws/amazon-q-developer-cli/issues/3064) custom arguments for slash commands. | | [Amp](https://ampcode.com/) | āœ… | | | [Auggie CLI](https://docs.augmentcode.com/cli/overview) | āœ… | | @@ -173,14 +174,14 @@ The `specify` command supports the following options: | Command | Description | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `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`, `qodercli`) | +| `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `qwen`, `opencode`, `codex`, `shai`, `qodercli`, `aider`) | ### `specify init` Arguments & Options | Argument/Option | Type | Description | | ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `` | 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`, `qodercli`, or `generic` (requires `--ai-commands-dir`) | +| `--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`, `aider`, 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) | | `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code | @@ -219,6 +220,9 @@ specify init my-project --ai shai # Initialize with IBM Bob support specify init my-project --ai bob +# Initialize with Aider support +specify init my-project --ai aider + # Initialize with an unsupported agent (generic / bring your own agent) specify init my-project --ai generic --ai-commands-dir .myagent/commands/ @@ -393,7 +397,7 @@ specify init . --force --ai claude specify init --here --force --ai claude ``` -The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, or Amazon Q Developer CLI installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command: +The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Aider CLI, or Amazon Q Developer CLI installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command: ```bash specify init --ai claude --ignore-agent-tools diff --git a/scripts/bash/update-agent-context.sh b/scripts/bash/update-agent-context.sh index a33ea5cdee..af2cad8293 100644 --- a/scripts/bash/update-agent-context.sh +++ b/scripts/bash/update-agent-context.sh @@ -30,12 +30,12 @@ # # 5. Multi-Agent Support # - Handles agent-specific file paths and naming conventions -# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Amazon Q Developer CLI, or Antigravity +# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Aider CLI, Amazon Q Developer CLI, or Antigravity # - Can update single agents or all existing agent files # - Creates default Claude file if no agent files exist # # 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|qodercli +# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qoder|aidercli # Leave empty to update all existing agent files set -e @@ -76,6 +76,7 @@ SHAI_FILE="$REPO_ROOT/SHAI.md" Q_FILE="$REPO_ROOT/AGENTS.md" AGY_FILE="$REPO_ROOT/.agent/rules/specify-rules.md" BOB_FILE="$REPO_ROOT/AGENTS.md" +AIDER_FILE="$REPO_ROOT/.aider/rules/specify-rules.md" # Template file TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md" @@ -637,12 +638,15 @@ update_specific_agent() { bob) update_agent_file "$BOB_FILE" "IBM Bob" ;; + aider) + update_agent_file "$AIDER_FILE" "Aider CLI" + ;; 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 "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|generic" + log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|aider|generic" exit 1 ;; esac @@ -730,6 +734,11 @@ update_all_existing_agents() { update_agent_file "$BOB_FILE" "IBM Bob" found_agent=true fi + + if [[ -f "$AIDER_FILE" ]]; then + update_agent_file "$AIDER_FILE" "Aider CLI" + found_agent=true + fi # If no agent files exist, create a default Claude file if [[ "$found_agent" == false ]]; then @@ -755,7 +764,7 @@ print_summary() { echo - log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli]" + log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|agy|bob|qodercli|aider]" } #============================================================================== diff --git a/scripts/powershell/update-agent-context.ps1 b/scripts/powershell/update-agent-context.ps1 index 61718e96ce..bddcdd68e9 100644 --- a/scripts/powershell/update-agent-context.ps1 +++ b/scripts/powershell/update-agent-context.ps1 @@ -9,7 +9,7 @@ Mirrors the behavior of scripts/bash/update-agent-context.sh: 2. Plan Data Extraction 3. Agent File Management (create from template or update existing) 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, qodercli) + 5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, q, agy, bob, aider, or qodercli) .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). @@ -25,7 +25,7 @@ Relies on common helper functions in common.ps1 #> param( [Parameter(Position=0)] - [ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','q','agy','bob','qodercli','generic')] + [ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','q','agy','bob','qodercli','aider','generic')] [string]$AgentType ) @@ -61,6 +61,7 @@ $SHAI_FILE = Join-Path $REPO_ROOT 'SHAI.md' $Q_FILE = Join-Path $REPO_ROOT 'AGENTS.md' $AGY_FILE = Join-Path $REPO_ROOT '.agent/rules/specify-rules.md' $BOB_FILE = Join-Path $REPO_ROOT 'AGENTS.md' +$AIDER_FILE = Join-Path $REPO_ROOT '.aider/rules/specify-rules.md' $TEMPLATE_FILE = Join-Path $REPO_ROOT '.specify/templates/agent-file-template.md' @@ -390,8 +391,9 @@ function Update-SpecificAgent { 'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' } 'agy' { Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity' } 'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' } + 'aider' { Update-AgentFile -TargetFile $AIDER_FILE -AgentName 'Aider CLI' } '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 } + 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|aider|generic'; return $false } } } @@ -414,6 +416,7 @@ function Update-AllExistingAgents { if (Test-Path $Q_FILE) { if (-not (Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI')) { $ok = $false }; $found = $true } if (Test-Path $AGY_FILE) { if (-not (Update-AgentFile -TargetFile $AGY_FILE -AgentName 'Antigravity')) { $ok = $false }; $found = $true } if (Test-Path $BOB_FILE) { if (-not (Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob')) { $ok = $false }; $found = $true } + if (Test-Path $AIDER_FILE) { if (-not (Update-AgentFile -TargetFile $AIDER_FILE -AgentName 'Aider CLI')) { $ok = $false }; $found = $true } if (-not $found) { Write-Info 'No existing agent files found, creating default Claude file...' if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false } @@ -428,7 +431,7 @@ function Print-Summary { if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" } if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" } 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|qodercli|generic]' + 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|aider|generic]' } function Main { diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index 5651ac7226..54e1ee47e2 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -251,6 +251,12 @@ def _format_rate_limit_error(status_code: int, headers: httpx.Headers, url: str) "install_url": None, # IDE-based "requires_cli": False, }, + "aider": { + "name": "Aider", + "folder": ".aider/", + "install_url": "https://aider.chat", + "requires_cli": True, + }, "generic": { "name": "Generic (bring your own agent)", "folder": None, # Set dynamically via --ai-commands-dir @@ -667,8 +673,8 @@ def deep_merge(base: dict, update: dict) -> dict: return merged def download_template_from_github(ai_assistant: str, download_dir: Path, *, script_type: str = "sh", verbose: bool = True, show_progress: bool = True, client: httpx.Client = None, debug: bool = False, github_token: str = None) -> Tuple[Path, dict]: - repo_owner = "github" - repo_name = "spec-kit" + repo_owner = "wolffy-au" + repo_name = "spec-kit-aider" if client is None: client = httpx.Client(verify=ssl_context) @@ -1214,7 +1220,7 @@ def install_ai_skills(project_path: Path, selected_ai: str, tracker: StepTracker @app.command() def init( 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, qodercli, or generic (requires --ai-commands-dir)"), + 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, aider, 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"), ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"), @@ -1656,8 +1662,8 @@ def version(): pass # Fetch latest template release version - repo_owner = "github" - repo_name = "spec-kit" + repo_owner = "wolffy-au" + repo_name = "spec-kit-aider" api_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest" template_version = "unknown" diff --git a/templates/commands/constitution.md b/templates/commands/constitution.md index 63d4f662ae..8d3908b0b6 100644 --- a/templates/commands/constitution.md +++ b/templates/commands/constitution.md @@ -4,6 +4,9 @@ handoffs: - label: Build Specification agent: speckit.specify prompt: Implement the feature specification based on the updated constitution. I want to build... +scripts: + sh: scripts/bash/check-prerequisites.sh --json + ps: scripts/powershell/check-prerequisites.ps1 -Json --- ## User Input