Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
268e983
feat: add Forgecode (forge) agent support
ericnoam Mar 30, 2026
d83be82
fix: strip handoffs frontmatter and replace $ARGUMENTS for forgecode
ericnoam Mar 30, 2026
8128e60
feat: add name field injection for forgecode agent
ericnoam Mar 31, 2026
c1a93c9
test: update test_argument_token_format for forgecode special case
ericnoam Mar 31, 2026
b46bf65
docs: add forgecode to README documentation
ericnoam Mar 31, 2026
c69893c
fix: show 'forge' binary name in user-facing messages for forgecode
ericnoam Mar 31, 2026
0a477a9
refactor: rename forgecode agent key to forge
ericnoam Mar 31, 2026
635790d
fix: ensure forge alias commands have correct name in frontmatter
ericnoam Mar 31, 2026
506b7ef
feat: add forge to PowerShell script and fix test whitespace
ericnoam Mar 31, 2026
1de7851
fix: use .NET Regex.Replace for count-limited replacement in PowerShell
ericnoam Mar 31, 2026
a7deefc
Merge branch 'main' into feature/add-forgecode-agent-support
ericnoam Apr 1, 2026
d1360ef
Apply suggestion from @Copilot
ericnoam Apr 1, 2026
e3f269b
feat: migrate Forge agent to Python integration system
ericnoam Apr 2, 2026
f5fbfce
Merge branch 'main' into feature/add-forgecode-agent-support
ericnoam Apr 2, 2026
1294d43
fix: replace $ARGUMENTS with {{parameters}} in Forge templates
ericnoam Apr 2, 2026
7d06021
refactor: make ForgeIntegration extend MarkdownIntegration
ericnoam Apr 2, 2026
1009d92
style: remove trailing whitespace from test file
ericnoam Apr 2, 2026
8330f5a
style: remove trailing whitespace from Forge integration
ericnoam Apr 2, 2026
99d7c9a
test: derive expected commands from templates dynamically
ericnoam Apr 2, 2026
494879f
fix: make Forge update-context scripts handle AGENTS.md directly
ericnoam Apr 2, 2026
99e1c3f
feat: add Forge support to shared update-agent-context scripts
ericnoam Apr 2, 2026
90a1845
fix: resolve unbound variable and duplicate file update issues
ericnoam Apr 2, 2026
769a87f
Merge branch 'main' into feature/add-forgecode-agent-support
ericnoam Apr 2, 2026
4a57f79
fix: import timezone from datetime for rate limit header parsing
ericnoam Apr 2, 2026
9f0ef26
fix: correct variable scope in PowerShell deduplication and update docs
ericnoam Apr 2, 2026
ba67ebf
fix: resolve missing scaffold_from_core_pack import in tests
ericnoam Apr 2, 2026
794d421
Merge branch 'github:main' into feature/add-forgecode-agent-support
ericnoam Apr 2, 2026
89b935d
fix: prevent duplicate path prefixes and consolidate shared file updates
ericnoam Apr 2, 2026
053ee8a
Merge branch 'github:main' into feature/add-forgecode-agent-support
ericnoam Apr 2, 2026
59c4212
refactor: remove unused rate-limit helpers and improve PowerShell scr…
ericnoam Apr 2, 2026
8aad4e6
fix: add missing 'forge' to PowerShell usage text and fix agent order
ericnoam Apr 2, 2026
7265539
refactor: remove old architecture files deleted in b1832c9
ericnoam Apr 2, 2026
a077fff
refactor: remove unused timezone import from __init__.py
ericnoam Apr 2, 2026
afbe989
docs: clarify that handoffs is a Claude Code feature, not Forge's
ericnoam Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions .github/workflows/scripts/create-release-packages.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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, junie, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, trae, pi, iflow, generic
Valid agents: claude, gemini, copilot, cursor-agent, qwen, opencode, windsurf, junie, codex, kilocode, auggie, roo, codebuddy, amp, kiro-cli, bob, qodercli, shai, tabnine, agy, vibe, kimi, trae, pi, iflow, forge, generic

.PARAMETER Scripts
Comma or space separated subset of script types to build (default: both)
Expand Down Expand Up @@ -73,7 +73,8 @@ function Generate-Commands {
[string]$Extension,
[string]$ArgFormat,
[string]$OutputDir,
[string]$ScriptVariant
[string]$ScriptVariant,
[string]$ExtraStripKey = ""
)

New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
Expand Down Expand Up @@ -137,7 +138,16 @@ function Generate-Commands {
}

