Files
github-spec-kit/AGENTS.md
Eric Rodriguez Suazo b8e7851234 feat: add Forgecode agent support (#2034)
* feat: add Forgecode (forge) agent support

- Add 'forgecode' to AGENT_CONFIGS in agents.py with .forge/commands
  directory, markdown format, and {{parameters}} argument placeholder
- Add 'forgecode' to AGENT_CONFIG in __init__.py with .forge/ folder,
  install URL, and requires_cli=True
- Add forgecode binary check in check_tool() mapping agent key
  'forgecode' to the actual 'forge' CLI binary
- Add forgecode case to build_variant() in create-release-packages.sh
  generating commands into .forge/commands/ with {{parameters}}
- Add forgecode to ALL_AGENTS in create-release-packages.sh

* fix: strip handoffs frontmatter and replace $ARGUMENTS for forgecode

The forgecode agent hangs when listing commands because the 'handoffs'
frontmatter field (a Claude Code-specific feature) contains 'send: true'
entries that forge tries to act on when indexing .forge/commands/ files.

Additionally, $ARGUMENTS in command bodies was never replaced with
{{parameters}}, so user input was not passed through to commands.

Python path (agents.py):
- Add strip_frontmatter_keys: [handoffs] to the forgecode AGENT_CONFIG
  entry so register_commands drops the key before rendering

Bash path (create-release-packages.sh):
- Add extra_strip_key parameter to generate_commands; pass 'handoffs'
  for the forgecode case in build_variant
- Use regex prefix match (~ "^"extra_key":") instead of exact
  equality to handle trailing whitespace after the YAML key
- Add sed replacement of $ARGUMENTS -> $arg_format in the body
  pipeline so {{parameters}} is substituted in forgecode command files

* feat: add name field injection for forgecode agent

Forgecode requires both 'name' and 'description' fields in command
frontmatter. This commit adds automatic injection of the 'name' field
during command generation for forgecode.

Changes:
- Python (agents.py): Add inject_name: True to forgecode config and
  implement name injection logic in register_commands
- Bash (create-release-packages.sh): Add post-processing step to inject
  name field into frontmatter after command generation

This complements the existing handoffs stripping fix (d83be82) to fully
support forgecode command requirements.

* test: update test_argument_token_format for forgecode special case

Forgecode uses {{parameters}} instead of the standard $ARGUMENTS
placeholder. Updated test to check for the correct placeholder format
for forgecode agent.

- Added special case handling for forgecode in test_argument_token_format
- Updated docstring to document forgecode's {{parameters}} format
- Test now passes for all 26 agents including forgecode

* docs: add forgecode to README documentation

Added forgecode agent to all relevant sections:
- Added to Supported AI Agents table
- Added to --ai option description
- Added to specify check command examples
- Added initialization example
- Added to CLI tools check list in detailed walkthrough

Forgecode is now fully documented alongside other supported agents.

* fix: show 'forge' binary name in user-facing messages for forgecode

Addresses Copilot PR feedback: Users should see the actual executable
name 'forge' in status and error messages, not the agent key 'forgecode'.

Changes:
- Added 'cli_binary' field to forgecode AGENT_CONFIG (set to 'forge')
- Updated check_tool() to accept optional display_key parameter
- Updated check_tool() to use cli_binary from AGENT_CONFIG when available
- Updated check() command to display cli_binary in StepTracker
- Updated init() error message to show cli_binary instead of agent key

UX improvements:
- 'specify check' now shows: '● forge (available/not found)'
- 'specify init --ai forgecode' error shows: 'forge not found'
  (instead of confusing 'forgecode not found')

This makes it clear to users that they need to install the 'forge'
binary, even though they selected the 'forgecode' agent.

* refactor: rename forgecode agent key to forge

Aligns with AGENTS.md design principle: "Use the actual CLI tool
name as the key, not a shortened version" (AGENTS.md:61-83).

The actual CLI executable is 'forge', so the AGENT_CONFIG key should
be 'forge' (not 'forgecode'). This follows the same pattern as other
agents like cursor-agent and kiro-cli.

Changes:
- Renamed AGENT_CONFIG key: "forgecode" → "forge"
- Removed cli_binary field (no longer needed)
- Simplified check_tool() - removed cli_binary lookup logic
- Simplified init() and check() - removed display_key mapping
- Updated all tests: test_forge_name_field_in_frontmatter
- Updated documentation: README.md

Code simplification:
- Removed 6 lines of workaround code
- Removed 1 function parameter (display_key)
- Eliminated all special-case logic for forge

Note: No backward compatibility needed - forge is a new agent
being introduced in this PR.

* fix: ensure forge alias commands have correct name in frontmatter

When inject_name is enabled (for forge), alias command files must
have their own name field in frontmatter, not reuse the primary
command's name. This is critical for Forge's command discovery
and dispatch system.

Changes:
- For agents with inject_name, create a deepcopy of frontmatter
  for each alias and set the name to the alias name
- Re-render the command content with the alias-specific frontmatter
- Ensures each alias file has the correct name field matching its
  filename

This fixes command discovery issues where forge would try to invoke
aliases using the primary command's name.

* feat: add forge to PowerShell script and fix test whitespace

1. PowerShell script (create-release-packages.ps1):
   - Added forge agent support for Windows users
   - Enables `specify init --ai forge --offline` on Windows
   - Enhanced Generate-Commands with ExtraStripKey parameter
   - Added frontmatter stripping for handoffs key
   - Added $ARGUMENTS replacement for {{parameters}}
   - Implemented forge case with name field injection
   - Complete parity with bash script

2. Test file (test_core_pack_scaffold.py):
   - Removed trailing whitespace from blank lines
   - Cleaner diffs and no linter warnings

Addresses Copilot PR feedback on both issues.

* fix: use .NET Regex.Replace for count-limited replacement in PowerShell

Addresses Copilot feedback: PowerShell's -replace operator does not
support a third argument for replacement count. Using it causes an
error or mis-parsing that would break forge package generation on
Windows.

Changed from:
  $content -replace '(?m)^---$', "---`nname: $cmdName", 1

To:
  $regex = [regex]'(?m)^---$'
  $content = $regex.Replace($content, "---`nname: $cmdName", 1)

The .NET Regex.Replace() method properly supports the count parameter,
ensuring the name field is injected only after the first frontmatter
delimiter (not the closing one).

This fix is critical for Windows users running:
  specify init --ai forge --offline

* Apply suggestion from @Copilot

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

* feat: migrate Forge agent to Python integration system

- Create ForgeIntegration class with custom processing for {{parameters}}, handoffs stripping, and name injection
- Add update-context scripts (bash and PowerShell) for Forge
- Register Forge in integration registry
- Update AGENTS.md with Forge documentation and special processing requirements section
- Add comprehensive test suite (11 tests, all passing)

Closes migration from release packaging to Python-based scaffolding for Forge agent.

* fix: replace $ARGUMENTS with {{parameters}} in Forge templates

- Add replacement of $ARGUMENTS to {{parameters}} after template processing
- Use arg_placeholder from config (Copilot's cleaner approach)
- Remove unused 'import re' from _apply_forge_transformations()
- Enhance tests to verify $ARGUMENTS replacement works correctly
- All 11 tests pass

Fixes template processing to ensure Forge receives user-supplied parameters correctly.

* refactor: make ForgeIntegration extend MarkdownIntegration

- Change base class from IntegrationBase to MarkdownIntegration
- Eliminates ~30 lines of duplicated validation/setup boilerplate
- Aligns with the pattern used by 20+ other markdown agents (Bob, Claude, Windsurf, etc.)
- Update AGENTS.md to reflect new inheritance hierarchy
- All Forge-specific processing retained ({{parameters}}, handoffs stripping, name injection)
- All 535 integration tests pass

This addresses reviewer feedback about using the MarkdownIntegration convenience base class.

* style: remove trailing whitespace from test file

- Strip trailing spaces from blank lines in test_integration_forge.py
- Fixes W291 linting warnings
- No functional changes

* style: remove trailing whitespace from Forge integration

- Strip trailing spaces from blank lines in __init__.py
- Fixes whitespace on lines 20, 86, 90, 93, 139, 143
- Verified other files in forge/ directory have no trailing whitespace
- No functional changes, all tests pass

* test: derive expected commands from templates dynamically

- Remove hard-coded command count (9) and command set from test_directory_structure
- Use forge.list_command_templates() to derive expected commands
- Test now auto-syncs when core command templates are added/removed
- Prevents test breakage when template set changes
- All 11 tests pass

* fix: make Forge update-context scripts handle AGENTS.md directly

- Add fallback logic to update/create AGENTS.md when shared script doesn't support forge yet
- Check if shared dispatcher knows about 'forge' before delegating
- If shared script doesn't support forge, handle AGENTS.md updates directly:
  - Add Forge section to existing AGENTS.md if not present
  - Create new AGENTS.md with Forge section if file doesn't exist
- Both bash and PowerShell scripts implement same logic
- Prevents 'Unknown agent type' errors until shared scripts add forge support
- Future-compatible: automatically delegates when shared script supports forge

Addresses reviewer feedback about update-context scripts failing without forge support.

* feat: add Forge support to shared update-agent-context scripts

- Add forge case to bash and PowerShell update-agent-context scripts
- Add FORGE_FILE variable mapping to AGENTS.md (like opencode/codex/pi)
- Add forge to all usage/help text and ValidateSet parameters
- Include forge in update_all_existing_agents functions

Wrapper script improvements:
- Simplify Forge wrapper scripts to unconditionally delegate to shared script
- Remove complex fallback logic that created stub AGENTS.md files
- Add clear error messages if shared script is missing/not executable
- Align with pattern used by other integrations (opencode, bob, etc.)

Benefits:
- Plan command's {AGENT_SCRIPT} now works for Forge users
- No more incomplete/stub context files masking missing support
- Cleaner, more maintainable code (-39 lines in wrappers)
- Consistent architecture across all integrations

Update AGENTS.md to document that Forge integration ensures shared scripts
include forge support for context updates.

Addresses reviewer feedback about Forge support being incomplete for
workflow steps that run {AGENT_SCRIPT}.

* fix: resolve unbound variable and duplicate file update issues

- Fix undefined FORGE_FILE variable in bash update-agent-context.sh
  - Add missing FORGE_FILE definition pointing to AGENTS.md
  - Update comment to include Forge in list of agents sharing AGENTS.md
  - Prevents crash with 'set -u' when running without explicit agent type

- Add deduplication logic to PowerShell update-agent-context.ps1
  - Implement Update-IfNew helper to track processed files by real path
  - Prevents AGENTS.md from being rewritten multiple times
  - Matches existing deduplication behavior in bash script

- Prevent duplicate YAML keys in Forge frontmatter injection
  - Check for existing 'name:' field before injection in both scripts
  - PowerShell: Parse frontmatter to detect existing name field
  - Bash: Enhanced awk script to check frontmatter state
  - Future-proofs against template changes that add name fields

All scripts now have consistent behavior and proper error handling.

* fix: import timezone from datetime for rate limit header parsing

The _parse_rate_limit_headers() function uses timezone.utc on line 82
but timezone was never imported from datetime. This would raise a
NameError the first time GitHub API rate-limit headers are parsed.

Import timezone alongside datetime to fix the missing import.

* fix: correct variable scope in PowerShell deduplication and update docs

- Fix Update-IfNew in PowerShell update-agent-context.ps1
  - Changed from $script: scope to Set-Variable -Scope 1
  - Properly mutates parent function's local variables
  - Fixes deduplication tracking for shared AGENTS.md file
  - Prevents incorrect default Claude file creation

- Update create-release-packages.sh documentation
  - Add missing 'forge' to AGENTS list in header comment
  - Documentation now matches actual ALL_AGENTS array

Without this fix, AGENTS.md would be updated multiple times (once
for each agent sharing it: opencode, codex, amp, kiro, bob, pi, forge)
and the script would always create a default Claude file even when
agent files exist.

* fix: resolve missing scaffold_from_core_pack import in tests

The test_core_pack_scaffold.py imports scaffold_from_core_pack from
specify_cli, but that symbol does not exist in the current codebase.
This causes an ImportError when the test module is loaded.

Implement a resilient resolver that:
- Tries scaffold_from_core_pack first (expected name)
- Falls back to alternative names (scaffold_from_release_pack, etc.)
- Gracefully skips tests if no compatible entrypoint exists

This prevents import-time failures and makes the test future-proof
for when the actual scaffolding function is added or restored.

* fix: prevent duplicate path prefixes and consolidate shared file updates

PowerShell release script:
- Add deduplication pass to Rewrite-Paths function
- Prevents .specify.specify/ double prefixes in generated commands
- Matches bash script behavior with regex '(?:\.specify/){2,}' -> '.specify/'

Bash update-agent-context script:
- Consolidate AGENTS.md updates to single call
- Remove redundant calls for $AMP_FILE, $KIRO_FILE, $BOB_FILE, $FORGE_FILE
- Update label to 'Codex/opencode/Amp/Kiro/Bob/Pi/Forge' to reflect all agents
- Prevents always-deduped $FORGE_FILE call that never executed

Both fixes improve efficiency and correctness while maintaining parity
between bash and PowerShell implementations.

* refactor: remove unused rate-limit helpers and improve PowerShell scripts

- Remove unused _parse_rate_limit_headers() and _format_rate_limit_error()
  from src/specify_cli/__init__.py (56 lines of dead code)
- Add GENRELEASES_DIR override support to PowerShell release script with
  comprehensive safety checks (parity with bash script)
- Remove redundant shared-file update calls from PowerShell agent context
  script (AMP_FILE, KIRO_FILE, BOB_FILE, FORGE_FILE all resolve to AGENTS.md)
- Update test docstring to accurately reflect Forge's {{parameters}} token

Changes align PowerShell scripts with bash equivalents and reduce maintenance
burden by removing dead code.

* fix: add missing 'forge' to PowerShell usage text and fix agent order

- Add 'forge' to usage message in Print-Summary (was missing from list)
- Reorder ValidateSet to match bash script order (vibe before qodercli)

This ensures PowerShell script documentation matches bash script and includes
all supported agents consistently.

* refactor: remove old architecture files deleted in b1832c9

Remove files that were deleted in b1832c9 (Stage 6 migration) but remained
on this branch due to merge conflicts:

- Remove .github/workflows/scripts/create-release-packages.{sh,ps1}
  (replaced by inline release.yml + uv tool install)
- Remove tests/test_core_pack_scaffold.py
  (scaffold system removed, tests no longer relevant)

These files existed on the feature branch because they were modified before
b1832c9 landed. The merge kept our versions, but they should be deleted to
align with the new integration-only architecture.

This PR now focuses purely on adding NEW Forge integration support, not
restoring old architecture.

* refactor: remove unused timezone import from __init__.py

Remove unused timezone import that was added in 4a57f79 for rate-limit
header parsing but became obsolete when rate-limit helper functions were
removed in 59c4212 (and also removed in upstream b1832c9).

No functional changes - purely cleanup of unused import.

* docs: clarify that handoffs is a Claude Code feature, not Forge's

Update docstrings to accurately explain that the 'handoffs' frontmatter key
is from Claude Code (for multi-agent collaboration) and is stripped because
it causes Forge to hang, not because it's a Forge-specific feature.

Changes:
- Module docstring: 'Forge-specific collaboration feature' → 'Claude Code feature that causes Forge to hang'
- Class docstring: Add '(incompatible with Forge)' clarification
- Method docstring: Add '(from Claude Code templates; incompatible with Forge)' context

This avoids implying that handoffs belongs to Forge when it actually comes
from spec-kit templates designed for Claude Code compatibility.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-02 16:40:43 -05:00

19 KiB

AGENTS.md

About Spec Kit and Specify

GitHub Spec Kit is a comprehensive toolkit for implementing Spec-Driven Development (SDD) - a methodology that emphasizes creating clear specifications before implementation. The toolkit includes templates, scripts, and workflows that guide development teams through a structured approach to building software.

Specify CLI is the command-line interface that bootstraps projects with the Spec Kit framework. It sets up the necessary directory structures, templates, and AI agent integrations to support the Spec-Driven Development workflow.

The toolkit supports multiple AI coding assistants, allowing teams to use their preferred tools while maintaining consistent project structure and development practices.


Adding New Agent Support

This section explains how to add support for new AI agents/assistants to the Specify CLI. Use this guide as a reference when integrating new AI tools into the Spec-Driven Development workflow.

Overview

Specify supports multiple AI agents by generating agent-specific command files and directory structures when initializing projects. Each agent has its own conventions for:

  • Command file formats (Markdown, TOML, etc.)
  • Directory structures (.claude/commands/, .windsurf/workflows/, etc.)
  • Command invocation patterns (slash commands, CLI tools, etc.)
  • Argument passing conventions ($ARGUMENTS, {{args}}, etc.)

Current Supported Agents

Agent Directory Format CLI Tool Description
Claude Code .claude/commands/ Markdown claude Anthropic's Claude Code CLI
Gemini CLI .gemini/commands/ TOML gemini Google's Gemini CLI
GitHub Copilot .github/agents/ Markdown N/A (IDE-based) GitHub Copilot in VS Code
Cursor .cursor/commands/ Markdown N/A (IDE-based) Cursor IDE (--ai cursor-agent)
Qwen Code .qwen/commands/ Markdown qwen Alibaba's Qwen Code CLI
opencode .opencode/command/ Markdown opencode opencode CLI
Codex CLI .agents/skills/ Markdown codex Codex CLI (--ai codex --ai-skills)
Windsurf .windsurf/workflows/ Markdown N/A (IDE-based) Windsurf IDE workflows
Junie .junie/commands/ Markdown junie Junie by JetBrains
Kilo Code .kilocode/workflows/ Markdown N/A (IDE-based) Kilo Code IDE
Auggie CLI .augment/commands/ Markdown auggie Auggie CLI
Roo Code .roo/commands/ Markdown N/A (IDE-based) Roo Code IDE
CodeBuddy CLI .codebuddy/commands/ Markdown codebuddy CodeBuddy CLI
Qoder CLI .qoder/commands/ Markdown qodercli Qoder CLI
Kiro CLI .kiro/prompts/ Markdown kiro-cli Kiro CLI
Amp .agents/commands/ Markdown amp Amp CLI
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
iFlow CLI .iflow/commands/ Markdown iflow iFlow CLI (iflow-ai)
Forge .forge/commands/ Markdown forge Forge CLI (forgecode.dev)
IBM Bob .bob/commands/ Markdown N/A (IDE-based) IBM Bob IDE
Trae .trae/rules/ Markdown N/A (IDE-based) Trae IDE
Antigravity .agent/commands/ Markdown N/A (IDE-based) Antigravity IDE (--ai agy --ai-skills)
Mistral Vibe .vibe/prompts/ Markdown vibe Mistral Vibe CLI
Generic User-specified via --ai-commands-dir Markdown N/A Bring your own agent

Step-by-Step Integration Guide

Follow these steps to add a new agent (using a hypothetical new agent as an example):

1. Add to AGENT_CONFIG

IMPORTANT: Use the actual CLI tool name as the key, not a shortened version.

Add the new agent to the AGENT_CONFIG dictionary in src/specify_cli/__init__.py. This is the single source of truth for all agent metadata:

AGENT_CONFIG = {
    # ... existing agents ...
    "new-agent-cli": {  # Use the ACTUAL CLI tool name (what users type in terminal)
        "name": "New Agent Display Name",
        "folder": ".newagent/",  # Directory for agent files
        "commands_subdir": "commands",  # Subdirectory name for command files (default: "commands")
        "install_url": "https://example.com/install",  # URL for installation docs (or None if IDE-based)
        "requires_cli": True,  # True if CLI tool required, False for IDE-based agents
    },
}

Key Design Principle: The dictionary key should match the actual executable name that users install. For example:

  • Use "cursor-agent" because the CLI tool is literally called cursor-agent
  • Don't use "cursor" as a shortcut if the tool is cursor-agent

This eliminates the need for special-case mappings throughout the codebase.

Field Explanations:

  • name: Human-readable display name shown to users
  • 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, 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

2. Update CLI Help Text

Update the --ai parameter help text in the init() command to include the new agent:

ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, codebuddy, new-agent-cli, or kiro-cli"),

Also update any function docstrings, examples, and error messages that list available agents.

3. Update README Documentation

Update the Supported AI Agents section in README.md to include the new agent:

  • Add the new agent to the table with appropriate support level (Full/Partial)
  • Include the agent's official website link
  • Add any relevant notes about the agent's implementation
  • Ensure the table formatting remains aligned and consistent

4. Update Release Package Script

Modify .github/workflows/scripts/create-release-packages.sh:

Add to ALL_AGENTS array
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf kiro-cli)
Add case statement for directory structure
case $agent in
  # ... existing cases ...
  windsurf)
    mkdir -p "$base_dir/.windsurf/workflows"
    generate_commands windsurf md "\$ARGUMENTS" "$base_dir/.windsurf/workflows" "$script" ;;
