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 @@ -44,5 +44,7 @@ gh release create "$VERSION" \
.genreleases/spec-kit-template-amp-ps-"$VERSION".zip \
.genreleases/spec-kit-template-q-sh-"$VERSION".zip \
.genreleases/spec-kit-template-q-ps-"$VERSION".zip \
.genreleases/spec-kit-template-continue-sh-"$VERSION".zip \
.genreleases/spec-kit-template-continue-ps-"$VERSION".zip \
--title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md
48 changes: 47 additions & 1 deletion .github/workflows/scripts/create-release-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ generate_commands() {
# Apply other substitutions
body=$(printf '%s\n' "$body" | sed "s/{ARGS}/$arg_format/g" | sed "s/__AGENT__/$agent/g" | rewrite_paths)

# If agent is 'continue', prepend special YAML header
if [[ $agent == "continue" ]]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this function needs to be more generic, that is - have a separate function for insertion of custom YAML frontmatter into prompt files, and then invoke it with the argument of invokable and a value of true.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've refactored the code to extract the YAML frontmatter insertion logic into a separate, more generic function called insert_yaml_frontmatter. This function can now be reused for other field insertions in the future.

The new function takes four parameters:

  • body: The content to process
  • name: The name to use for the speckit.{name} entry
  • field_name: The field name to insert (e.g., "invokable")
  • field_value: The value for that field (e.g., "true")

This approach makes the code more maintainable and follows the DRY principle. When the agent is "continue" and a description is present, it still inserts the name: speckit.{name} and invokable: true fields into the YAML frontmatter of the prompt files, but now does so by calling the generic function with the appropriate parameters.

This also makes it easier to add other custom fields in the future without duplicating the AWK logic.

# Find description in body and write invokable: true in next line
if [[ -n "$description" ]]; then
# Insert name and invokable fields after the first --- delimiter
body=$(insert_yaml_frontmatter "$body" "$name" "invokable" "true")
fi
fi

case $ext in
toml)
body=$(printf '%s\n' "$body" | sed 's/\\/\\\\/g')
Expand All @@ -101,6 +110,40 @@ generate_commands() {
done
}

# Generic function to insert custom YAML frontmatter into prompt files
insert_yaml_frontmatter() {
local body=$1
local name=$2
local field_name=$3
local field_value=$4

printf '%s' "$body" | awk -v name="$name" -v field="$field_name" -v value="$field_value" '
BEGIN { in_frontmatter = 0; processed = 0 }
/^---$/ {
print
if (!processed) {
in_frontmatter = 1
}
next
}
in_frontmatter && /^description:/ && !processed {
print "name: speckit." name
print
print field ": " value
processed = 1
next
}
in_frontmatter && /^[a-zA-Z]/ && !processed {
print "name: speckit." name
print field ": " value
print
processed = 1
in_frontmatter = 0
}
!in_frontmatter || processed { print }
'
}

build_variant() {
local agent=$1 script=$2
local base_dir="$GENRELEASES_DIR/sdd-${agent}-package-${script}"
Expand Down Expand Up @@ -186,13 +229,16 @@ build_variant() {
q)
mkdir -p "$base_dir/.amazonq/prompts"
generate_commands q md "\$ARGUMENTS" "$base_dir/.amazonq/prompts" "$script" ;;
continue)
mkdir -p "$base_dir/.continue/prompts"
generate_commands continue md "\$ARGUMENTS" "$base_dir/.continue/prompts" "$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 q)
ALL_AGENTS=(claude gemini copilot cursor-agent qwen opencode windsurf codex kilocode auggie roo codebuddy amp q continue)
ALL_SCRIPTS=(sh ps)

norm_list() {
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Want to see Spec Kit in action? Watch our [video overview](https://www.youtube.c
| [Codex CLI](https://github.com/openai/codex) | βœ… | |
| [Amazon Q Developer CLI](https://aws.amazon.com/developer/learning/q-developer-cli/) | ⚠️ | Amazon Q Developer CLI [does not support](https://github.com/aws/amazon-q-developer-cli/issues/3064) custom arguments for slash commands. |
| [Amp](https://ampcode.com/) | βœ… | |
| [Continue](https://github.com/continuedev/continue) | βœ… | VS Code extension |

## πŸ”§ Specify CLI Reference

Expand All @@ -167,7 +168,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`, or `q` |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor-agent`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, `roo`, `codebuddy`, `amp`, `q`, or `continue` |
| `--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
11 changes: 10 additions & 1 deletion scripts/bash/update-agent-context.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md"
CODEBUDDY_FILE="$REPO_ROOT/CODEBUDDY.md"
AMP_FILE="$REPO_ROOT/AGENTS.md"
Q_FILE="$REPO_ROOT/AGENTS.md"
CONTINUE_FILE="$REPO_ROOT/.continue/rules/specify-rules.md"

# Template file
TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md"
Expand Down Expand Up @@ -621,9 +622,12 @@ update_specific_agent() {
q)
update_agent_file "$Q_FILE" "Amazon Q Developer CLI"
;;
continue)
update_agent_file "$CONTINUE_FILE" "Continue"
;;
*)
log_error "Unknown agent type '$agent_type'"
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|amp|q"
log_error "Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|amp|q|continue"
exit 1
;;
esac
Expand Down Expand Up @@ -692,6 +696,11 @@ update_all_existing_agents() {
update_agent_file "$Q_FILE" "Amazon Q Developer CLI"
found_agent=true
fi

if [[ -f "$CONTINUE_FILE" ]]; then
update_agent_file "$CONTINUE_FILE" "Continue"
found_agent=true
fi

# If no agent files exist, create a default Claude file
if [[ "$found_agent" == false ]]; then
Expand Down
7 changes: 5 additions & 2 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','q')]
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','q','continue')]
[string]$AgentType
)

Expand Down Expand Up @@ -57,6 +57,7 @@ $ROO_FILE = Join-Path $REPO_ROOT '.roo/rules/specify-rules.md'
$CODEBUDDY_FILE = Join-Path $REPO_ROOT 'CODEBUDDY.md'
$AMP_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$Q_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$CONTINUE_FILE = Join-Path $REPO_ROOT '.continue/rules/specify-rules.md'

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

Expand Down Expand Up @@ -382,7 +383,8 @@ function Update-SpecificAgent {
'codebuddy' { Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI' }
'amp' { Update-AgentFile -TargetFile $AMP_FILE -AgentName 'Amp' }
'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|q'; return $false }
'continue' { Update-AgentFile -TargetFile $CONTINUE_FILE -AgentName 'Continue' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|q|continue'; return $false }
}
}

Expand All @@ -401,6 +403,7 @@ function Update-AllExistingAgents {
if (Test-Path $ROO_FILE) { if (-not (Update-AgentFile -TargetFile $ROO_FILE -AgentName 'Roo Code')) { $ok = $false }; $found = $true }
if (Test-Path $CODEBUDDY_FILE) { if (-not (Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI')) { $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 $CONTINUE_FILE) { if (-not (Update-AgentFile -TargetFile $CONTINUE_FILE -AgentName 'Continue')) { $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 Down
8 changes: 7 additions & 1 deletion src/specify_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ def _github_auth_headers(cli_token: str | None = None) -> dict:
"install_url": "https://ampcode.com/manual#install",
"requires_cli": True,
},
"continue": {
"name": "Continue",
"folder": ".continue/",
"install_url": None, # IDE-based
"requires_cli": False,
},
}

SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
Expand Down Expand Up @@ -865,7 +871,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, or q"),
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, q, or continue"),
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