Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .github/workflows/scripts/create-github-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,7 @@ gh release create "$VERSION" \
.genreleases/spec-kit-template-q-ps-"$VERSION".zip \
.genreleases/spec-kit-template-bob-sh-"$VERSION".zip \
.genreleases/spec-kit-template-bob-ps-"$VERSION".zip \
.genreleases/spec-kit-template-trae-sh-"$VERSION".zip \
.genreleases/spec-kit-template-trae-ps-"$VERSION".zip \
--title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md
6 changes: 5 additions & 1 deletion .github/workflows/scripts/create-release-packages.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,10 @@ function Build-Variant {
$cmdDir = Join-Path $baseDir ".qoder/commands"
Generate-Commands -Agent 'qoder' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
}
'trae' {
$cmdDir = Join-Path $baseDir ".trae/rules"
Generate-Commands -Agent 'trae' -Extension 'md' -ArgFormat '$ARGUMENTS' -OutputDir $cmdDir -ScriptVariant $Script
}
}

# Create zip archive
Expand All @@ -356,7 +360,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', 'qoder')
$AllAgents = @('claude', 'gemini', 'copilot', 'cursor-agent', 'qwen', 'opencode', 'windsurf', 'codex', 'kilocode', 'auggie', 'roo', 'codebuddy', 'amp', 'q', 'bob', 'qoder', 'trae')
$AllScripts = @('sh', 'ps')

function Normalize-List {
Expand Down
40 changes: 31 additions & 9 deletions .github/workflows/scripts/create-release-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,14 @@ build_variant() {
esac
fi

[[ -d templates ]] && { mkdir -p "$SPEC_DIR/templates"; find templates -type f -not -path "templates/commands/*" -not -name "vscode-settings.json" -exec cp --parents {} "$SPEC_DIR"/ \; ; echo "Copied templates -> .specify/templates"; }
[[ -d templates ]] && {
find templates -type f -not -path "templates/commands/*" -not -name "vscode-settings.json" | while read -r file; do
dir=$(dirname "$file")
mkdir -p "$SPEC_DIR/$dir"
cp "$file" "$SPEC_DIR/$file"
done
echo "Copied templates -> .specify/templates"
}

# NOTE: We substitute {ARGS} internally. Outward tokens differ intentionally:
# * Markdown/prompt (claude, copilot, cursor-agent, opencode): $ARGUMENTS
Expand Down Expand Up @@ -217,13 +224,16 @@ build_variant() {
bob)
mkdir -p "$base_dir/.bob/commands"
generate_commands bob md "\$ARGUMENTS" "$base_dir/.bob/commands" "$script" ;;
trae)
mkdir -p "$base_dir/.trae/rules"
generate_commands trae md "\$ARGUMENTS" "$base_dir/.trae/rules" "$script" ;;
esac
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
echo "Created $GENRELEASES_DIR/spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
}

# Determine agent list
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q bob qoder)
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp shai q bob qoder trae)
ALL_SCRIPTS=(sh ps)