esac

4. Update GitHub Release Script

Modify .github/workflows/scripts/create-github-release.sh to include the new agent's packages:

gh release create "$VERSION" \
  # ... existing packages ...
  .genreleases/spec-kit-template-windsurf-sh-"$VERSION".zip \
  .genreleases/spec-kit-template-windsurf-ps-"$VERSION".zip \
  # Add new agent packages here

5. Update Agent Context Scripts

Bash script (scripts/bash/update-agent-context.sh)

Add file variable:

WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"

Add to case statement:

case "$AGENT_TYPE" in
  # ... existing cases ...
  windsurf) update_agent_file "$WINDSURF_FILE" "Windsurf" ;;
  "")
    # ... existing checks ...
    [ -f "$WINDSURF_FILE" ] && update_agent_file "$WINDSURF_FILE" "Windsurf";
    # Update default creation condition
    ;;
esac
PowerShell script (scripts/powershell/update-agent-context.ps1)

Add file variable:

$windsurfFile = Join-Path $repoRoot '.windsurf/rules/specify-rules.md'

Add to switch statement:

switch ($AgentType) {
    # ... existing cases ...
    'windsurf' { Update-AgentFile $windsurfFile 'Windsurf' }
    '' {
        foreach ($pair in @(
            # ... existing pairs ...
            @{file=$windsurfFile; name='Windsurf'}
        )) {
            if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
        }
        # Update default creation condition
    }
}

