From 5a2c4aadace6856a6f7f79c81535f3ed0ab8c285 Mon Sep 17 00:00:00 2001 From: mrGreazly Date: Sat, 14 Mar 2026 13:43:03 +0300 Subject: [PATCH 1/3] feat(ai): add native support for Pi coding agent by pi+gpt 5.4 --- .devcontainer/post-create.sh | 4 + .../scripts/create-github-release.sh | 2 + .../scripts/create-release-packages.ps1 | 8 +- .../scripts/create-release-packages.sh | 7 +- AGENTS.md | 10 ++- README.md | 10 ++- docs/installation.md | 3 +- docs/upgrade.md | 10 ++- scripts/bash/update-agent-context.sh | 13 ++-- scripts/powershell/update-agent-context.ps1 | 9 ++- src/specify_cli/__init__.py | 7 ++ src/specify_cli/agents.py | 6 ++ tests/test_agent_config_consistency.py | 78 +++++++++++++++++++ tests/test_ai_skills.py | 26 +++++++ tests/test_extensions.py | 9 +++ 15 files changed, 180 insertions(+), 22 deletions(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index d7d3da5884..ad85dd3a77 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 Pi Coding Agent..." +run_command "npm install -g @mariozechner/pi-coding-agent@latest" +echo "✅ Done" + echo -e "\n🤖 Installing Kiro CLI..." # https://kiro.dev/docs/cli/ KIRO_INSTALLER_URL="https://kiro.dev/install.sh" diff --git a/.github/workflows/scripts/create-github-release.sh b/.github/workflows/scripts/create-github-release.sh index 864e0011ba..2813bc1431 100755 --- a/.github/workflows/scripts/create-github-release.sh +++ b/.github/workflows/scripts/create-github-release.sh @@ -58,6 +58,8 @@ gh release create "$VERSION" \ .genreleases/spec-kit-template-vibe-ps-"$VERSION".zip \ .genreleases/spec-kit-template-kimi-sh-"$VERSION".zip \ .genreleases/spec-kit-template-kimi-ps-"$VERSION".zip \ + .genreleases/spec-kit-template-pi-sh-"$VERSION".zip \ + .genreleases/spec-kit-template-pi-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 60ad3da97c..bd75ecd56a 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, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, generic + Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, pi, generic .PARAMETER Scripts Comma or space separated subset of script types to build (default: both) @@ -454,6 +454,10 @@ function Build-Variant { New-Item -ItemType Directory -Force -Path $skillsDir | Out-Null New-KimiSkills -SkillsDir $skillsDir -ScriptVariant $Script } + 'pi' { + $cmdDir = Join-Path $baseDir ".pi/prompts" + Generate-Commands -Agent 'pi' -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 @@ -470,7 +474,7 @@ function Build-Variant { } # Define all agents and scripts -$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'generic') +$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'pi', '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 620da02337..e3a660b99f 100755 --- a/.github/workflows/scripts/create-release-packages.sh +++ b/.github/workflows/scripts/create-release-packages.sh @@ -6,7 +6,7 @@ set -euo pipefail # Usage: .github/workflows/scripts/create-release-packages.sh # Version argument should include leading 'v'. # 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 kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi generic (default: all) +# AGENTS : space or comma separated subset of: claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi pi generic (default: all) # SCRIPTS : space or comma separated subset of: sh ps (default: both) # Examples: # AGENTS=claude SCRIPTS=sh $0 v0.2.0 @@ -291,6 +291,9 @@ build_variant() { kimi) mkdir -p "$base_dir/.kimi/skills" create_kimi_skills "$base_dir/.kimi/skills" "$script" ;; + pi) + mkdir -p "$base_dir/.pi/prompts" + generate_commands pi md "\$ARGUMENTS" "$base_dir/.pi/prompts" "$script" ;; generic) mkdir -p "$base_dir/.speckit/commands" generate_commands generic md "\$ARGUMENTS" "$base_dir/.speckit/commands" "$script" ;; @@ -300,7 +303,7 @@ build_variant() { } # Determine agent list -ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi generic) +ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi pi generic) ALL_SCRIPTS=(sh ps) norm_list() { diff --git a/AGENTS.md b/AGENTS.md index 8f0742eb8f..7ca4c63dd6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -45,6 +45,7 @@ Specify supports multiple AI agents by generating agent-specific command files a | **SHAI** | `.shai/commands/` | Markdown | `shai` | SHAI CLI | | **Tabnine CLI** | `.tabnine/agent/commands/` | TOML | `tabnine` | Tabnine CLI | | **Kimi Code** | `.kimi/skills/` | Markdown | `kimi` | Kimi Code CLI (Moonshot AI) | +| **Pi Coding Agent** | `.pi/prompts/` | Markdown | `pi` | Pi terminal coding agent | | **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 | @@ -84,7 +85,7 @@ This eliminates the need for special-case mappings throughout the codebase. - `folder`: Directory where agent-specific files are stored (relative to project root) - `commands_subdir`: Subdirectory name within the agent folder where command/prompt files are stored (default: `"commands"`) - Most agents use `"commands"` (e.g., `.claude/commands/`) - - Some agents use alternative names: `"agents"` (copilot), `"workflows"` (windsurf, kilocode), `"prompts"` (codex, kiro-cli), `"command"` (opencode - singular) + - Some agents use alternative names: `"agents"` (copilot), `"workflows"` (windsurf, kilocode), `"prompts"` (codex, kiro-cli, pi), `"command"` (opencode - singular) - This field enables `--ai-skills` to locate command templates correctly for skill generation - `install_url`: Installation documentation URL (set to `None` for IDE-based agents) - `requires_cli`: Whether the agent requires a CLI tool check during initialization @@ -322,6 +323,7 @@ Require a command-line tool to be installed: - **SHAI**: `shai` CLI - **Tabnine CLI**: `tabnine` CLI - **Kimi Code**: `kimi` CLI +- **Pi Coding Agent**: `pi` CLI ### IDE-Based Agents @@ -335,7 +337,7 @@ Work within integrated development environments: ### Markdown Format -Used by: Claude, Cursor, opencode, Windsurf, Kiro CLI, Amp, SHAI, IBM Bob, Kimi Code, Qwen +Used by: Claude, Cursor, opencode, Windsurf, Kiro CLI, Amp, SHAI, IBM Bob, Kimi Code, Qwen, Pi **Standard format:** @@ -373,6 +375,10 @@ Command content with {SCRIPT} and {{args}} placeholders. ## Directory Conventions - **CLI agents**: Usually `./commands/` +- **Common prompt-based exceptions**: + - Codex: `.codex/prompts/` + - Kiro CLI: `.kiro/prompts/` + - Pi: `.pi/prompts/` - **IDE agents**: Follow IDE-specific patterns: - Copilot: `.github/agents/` - Cursor: `.cursor/commands/` diff --git a/README.md b/README.md index 006d552270..56425ec785 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,7 @@ See Spec-Driven Development in action across different scenarios with these comm | [Jules](https://jules.google.com/) | ✅ | | | [Kilo Code](https://github.com/Kilo-Org/kilocode) | ✅ | | | [opencode](https://opencode.ai/) | ✅ | | +| [Pi Coding Agent](https://pi.dev) | ✅ | Uses project-level `.pi/prompts/` templates plus root `AGENTS.md` context files | | [Qwen Code](https://github.com/QwenLM/qwen-code) | ✅ | | | [Roo Code](https://roocode.com/) | ✅ | | | [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | | @@ -195,14 +196,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`, `kiro-cli`, `shai`, `qodercli`, `vibe`, `kimi`) | +| `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `qwen`, `opencode`, `codex`, `kiro-cli`, `shai`, `qodercli`, `vibe`, `kimi`, `pi`) | ### `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`, `kiro-cli` (`kiro` alias), `agy`, `bob`, `qodercli`, `vibe`, `kimi`, 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`, `kiro-cli` (`kiro` alias), `agy`, `bob`, `qodercli`, `vibe`, `kimi`, `pi`, 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 | @@ -247,6 +248,9 @@ specify init my-project --ai vibe # Initialize with IBM Bob support specify init my-project --ai bob +# Initialize with Pi Coding Agent support +specify init my-project --ai pi + # Initialize with Antigravity support specify init my-project --ai agy --ai-skills @@ -424,7 +428,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, Tabnine CLI, Kiro CLI, or Mistral Vibe installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command: +The CLI will check if you have Claude Code, Gemini CLI, Cursor CLI, Qwen CLI, opencode, Codex CLI, Qoder CLI, Tabnine CLI, Kiro CLI, Pi, or Mistral Vibe installed. If you do not, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command: ```bash specify init --ai claude --ignore-agent-tools diff --git a/docs/installation.md b/docs/installation.md index 6daff24315..7cb7b1ff9b 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -3,7 +3,7 @@ ## Prerequisites - **Linux/macOS** (or Windows; PowerShell scripts now supported without WSL) -- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Codebuddy CLI](https://www.codebuddy.ai/cli) or [Gemini CLI](https://github.com/google-gemini/gemini-cli) +- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Codebuddy CLI](https://www.codebuddy.ai/cli), [Gemini CLI](https://github.com/google-gemini/gemini-cli), or [Pi Coding Agent](https://pi.dev) - [uv](https://docs.astral.sh/uv/) for package management - [Python 3.11+](https://www.python.org/downloads/) - [Git](https://git-scm.com/downloads) @@ -35,6 +35,7 @@ uvx --from git+https://github.com/github/spec-kit.git specify init --ai gemini uvx --from git+https://github.com/github/spec-kit.git specify init --ai copilot uvx --from git+https://github.com/github/spec-kit.git specify init --ai codebuddy +uvx --from git+https://github.com/github/spec-kit.git specify init --ai pi ``` ### Specify Script Type (Shell vs PowerShell) diff --git a/docs/upgrade.md b/docs/upgrade.md index 676e5131f0..74bf6192c0 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -289,8 +289,9 @@ This tells Spec Kit which feature directory to use when creating specs, plans, a ```bash ls -la .claude/commands/ # Claude Code - ls -la .gemini/commands/ # Gemini - ls -la .cursor/commands/ # Cursor + ls -la .gemini/commands/ # Gemini + ls -la .cursor/commands/ # Cursor + ls -la .pi/prompts/ # Pi Coding Agent ``` 3. **Check agent-specific setup:** @@ -398,7 +399,7 @@ The `specify` CLI tool is used for: - **Upgrades:** `specify init --here --force` to update templates and commands - **Diagnostics:** `specify check` to verify tool installation -Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/speckit.plan`, etc.) are **permanently installed** in your project's agent folder (`.claude/`, `.github/prompts/`, etc.). Your AI assistant reads these command files directly—no need to run `specify` again. +Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/speckit.plan`, etc.) are **permanently installed** in your project's agent folder (`.claude/`, `.github/prompts/`, `.pi/prompts/`, etc.). Your AI assistant reads these command files directly—no need to run `specify` again. **If your agent isn't recognizing slash commands:** @@ -410,6 +411,9 @@ Once you've run `specify init`, the slash commands (like `/speckit.specify`, `/s # For Claude ls -la .claude/commands/ + + # For Pi + ls -la .pi/prompts/ ``` 2. **Restart your IDE/editor completely** (not just reload window) diff --git a/scripts/bash/update-agent-context.sh b/scripts/bash/update-agent-context.sh index e0f2854846..2b79cec2f9 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, Tabnine CLI, Kiro CLI, Mistral Vibe, Kimi Code, Antigravity or Generic +# - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, Roo Code, CodeBuddy CLI, Qoder CLI, Amp, SHAI, Tabnine CLI, Kiro CLI, Mistral Vibe, Kimi Code, Pi Coding Agent, Antigravity or Generic # - 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|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|generic +# Agent types: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|pi|generic # Leave empty to update all existing agent files set -e @@ -73,7 +73,7 @@ AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md" ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md" CODEBUDDY_FILE="$REPO_ROOT/CODEBUDDY.md" QODER_FILE="$REPO_ROOT/QODER.md" -# AMP, Kiro CLI, and IBM Bob all share AGENTS.md — use AGENTS_FILE to avoid +# Amp, Kiro CLI, IBM Bob, and Pi all share AGENTS.md — use AGENTS_FILE to avoid # updating the same file multiple times. AMP_FILE="$AGENTS_FILE" SHAI_FILE="$REPO_ROOT/SHAI.md" @@ -675,12 +675,15 @@ update_specific_agent() { kimi) update_agent_file "$KIMI_FILE" "Kimi Code" || return 1 ;; + pi) + update_agent_file "$AGENTS_FILE" "Pi Coding Agent" || return 1 + ;; 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|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|generic" + log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|pi|generic" exit 1 ;; esac @@ -754,7 +757,7 @@ print_summary() { fi echo - log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|generic]" + log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|pi|generic]" } #============================================================================== diff --git a/scripts/powershell/update-agent-context.ps1 b/scripts/powershell/update-agent-context.ps1 index 30e1e0e693..af86fdd0d0 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, tabnine, kiro-cli, agy, bob, vibe, qodercli, kimi, generic) + 5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, tabnine, kiro-cli, agy, bob, vibe, qodercli, kimi, pi, generic) .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','tabnine','kiro-cli','agy','bob','qodercli','vibe','kimi','generic')] + [ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','tabnine','kiro-cli','agy','bob','qodercli','vibe','kimi','pi','generic')] [string]$AgentType ) @@ -408,8 +408,9 @@ function Update-SpecificAgent { 'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' } 'vibe' { Update-AgentFile -TargetFile $VIBE_FILE -AgentName 'Mistral Vibe' } 'kimi' { Update-AgentFile -TargetFile $KIMI_FILE -AgentName 'Kimi Code' } + 'pi' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'Pi Coding Agent' } '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|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|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|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|pi|generic'; return $false } } } @@ -449,7 +450,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|tabnine|kiro-cli|agy|bob|vibe|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|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|pi|generic]' } function Main { diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index a45535aee4..c0d57c6a17 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -272,6 +272,13 @@ def _format_rate_limit_error(status_code: int, headers: httpx.Headers, url: str) "install_url": "https://code.kimi.com/", "requires_cli": True, }, + "pi": { + "name": "Pi Coding Agent", + "folder": ".pi/", + "commands_subdir": "prompts", + "install_url": "https://www.npmjs.com/package/@mariozechner/pi-coding-agent", + "requires_cli": True, + }, "generic": { "name": "Generic (bring your own agent)", "folder": None, # Set dynamically via --ai-commands-dir diff --git a/src/specify_cli/agents.py b/src/specify_cli/agents.py index 9927daee8c..dc130e8db4 100644 --- a/src/specify_cli/agents.py +++ b/src/specify_cli/agents.py @@ -106,6 +106,12 @@ class CommandRegistrar: "args": "$ARGUMENTS", "extension": ".md" }, + "pi": { + "dir": ".pi/prompts", + "format": "markdown", + "args": "$ARGUMENTS", + "extension": ".md" + }, "amp": { "dir": ".agents/commands", "format": "markdown", diff --git a/tests/test_agent_config_consistency.py b/tests/test_agent_config_consistency.py index 6831fad360..5e63b12596 100644 --- a/tests/test_agent_config_consistency.py +++ b/tests/test_agent_config_consistency.py @@ -233,3 +233,81 @@ def test_kimi_in_github_release_output(self): def test_ai_help_includes_kimi(self): """CLI help text for --ai should include kimi.""" assert "kimi" in AI_ASSISTANT_HELP + + # --- Pi Coding Agent consistency checks --- + + def test_pi_in_agent_config(self): + """AGENT_CONFIG should include pi with correct folder and commands_subdir.""" + assert "pi" in AGENT_CONFIG + assert AGENT_CONFIG["pi"]["folder"] == ".pi/" + assert AGENT_CONFIG["pi"]["commands_subdir"] == "prompts" + assert AGENT_CONFIG["pi"]["requires_cli"] is True + assert AGENT_CONFIG["pi"]["install_url"] is not None + + def test_pi_in_extension_registrar(self): + """Extension command registrar should include pi using .pi/prompts.""" + cfg = CommandRegistrar.AGENT_CONFIGS + + assert "pi" in cfg + pi_cfg = cfg["pi"] + assert pi_cfg["dir"] == ".pi/prompts" + assert pi_cfg["format"] == "markdown" + assert pi_cfg["args"] == "$ARGUMENTS" + assert pi_cfg["extension"] == ".md" + + def test_pi_in_release_agent_lists(self): + """Bash and PowerShell release scripts should include pi in agent lists.""" + sh_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.sh").read_text(encoding="utf-8") + ps_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.ps1").read_text(encoding="utf-8") + + sh_match = re.search(r"ALL_AGENTS=\(([^)]*)\)", sh_text) + assert sh_match is not None + sh_agents = sh_match.group(1).split() + + ps_match = re.search(r"\$AllAgents = @\(([^)]*)\)", ps_text) + assert ps_match is not None + ps_agents = re.findall(r"'([^']+)'", ps_match.group(1)) + + assert "pi" in sh_agents + assert "pi" in ps_agents + + def test_release_scripts_generate_pi_prompt_templates(self): + """Release scripts should generate Markdown prompt templates for pi in .pi/prompts.""" + sh_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.sh").read_text(encoding="utf-8") + ps_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-release-packages.ps1").read_text(encoding="utf-8") + + assert ".pi/prompts" in sh_text + assert ".pi/prompts" in ps_text + assert re.search(r"pi\)\s*\n.*?\.pi/prompts", sh_text, re.S) is not None + assert re.search(r"'pi'\s*\{.*?\.pi/prompts", ps_text, re.S) is not None + + def test_pi_in_powershell_validate_set(self): + """PowerShell update-agent-context script should include 'pi' in ValidateSet.""" + ps_text = (REPO_ROOT / "scripts" / "powershell" / "update-agent-context.ps1").read_text(encoding="utf-8") + + validate_set_match = re.search(r"\[ValidateSet\(([^)]*)\)\]", ps_text) + assert validate_set_match is not None + validate_set_values = re.findall(r"'([^']+)'", validate_set_match.group(1)) + + assert "pi" in validate_set_values + + def test_pi_in_github_release_output(self): + """GitHub release script should include pi template packages.""" + gh_release_text = (REPO_ROOT / ".github" / "workflows" / "scripts" / "create-github-release.sh").read_text(encoding="utf-8") + + assert "spec-kit-template-pi-sh-" in gh_release_text + assert "spec-kit-template-pi-ps-" in gh_release_text + + def test_agent_context_scripts_include_pi(self): + """Agent context scripts should support pi agent type.""" + bash_text = (REPO_ROOT / "scripts" / "bash" / "update-agent-context.sh").read_text(encoding="utf-8") + pwsh_text = (REPO_ROOT / "scripts" / "powershell" / "update-agent-context.ps1").read_text(encoding="utf-8") + + assert "pi" in bash_text + assert "Pi Coding Agent" in bash_text + assert "pi" in pwsh_text + assert "Pi Coding Agent" in pwsh_text + + def test_ai_help_includes_pi(self): + """CLI help text for --ai should include pi.""" + assert "pi" in AI_ASSISTANT_HELP diff --git a/tests/test_ai_skills.py b/tests/test_ai_skills.py index 45d45cc4a8..ff34e3d137 100644 --- a/tests/test_ai_skills.py +++ b/tests/test_ai_skills.py @@ -182,6 +182,11 @@ def test_kiro_cli_skills_dir(self, project_dir): result = _get_skills_dir(project_dir, "kiro-cli") assert result == project_dir / ".kiro" / "skills" + def test_pi_skills_dir(self, project_dir): + """Pi should use .pi/skills/.""" + result = _get_skills_dir(project_dir, "pi") + assert result == project_dir / ".pi" / "skills" + def test_unknown_agent_uses_default(self, project_dir): """Unknown agents should fall back to DEFAULT_SKILLS_DIR.""" result = _get_skills_dir(project_dir, "nonexistent-agent") @@ -422,6 +427,27 @@ def test_qwen_md_commands_dir_installs_skills(self, project_dir): assert (cmds_dir / "speckit.specify.md").exists() assert (cmds_dir / "speckit.plan.md").exists() + def test_pi_prompt_dir_installs_skills(self, project_dir): + """Pi should install skills directly from .pi/prompts/.""" + prompts_dir = project_dir / ".pi" / "prompts" + prompts_dir.mkdir(parents=True) + (prompts_dir / "speckit.specify.md").write_text( + "---\ndescription: Create or update the feature specification.\n---\n\n# Specify\n\nBody.\n" + ) + (prompts_dir / "speckit.plan.md").write_text( + "---\ndescription: Generate implementation plan.\n---\n\n# Plan\n\nBody.\n" + ) + + result = install_ai_skills(project_dir, "pi") + + assert result is True + skills_dir = project_dir / ".pi" / "skills" + assert skills_dir.exists() + skill_dirs = [d.name for d in skills_dir.iterdir() if d.is_dir()] + assert len(skill_dirs) >= 1 + assert (prompts_dir / "speckit.specify.md").exists() + assert (prompts_dir / "speckit.plan.md").exists() + @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): """install_ai_skills should produce skills for every configured agent.""" diff --git a/tests/test_extensions.py b/tests/test_extensions.py index 6299abbb8b..52cf6ae956 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -541,6 +541,15 @@ def test_codex_agent_config_present(self): assert "codex" in CommandRegistrar.AGENT_CONFIGS assert CommandRegistrar.AGENT_CONFIGS["codex"]["dir"] == ".codex/prompts" + def test_pi_agent_config_present(self): + """Pi should be mapped to .pi/prompts.""" + assert "pi" in CommandRegistrar.AGENT_CONFIGS + cfg = CommandRegistrar.AGENT_CONFIGS["pi"] + assert cfg["dir"] == ".pi/prompts" + assert cfg["format"] == "markdown" + assert cfg["args"] == "$ARGUMENTS" + assert cfg["extension"] == ".md" + def test_qwen_agent_config_is_markdown(self): """Qwen should use Markdown format with $ARGUMENTS (not TOML).""" assert "qwen" in CommandRegistrar.AGENT_CONFIGS From c7f1891366cf3c38154b9eb7c0f90d2487e2d153 Mon Sep 17 00:00:00 2001 From: mrGreazly Date: Sat, 14 Mar 2026 17:20:34 +0300 Subject: [PATCH 2/3] docs(pi): document MCP limitations for Pi agent --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56425ec785..5293bb052b 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ See Spec-Driven Development in action across different scenarios with these comm | [Jules](https://jules.google.com/) | ✅ | | | [Kilo Code](https://github.com/Kilo-Org/kilocode) | ✅ | | | [opencode](https://opencode.ai/) | ✅ | | -| [Pi Coding Agent](https://pi.dev) | ✅ | Uses project-level `.pi/prompts/` templates plus root `AGENTS.md` context files | +| [Pi Coding Agent](https://pi.dev) | ✅ | pi doesn't have MCP support OOTB so `taskstoissues` will not work as intended. MCP support can be added via [extentions](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent#extensions)| | [Qwen Code](https://github.com/QwenLM/qwen-code) | ✅ | | | [Roo Code](https://roocode.com/) | ✅ | | | [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | | From dd9d85c44067d6e5dc09dd48458e46067fa76f10 Mon Sep 17 00:00:00 2001 From: mrGreazly Date: Sat, 14 Mar 2026 18:10:48 +0300 Subject: [PATCH 3/3] fix: unitended kimi agent mention added to update-agent-context.ps1 --- scripts/powershell/update-agent-context.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/powershell/update-agent-context.ps1 b/scripts/powershell/update-agent-context.ps1 index af86fdd0d0..aba0017b5a 100644 --- a/scripts/powershell/update-agent-context.ps1 +++ b/scripts/powershell/update-agent-context.ps1 @@ -450,7 +450,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|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|pi|generic]' + Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|pi|generic]' } function Main {