if ($inFrontmatter) {
# Check for scripts/agent_scripts or extra strip key
$shouldSkip = $false
if ($line -match '^(scripts|agent_scripts):$') {
$shouldSkip = $true
}
if (-not [string]::IsNullOrEmpty($ExtraStripKey) -and $line -match "^${ExtraStripKey}:") {
$shouldSkip = $true
}

if ($shouldSkip) {
$skipScripts = $true
continue
}
Expand All @@ -156,6 +166,7 @@ function Generate-Commands {

# Apply other substitutions
$body = $body -replace '\{ARGS\}', $ArgFormat
$body = $body -replace '\$ARGUMENTS', $ArgFormat
$body = $body -replace '__AGENT__', $Agent
$body = Rewrite-Paths -Content $body

Expand Down Expand Up @@ -477,6 +488,22 @@ function Build-Variant {
$cmdDir = Join-Path $baseDir ".iflow/commands"
Generate-Commands -Agent 'iflow' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
}
'forge' {
$cmdDir = Join-Path $baseDir ".forge/commands"
Generate-Commands -Agent 'forge' -Extension 'md' -ArgFormat '{{parameters}}' -OutputDir $cmdDir -ScriptVariant $Script -ExtraStripKey 'handoffs'

# Inject name field into frontmatter (forge requires name + description)
$cmdFiles = Get-ChildItem -Path "$cmdDir/*.md" -File -ErrorAction SilentlyContinue
foreach ($cmdFile in $cmdFiles) {
$cmdName = [System.IO.Path]::GetFileNameWithoutExtension($cmdFile.Name)
$content = Get-Content -Path $cmdFile.FullName -Raw

# Inject name field after first ---
$content = $content -replace '(?m)^---$', "---`nname: $cmdName", 1
Comment thread
ericnoam marked this conversation as resolved.
Outdated

Set-Content -Path $cmdFile.FullName -Value $content -NoNewline
}
}
'generic' {
$cmdDir = Join-Path $baseDir ".speckit/commands"
Generate-Commands -Agent 'generic' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
Expand All @@ -493,7 +520,7 @@ function Build-Variant {
}

# Define all agents and scripts
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'junie', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'trae', 'pi', 'iflow', 'generic')
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'junie', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'kiro-cli', 'bob', 'qodercli', 'shai', 'tabnine', 'agy', 'vibe', 'kimi', 'trae', 'pi', 'iflow', 'forge', 'generic')
$AllScripts = @('sh', 'ps')

function Normalize-List {
Expand Down
24 changes: 18 additions & 6 deletions .github/workflows/scripts/create-release-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ rewrite_paths() {
}

generate_commands() {
local agent=$1 ext=$2 arg_format=$3 output_dir=$4 script_variant=$5
local agent=$1 ext=$2 arg_format=$3 output_dir=$4 script_variant=$5 extra_strip_key="${6:-}"
mkdir -p "$output_dir"
for template in templates/commands/*.md; do
[[ -f "$template" ]] || continue
Expand Down Expand Up @@ -95,18 +95,19 @@ generate_commands() {
body=$(printf '%s\n' "$body" | sed "s|{AGENT_SCRIPT}|${agent_script_command}|g")
fi

# Remove the scripts: and agent_scripts: sections from frontmatter while preserving YAML structure
body=$(printf '%s\n' "$body" | awk '
# Remove the scripts:, agent_scripts:, and any extra key sections from frontmatter
body=$(printf '%s\n' "$body" | awk -v extra_key="$extra_strip_key" '
/^---$/ { print; if (++dash_count == 1) in_frontmatter=1; else in_frontmatter=0; next }
in_frontmatter && /^scripts:$/ { skip_scripts=1; next }
in_frontmatter && /^agent_scripts:$/ { skip_scripts=1; next }
in_frontmatter && extra_key != "" && $0 ~ ("^"extra_key":") { skip_scripts=1; next }
in_frontmatter && /^[a-zA-Z].*:/ && skip_scripts { skip_scripts=0 }
in_frontmatter && skip_scripts && /^[[:space:]]/ { next }
{ print }
')

# Apply other substitutions
body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)
# Apply other substitutions; also replace $ARGUMENTS with the agent-specific placeholder
body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed 's/\$ARGUMENTS/'"$arg_format"'/g' | sed "s/__AGENT__/$agent/g" | rewrite_paths)

case $ext in
toml)
Expand Down Expand Up @@ -330,6 +331,17 @@ build_variant() {
iflow)
mkdir -p "$base_dir/.iflow/commands"
generate_commands iflow md "\$ARGUMENTS" "$base_dir/.iflow/commands" "$script" ;;
forge)
mkdir -p "$base_dir/.forge/commands"
generate_commands forge md "{{parameters}}" "$base_dir/.forge/commands" "$script" "handoffs"
# Inject name field into frontmatter (forge requires name + description)
for _cmd_file in "$base_dir/.forge/commands/"*.md; do
[[ -f "$_cmd_file" ]] || continue
_cmd_name=$(basename "$_cmd_file" .md)
_tmp_file="${_cmd_file}.tmp"
awk -v name="$_cmd_name" 'NR==1 && /^---$/ { print; print "name: "name; next } { print }' "$_cmd_file" > "$_tmp_file"
Comment thread
ericnoam marked this conversation as resolved.
Outdated
mv "$_tmp_file" "$_cmd_file"
done ;;
generic)
mkdir -p "$base_dir/.speckit/commands"
generate_commands generic md "\$ARGUMENTS" "$base_dir/.speckit/commands" "$script" ;;
Expand All @@ -339,7 +351,7 @@ build_variant() {
}

# Determine agent list
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf junie codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi trae pi iflow generic)
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf junie codex kilocode auggie roo codebuddy amp shai tabnine kiro-cli agy bob vibe qodercli kimi trae pi iflow forge generic)
ALL_SCRIPTS=(sh ps)

validate_subset() {
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ Community projects that extend, visualize, or build on Spec Kit:
| [CodeBuddy CLI](https://www.codebuddy.ai/cli) | ✅ | |
| [Codex CLI](https://github.com/openai/codex) | ✅ | Requires `--ai-skills`. Codex recommends [skills](https://developers.openai.com/codex/skills) and treats [custom prompts](https://developers.openai.com/codex/custom-prompts) as deprecated. Spec-kit installs Codex skills into `.agents/skills` and invokes them as `$speckit-<command>`. |
| [Cursor](https://cursor.sh/) | ✅ | |
| [Forge](https://forgecode.dev/) | ✅ | CLI tool: `forge` |
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | ✅ | |
| [GitHub Copilot](https://code.visualstudio.com/) | ✅ | |
| [IBM Bob](https://www.ibm.com/products/bob) | ✅ | IDE-based agent with slash command support |
Expand Down Expand Up @@ -294,14 +295,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` plus all CLI-based agents configured in `AGENT_CONFIG` (for example: `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `junie`, `qwen`, `opencode`, `codex`, `kiro-cli`, `shai`, `qodercli`, `vibe`, `kimi`, `iflow`, `pi`, etc.) |
| `check` | Check for installed tools: `git` plus all CLI-based agents configured in `AGENT_CONFIG` (for example: `claude`, `gemini`, `code`/`code-insiders`, `cursor-agent`, `windsurf`, `junie`, `qwen`, `opencode`, `codex`, `kiro-cli`, `shai`, `qodercli`, `vibe`, `kimi`, `iflow`, `pi`, `forge`, etc.) |

### `specify init` Arguments & Options

| Argument/Option | Type | Description |
| ---------------------- | -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`, or use `.` for current directory) |
| `--ai` | Option | AI assistant to use (see `AGENT_CONFIG` for the full, up-to-date list). Common options include: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `junie`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `kiro-cli` (`kiro` alias), `agy`, `bob`, `qodercli`, `vibe`, `kimi`, `iflow`, `pi`, or `generic` (requires `--ai-commands-dir`) |
| `--ai` | Option | AI assistant to use (see `AGENT_CONFIG` for the full, up-to-date list). Common options include: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `junie`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `kiro-cli` (`kiro` alias), `agy`, `bob`, `qodercli`, `vibe`, `kimi`, `iflow`, `pi`, `forge`, 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 |
Expand Down Expand Up @@ -356,6 +357,9 @@ specify init my-project --ai codex --ai-skills
# Initialize with Antigravity support
specify init my-project --ai agy --ai-skills

# Initialize with Forge support
specify init my-project --ai forge

# Initialize with an unsupported agent (generic / bring your own agent)
specify init my-project --ai generic --ai-commands-dir .myagent/commands/

Expand Down Expand Up @@ -597,7 +601,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, 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:
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, Forge, 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 <project_name> --ai claude --ignore-agent-tools
Expand Down
Loading
Loading