6. Update CLI Tool Checks (Optional)

For agents that require CLI tools, add checks in the check() command and agent validation:

# In check() command
tracker.add("windsurf", "Windsurf IDE (optional)")
windsurf_ok = check_tool_for_tracker("windsurf", "https://windsurf.com/", tracker)

# In init validation (only if CLI tool required)
elif selected_ai == "windsurf":
    if not check_tool("windsurf", "Install from: https://windsurf.com/"):
        console.print("[red]Error:[/red] Windsurf CLI is required for Windsurf projects")
        agent_tool_missing = True

Note: CLI tool checks are now handled automatically based on the requires_cli field in AGENT_CONFIG. No additional code changes needed in the check() or init() commands - they automatically loop through AGENT_CONFIG and check tools as needed.

Important Design Decisions

Using Actual CLI Tool Names as Keys

CRITICAL: When adding a new agent to AGENT_CONFIG, always use the actual executable name as the dictionary key, not a shortened or convenient version.

Why this matters:

  • The check_tool() function uses shutil.which(tool) to find executables in the system PATH
  • If the key doesn't match the actual CLI tool name, you'll need special-case mappings throughout the codebase
  • This creates unnecessary complexity and maintenance burden

Example - The Cursor Lesson:

Wrong approach (requires special-case mapping):