norm_list() {
Expand All @@ -232,29 +242,41 @@ norm_list() {
}

validate_subset() {
local type=$1; shift; local -n allowed=$1; shift; local items=("$@")
local type=$1; shift
local items=("$@")
local allowed_list

if [[ "$type" == "agent" ]]; then
allowed_list=("${ALL_AGENTS[@]}")
elif [[ "$type" == "script" ]]; then
allowed_list=("${ALL_SCRIPTS[@]}")
else
echo "Internal error: unknown validation type $type" >&2
return 1
fi

local invalid=0
for it in "${items[@]}"; do
local found=0
for a in "${allowed[@]}"; do [[ $it == "$a" ]] && { found=1; break; }; done
for a in "${allowed_list[@]}"; do [[ $it == "$a" ]] && { found=1; break; }; done
if [[ $found -eq 0 ]]; then
echo "Error: unknown $type '$it' (allowed: ${allowed[*]})" >&2
echo "Error: unknown $type '$it' (allowed: ${allowed_list[*]})" >&2
invalid=1
fi
done
return $invalid
}

if [[ -n ${AGENTS:-} ]]; then
mapfile -t AGENT_LIST < <(printf '%s' "$AGENTS" | norm_list)
validate_subset agent ALL_AGENTS "${AGENT_LIST[@]}" || exit 1
while IFS= read -r line; do AGENT_LIST+=("$line"); done < <(printf '%s' "$AGENTS" | norm_list)
validate_subset agent "${AGENT_LIST[@]}" || exit 1
else
AGENT_LIST=("${ALL_AGENTS[@]}")
fi

if [[ -n ${SCRIPTS:-} ]]; then
mapfile -t SCRIPT_LIST < <(printf '%s' "$SCRIPTS" | norm_list)
validate_subset script ALL_SCRIPTS "${SCRIPT_LIST[@]}" || exit 1
while IFS= read -r line; do SCRIPT_LIST+=("$line"); done < <(printf '%s' "$SCRIPTS" | norm_list)
validate_subset script "${SCRIPT_LIST[@]}" || exit 1
else
SCRIPT_LIST=("${ALL_SCRIPTS[@]}")
fi
Expand Down
11 changes: 10 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
| **Trae** | `.trae/rules/` | Markdown | N/A (IDE-based) | Use `#` to reference files |

### Step-by-Step Integration Guide

Expand Down Expand Up @@ -325,11 +326,18 @@ Work within integrated development environments:
- **Windsurf**: Built into Windsurf IDE
- **IBM Bob**: Built into IBM Bob IDE

### Trae IDE

Trae uses the `.trae/rules/` directory for context. To use Spec-Kit commands in Trae:

1. Use **`#`** in the chat (e.g., `#speckit.plan.md`) to load the rule file.
2. The AI will follow the instructions in the file.

## Command File Formats

### Markdown Format

Used by: Claude, Cursor, opencode, Windsurf, Amazon Q Developer, Amp, SHAI, IBM Bob
Used by: Claude, Cursor, opencode, Windsurf, Amazon Q Developer, Amp, SHAI, IBM Bob, Trae

**Standard format:**

Expand Down Expand Up @@ -371,6 +379,7 @@ Command content with {SCRIPT} and {{args}} placeholders.
- Copilot: `.github/agents/`
- Cursor: `.cursor/commands/`
- Windsurf: `.windsurf/workflows/`
- Trae: `.trae/rules/`

## Argument Patterns

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.c
| [Qwen Code](https://github.com/QwenLM/qwen-code) | ✅ | |
| [Roo Code](https://roocode.com/) | ✅ | |
| [SHAI (OVHcloud)](https://github.com/ovh/shai) | ✅ | |
| [Trae](https://trae.ai) | ✅ | |
| [Windsurf](https://windsurf.com/) | ✅ | |

## 🔧 Specify CLI Reference
Expand All @@ -179,7 +180,7 @@ The `specify` command supports the following 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: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `q`, `bob`, or `qoder` |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `shai`, `q`, `bob`, `qoder`, or `trae` |
| `--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 |
| `--no-git` | Flag | Skip git repository initialization |
Expand Down
13 changes: 11 additions & 2 deletions scripts/bash/update-agent-context.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ AMP_FILE="$REPO_ROOT/AGENTS.md"
SHAI_FILE="$REPO_ROOT/SHAI.md"
Q_FILE="$REPO_ROOT/AGENTS.md"
BOB_FILE="$REPO_ROOT/AGENTS.md"
TRAE_FILE="$REPO_ROOT/.trae/rules/specify-rules.md"

# Template file
TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md"
Expand Down Expand Up @@ -633,9 +634,12 @@ update_specific_agent() {
bob)
update_agent_file "$BOB_FILE" "IBM Bob"
;;
trae)
update_agent_file "$TRAE_FILE" "Trae AI"
;;
*)
log_error "Unknown agent type '$agent_type'"
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|amp|shai|q|bob|qoder"
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|amp|shai|q|bob|qoder|trae"
exit 1
;;
esac
Expand Down Expand Up @@ -719,6 +723,11 @@ update_all_existing_agents() {
update_agent_file "$BOB_FILE" "IBM Bob"
found_agent=true
fi

if [[ -f "$TRAE_FILE" ]]; then
update_agent_file "$TRAE_FILE" "Trae AI"
found_agent=true
fi

# If no agent files exist, create a default Claude file
if [[ "$found_agent" == false ]]; then
Expand All @@ -744,7 +753,7 @@ print_summary() {

echo

log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|codebuddy|shai|q|bob|qoder]"
log_info "Usage: $0 [claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|codebuddy|shai|q|bob|qoder|trae]"
}

#==============================================================================
Expand Down
9 changes: 6 additions & 3 deletions scripts/powershell/update-agent-context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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','bob','qoder')]
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','q','bob','qoder','trae')]
[string]$AgentType
)

Expand Down Expand Up @@ -60,6 +60,7 @@ $AMP_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$SHAI_FILE = Join-Path $REPO_ROOT 'SHAI.md'
$Q_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$BOB_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$TRAE_FILE = Join-Path $REPO_ROOT '.trae/rules/specify-rules.md'

$TEMPLATE_FILE = Join-Path $REPO_ROOT '.specify/templates/agent-file-template.md'

Expand Down Expand Up @@ -388,7 +389,8 @@ function Update-SpecificAgent {
'shai' { Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI' }
'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' }
'bob' { Update-AgentFile -TargetFile $BOB_FILE -AgentName 'IBM Bob' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|bob|qoder'; return $false }
'trae' { Update-AgentFile -TargetFile $TRAE_FILE -AgentName 'Trae AI' }
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|bob|qoder|trae'; return $false }
}
}

Expand All @@ -410,6 +412,7 @@ function Update-AllExistingAgents {
if (Test-Path $SHAI_FILE) { if (-not (Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI')) { $ok = $false }; $found = $true }
if (Test-Path $Q_FILE) { if (-not (Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI')) { $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 $TRAE_FILE) { if (-not (Update-AgentFile -TargetFile $TRAE_FILE -AgentName 'Trae AI')) { $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 }
Expand All @@ -424,7 +427,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|bob|qoder]'
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q|bob|qoder|trae]'
}

function Main {
Expand Down
8 changes: 7 additions & 1 deletion src/specify_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ def _format_rate_limit_error(status_code: int, headers: httpx.Headers, url: str)
"install_url": None, # IDE-based
"requires_cli": False,
},
"trae": {
"name": "Trae",
"folder": ".trae/",
"install_url": None, # IDE-based
"requires_cli": False,
},
}

SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
Expand Down Expand Up @@ -945,7 +951,7 @@ def ensure_executable_scripts(project_path: Path, tracker: StepTracker | None =
@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, bob, or qoder "),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, codebuddy, amp, shai, q, bob, qoder, or trae"),
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"),
no_git: bool = typer.Option(False, "--no-git", help="Skip git repository initialization"),
Expand Down