AGENT_CONFIG = {
    "cursor": {  # Shorthand that doesn't match the actual tool
        "name": "Cursor",
        # ...
    }
}

# Then you need special cases everywhere:
cli_tool = agent_key
if agent_key == "cursor":
    cli_tool = "cursor-agent"  # Map to the real tool name

Correct approach (no mapping needed):

AGENT_CONFIG = {
    "cursor-agent": {  # Matches the actual executable name
        "name": "Cursor",
        # ...
    }
}

# No special cases needed - just use agent_key directly!

Benefits of this approach:

  • Eliminates special-case logic scattered throughout the codebase
  • Makes the code more maintainable and easier to understand
  • Reduces the chance of bugs when adding new agents
  • Tool checking "just works" without additional mappings

7. Update Devcontainer files (Optional)

For agents that have VS Code extensions or require CLI installation, update the devcontainer configuration files:

VS Code Extension-based Agents

For agents available as VS Code extensions, add them to .devcontainer/devcontainer.json:

{
  "customizations": {
    "vscode": {
      "extensions": [
        // ... existing extensions ...
        // [New Agent Name]
        "[New Agent Extension ID]"
      ]
    }
  }
}
CLI-based Agents

For agents that require CLI tools, add installation commands to .devcontainer/post-create.sh:

#!/bin/bash

# Existing installations...

echo -e "\n🤖 Installing [New Agent Name] CLI..."
# run_command "npm install -g [agent-cli-package]@latest" # Example for node-based CLI
# or other installation instructions (must be non-interactive and compatible with Linux Debian "Trixie" or later)...
echo "✅ Done"

Quick Tips:

  • Extension-based agents: Add to the extensions array in devcontainer.json
  • CLI-based agents: Add installation scripts to post-create.sh
  • Hybrid agents: May require both extension and CLI installation
  • Test thoroughly: Ensure installations work in the devcontainer environment

Agent Categories

CLI-Based Agents

Require a command-line tool to be installed:

  • Claude Code: claude CLI
  • Gemini CLI: gemini CLI
  • Qwen Code: qwen CLI
  • opencode: opencode CLI
  • Codex CLI: codex CLI (requires --ai-skills)
  • Junie: junie CLI
  • Auggie CLI: auggie CLI
  • CodeBuddy CLI: codebuddy CLI
  • Qoder CLI: qodercli CLI
  • Kiro CLI: kiro-cli CLI
  • Amp: amp CLI
  • SHAI: shai CLI
  • Tabnine CLI: tabnine CLI
  • Kimi Code: kimi CLI
  • Mistral Vibe: vibe CLI
  • Pi Coding Agent: pi CLI
  • iFlow CLI: iflow CLI
  • Forge: forge CLI

IDE-Based Agents

Work within integrated development environments:

  • GitHub Copilot: Built into VS Code/compatible editors
  • Cursor: Built into Cursor IDE (--ai cursor-agent)
  • Windsurf: Built into Windsurf IDE
  • Kilo Code: Built into Kilo Code IDE
  • Roo Code: Built into Roo Code IDE
  • IBM Bob: Built into IBM Bob IDE
  • Trae: Built into Trae IDE
  • Antigravity: Built into Antigravity IDE (--ai agy --ai-skills)

Command File Formats

Markdown Format

Used by: Claude, Cursor, GitHub Copilot, opencode, Windsurf, Junie, Kiro CLI, Amp, SHAI, IBM Bob, Kimi Code, Qwen, Pi, Codex, Auggie, CodeBuddy, Qoder, Roo Code, Kilo Code, Trae, Antigravity, Mistral Vibe, iFlow, Forge

Standard format:

---
description: "Command description"
---

Command content with {SCRIPT} and $ARGUMENTS placeholders.

GitHub Copilot Chat Mode format:

---
description: "Command description"
mode: speckit.command-name
---

Command content with {SCRIPT} and $ARGUMENTS placeholders.

TOML Format

Used by: Gemini, Tabnine

description = "Command description"

prompt = """
Command content with {SCRIPT} and {{args}} placeholders.
"""

Directory Conventions

  • CLI agents: Usually .<agent-name>/commands/
  • Singular command exception:
    • opencode: .opencode/command/ (singular command, not commands)
  • Nested path exception:
    • Tabnine: .tabnine/agent/commands/ (extra agent/ segment)
  • Shared .agents/ folder:
    • Amp: .agents/commands/ (shared folder, not .amp/)
    • Codex: .agents/skills/ (shared folder; requires --ai-skills; invoked as $speckit-<command>)
  • Skills-based exceptions:
    • Kimi Code: .kimi/skills/ (skills, invoked as /skill:speckit-<command>)
  • Prompt-based exceptions:
    • Kiro CLI: .kiro/prompts/
    • Pi: .pi/prompts/
    • Mistral Vibe: .vibe/prompts/
  • Rules-based exceptions:
    • Trae: .trae/rules/
  • IDE agents: Follow IDE-specific patterns:
    • Copilot: .github/agents/
    • Cursor: .cursor/commands/
    • Windsurf: .windsurf/workflows/
    • Kilo Code: .kilocode/workflows/
    • Roo Code: .roo/commands/
    • IBM Bob: .bob/commands/
    • Antigravity: .agent/skills/ (--ai-skills required; .agent/commands/ is deprecated)

Argument Patterns

Different agents use different argument placeholders:

  • Markdown/prompt-based: $ARGUMENTS
  • TOML-based: {{args}}
  • Forge-specific: {{parameters}} (uses custom parameter syntax)
  • Script placeholders: {SCRIPT} (replaced with actual script path)
  • Agent placeholders: __AGENT__ (replaced with agent name)

Special Processing Requirements

Some agents require custom processing beyond the standard template transformations:

Copilot Integration

GitHub Copilot has unique requirements:

  • Commands use .agent.md extension (not .md)
  • Each command gets a companion .prompt.md file in .github/prompts/
  • Installs .vscode/settings.json with prompt file recommendations
  • Context file lives at .github/copilot-instructions.md

Implementation: Extends IntegrationBase with custom setup() method that:

  1. Processes templates with process_template()
  2. Generates companion .prompt.md files
  3. Merges VS Code settings

Forge Integration

Forge has special frontmatter and argument requirements:

  • Uses {{parameters}} instead of $ARGUMENTS
  • Strips handoffs frontmatter key (Forge-specific collaboration feature)
  • Injects name field into frontmatter when missing

Implementation: Extends MarkdownIntegration with custom setup() method that:

  1. Inherits standard template processing from MarkdownIntegration
  2. Adds extra $ARGUMENTS{{parameters}} replacement after template processing
  3. Applies Forge-specific transformations via _apply_forge_transformations()
  4. Strips handoffs frontmatter key
  5. Injects missing name fields
  6. Ensures the shared update-agent-context.* scripts include a forge case that maps context updates to AGENTS.md (similar to opencode/codex/pi) and lists forge in their usage/help text

Standard Markdown Agents

Most agents (Bob, Claude, Windsurf, etc.) use MarkdownIntegration:

  • Simple subclass with just key, config, registrar_config set
  • Inherits standard processing from MarkdownIntegration.setup()
  • No custom processing needed

Testing New Agent Integration

  1. Build test: Run package creation script locally
  2. CLI test: Test specify init --ai <agent> command
  3. File generation: Verify correct directory structure and files
  4. Command validation: Ensure generated commands work with the agent
  5. Context update: Test agent context update scripts

Common Pitfalls

  1. Using shorthand keys instead of actual CLI tool names: Always use the actual executable name as the AGENT_CONFIG key (e.g., "cursor-agent" not "cursor"). This prevents the need for special-case mappings throughout the codebase.
  2. Forgetting update scripts: Both bash and PowerShell scripts must be updated when adding new agents.
  3. Incorrect requires_cli value: Set to True only for agents that actually have CLI tools to check; set to False for IDE-based agents.
  4. Wrong argument format: Use correct placeholder format for each agent type ($ARGUMENTS for Markdown, {{args}} for TOML).
  5. Directory naming: Follow agent-specific conventions exactly (check existing agents for patterns).
  6. Help text inconsistency: Update all user-facing text consistently (help strings, docstrings, README, error messages).

Future Considerations

When adding new agents:

  • Consider the agent's native command/workflow patterns
  • Ensure compatibility with the Spec-Driven Development process
  • Document any special requirements or limitations
  • Update this guide with lessons learned
  • Verify the actual CLI tool name before adding to AGENT_CONFIG

This documentation should be updated whenever new agents are added to maintain accuracy and completeness.