Skip to content
Merged
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
6 changes: 5 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
cat > release_notes.md << EOF
Template release ${{ steps.get_tag.outputs.new_version }}

Updated specification-driven development templates for GitHub Copilot, Claude Code, Gemini CLI, and Cursor.
Updated specification-driven development templates for GitHub Copilot, Claude Code, Gemini CLI, Cursor and opencode.

Now includes per-script variants for POSIX shell (sh) and PowerShell (ps).

Expand All @@ -94,6 +94,8 @@ jobs:
- spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-cursor-sh-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-cursor-ps-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-opencode-sh-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-opencode-ps-${{ steps.get_tag.outputs.new_version }}.zip
EOF

echo "Generated release notes:"
Expand All @@ -114,6 +116,8 @@ jobs:
spec-kit-template-gemini-ps-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-cursor-sh-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-cursor-ps-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-opencode-sh-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-opencode-ps-${{ steps.get_tag.outputs.new_version }}.zip \
--title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md
env:
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/scripts/create-release-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -euo pipefail
# Usage: .github/workflows/scripts/create-release-packages.sh <version>
# 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 (default: all)
# AGENTS : space or comma separated subset of: claude gemini copilot opencode (default: all)
# SCRIPTS : space or comma separated subset of: sh ps (default: both)
# Examples:
# AGENTS=claude SCRIPTS=sh $0 v0.2.0
Expand Down Expand Up @@ -147,13 +147,16 @@ build_variant() {
mkdir -p "$base_dir/.qwen/commands"
generate_commands qwen md "\$ARGUMENTS" "$base_dir/.qwen/commands" "$script"
[[ -f agent_templates/qwen/QWEN.md ]] && cp agent_templates/qwen/QWEN.md "$base_dir/QWEN.md" ;;
opencode)
mkdir -p "$base_dir/.opencode/command"
generate_commands opencode md "\$ARGUMENTS" "$base_dir/.opencode/command" "$script" ;;
esac
( cd "$base_dir" && zip -r "../spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip" . )
echo "Created spec-kit-template-${agent}-${script}-${NEW_VERSION}.zip"
}

# Determine agent list
ALL_AGENTS=(claude gemini copilot cursor qwen)
ALL_AGENTS=(claude gemini copilot cursor qwen opencode)
ALL_SCRIPTS=(sh ps)

norm_list() {
Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.6] - 2025-09-17

### Added

- opencode support as additional AI assistant option

## [0.0.5] - 2025-09-17

### Added
Expand All @@ -25,4 +31,5 @@ N/A

### Changed

N/A
N/A

9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,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`) |
| `check` | Check for installed tools (`git`, `claude`, `gemini`, `code`/`code-insiders`, `opencode`, `cursor-agent`) |

### `specify init` Arguments & Options

| Argument/Option | Type | Description |
|------------------------|----------|------------------------------------------------------------------------------|
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`) |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, or `cursor` |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `opencode`, or `cursor` |
| `--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 Expand Up @@ -170,7 +170,7 @@ Our research and experimentation focus on:
## 🔧 Prerequisites

- **Linux/macOS** (or WSL2 on Windows)
- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Cursor](https://cursor.sh/), or [Qwen CLI](https://github.com/QwenLM/qwen-code)
- AI coding agent: [Claude Code](https://www.anthropic.com/claude-code), [GitHub Copilot](https://code.visualstudio.com/), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Cursor](https://cursor.sh/), [Qwen CLI](https://github.com/QwenLM/qwen-code) or [opencode](https://opencode.ai/)
- [uv](https://docs.astral.sh/uv/) for package management
- [Python 3.11+](https://www.python.org/downloads/)
- [Git](https://git-scm.com/downloads)
Expand Down Expand Up @@ -208,11 +208,12 @@ specify init <project_name> --ai claude
specify init <project_name> --ai gemini
specify init <project_name> --ai copilot
specify init <project_name> --ai qwen
specify init <project_name> --ai opencode
# Or in current directory:
specify init --here --ai claude
```

The CLI will check if you have Claude Code, Gemini CLI, or Qwen CLI 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, Qwen CLI or opencode 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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "specify-cli"
version = "0.0.5"
version = "0.0.6"
description = "Setup tool for Specify spec-driven development projects"
requires-python = ">=3.11"
dependencies = [
Expand Down
11 changes: 6 additions & 5 deletions scripts/bash/update-agent-context.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH"
NEW_PLAN="$FEATURE_DIR/plan.md"
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"; CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"; GEMINI_FILE="$REPO_ROOT/GEMINI.md"; COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"; CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"; AGENTS_FILE="$REPO_ROOT/AGENTS.md"
AGENT_TYPE="$1"
[ -f "$NEW_PLAN" ] || { echo "ERROR: No plan.md found at $NEW_PLAN"; exit 1; }
echo "=== Updating agent context files for feature $CURRENT_BRANCH ==="
Expand Down Expand Up @@ -52,11 +52,12 @@ case "$AGENT_TYPE" in
gemini) update_agent_file "$GEMINI_FILE" "Gemini CLI" ;;
copilot) update_agent_file "$COPILOT_FILE" "GitHub Copilot" ;;
cursor) update_agent_file "$CURSOR_FILE" "Cursor IDE" ;;
opencode) update_agent_file "$AGENTS_FILE" "opencode" ;;
"") [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code"; \
[ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI"; \
[ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot"; \
[ -f "$CURSOR_FILE" ] && update_agent_file "$CURSOR_FILE" "Cursor IDE"; \
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$CURSOR_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
*) echo "ERROR: Unknown agent type '$AGENT_TYPE' (expected claude|gemini|copilot|cursor)"; exit 1 ;;
esac
echo; echo "Summary of changes:"; [ -n "$NEW_LANG" ] && echo "- Added language: $NEW_LANG"; [ -n "$NEW_FRAMEWORK" ] && echo "- Added framework: $NEW_FRAMEWORK"; [ -n "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ] && echo "- Added database: $NEW_DB"; echo; echo "Usage: $0 [claude|gemini|copilot|cursor]"
[ -f "$AGENTS_FILE" ] && update_agent_file "$AGENTS_FILE" "opencode"; \
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$CURSOR_FILE" ] && [ ! -f "$AGENTS_FILE" ]; then update_agent_file "$CLAUDE_FILE" "Claude Code"; fi ;;
*) echo "ERROR: Unknown agent type '$AGENT_TYPE' (expected claude|gemini|copilot|cursor|opencode)"; exit 1 ;;
echo; echo "Summary of changes:"; [ -n "$NEW_LANG" ] && echo "- Added language: $NEW_LANG"; [ -n "$NEW_FRAMEWORK" ] && echo "- Added framework: $NEW_FRAMEWORK"; [ -n "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ] && echo "- Added database: $NEW_DB"; echo; echo "Usage: $0 [claude|gemini|copilot|cursor|opencode]"
9 changes: 6 additions & 3 deletions scripts/powershell/update-agent-context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ $claudeFile = Join-Path $repoRoot 'CLAUDE.md'
$geminiFile = Join-Path $repoRoot 'GEMINI.md'
$copilotFile = Join-Path $repoRoot '.github/copilot-instructions.md'
$cursorFile = Join-Path $repoRoot '.cursor/rules/specify-rules.mdc'
$agentsFile = Join-Path $repoRoot 'AGENTS.md'

Write-Output "=== Updating agent context files for feature $currentBranch ==="

Expand Down Expand Up @@ -71,21 +72,23 @@ switch ($AgentType) {
'gemini' { Update-AgentFile $geminiFile 'Gemini CLI' }
'copilot' { Update-AgentFile $copilotFile 'GitHub Copilot' }
'cursor' { Update-AgentFile $cursorFile 'Cursor IDE' }
'opencode' { Update-AgentFile $agentsFile 'opencode' }
'' {
foreach ($pair in @(
@{file=$claudeFile; name='Claude Code'},
@{file=$geminiFile; name='Gemini CLI'},
@{file=$copilotFile; name='GitHub Copilot'},
@{file=$cursorFile; name='Cursor IDE'}
@{file=$agentsFile; name='opencode'}
)) {
if (Test-Path $pair.file) { Update-AgentFile $pair.file $pair.name }
}
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile) -and -not (Test-Path $cursorFile)) {
if (-not (Test-Path $claudeFile) -and -not (Test-Path $geminiFile) -and -not (Test-Path $copilotFile) -and -not (Test-Path $cursorFile) -and -not (Test-Path $agentsFile)) {
Write-Output 'No agent context files found. Creating Claude Code context file by default.'
Update-AgentFile $claudeFile 'Claude Code'
}
}
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, cursor or leave empty for all."; exit 1 }
Default { Write-Error "ERROR: Unknown agent type '$AgentType'. Use: claude, gemini, copilot, cursor, opencode or leave empty for all."; exit 1 }
}

Write-Output ''
Expand All @@ -95,4 +98,4 @@ if ($newFramework) { Write-Output "- Added framework: $newFramework" }
if ($newDb -and $newDb -ne 'N/A') { Write-Output "- Added database: $newDb" }

Write-Output ''
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot|cursor]'
Write-Output 'Usage: ./update-agent-context.ps1 [claude|gemini|copilot|cursor|opencode]'
21 changes: 17 additions & 4 deletions src/specify_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"claude": "Claude Code",
"gemini": "Gemini CLI",
"cursor": "Cursor",
"qwen": "Qwen Code"
"qwen": "Qwen Code",
"opencode": "opencode"
}
# Add script type choices
SCRIPT_TYPE_CHOICES = {"sh": "POSIX Shell (bash/zsh)", "ps": "PowerShell"}
Expand Down Expand Up @@ -723,7 +724,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)"),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor, or qwen"),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor, qwen or opencode"),
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 All @@ -736,7 +737,7 @@ def init(

This command will:
1. Check that required tools are installed (git is optional)
2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, Cursor, or Qwen Code)
2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, Cursor, Qwen Code or opencode)
3. Download the appropriate template from GitHub
4. Extract the template to a new project directory or current directory
5. Initialize a fresh git repository (if not --no-git and no existing repo)
Expand All @@ -749,6 +750,7 @@ def init(
specify init my-project --ai copilot --no-git
specify init my-project --ai cursor
specify init my-project --ai qwen
specify init my-project --ai opencode
specify init --ignore-agent-tools my-project
specify init --here --ai claude
specify init --here
Expand Down Expand Up @@ -832,6 +834,10 @@ def init(
if not check_tool("qwen", "Install from: https://github.com/QwenLM/qwen-code"):
console.print("[red]Error:[/red] Qwen CLI is required for Qwen Code projects")
agent_tool_missing = True
elif selected_ai == "opencode":
if not check_tool("opencode", "Install from: https://opencode.ai"):
console.print("[red]Error:[/red] opencode CLI is required for opencode projects")
agent_tool_missing = True
# GitHub Copilot and Cursor checks are not needed as they're typically available in supported IDEs

if agent_tool_missing:
Expand Down Expand Up @@ -964,6 +970,11 @@ def init(
steps_lines.append(" - Run qwen /plan to create implementation plans")
steps_lines.append(" - Run qwen /tasks to generate tasks")
steps_lines.append(" - See QWEN.md for all available commands")
elif selected_ai == "opencode":
steps_lines.append(f"{step_num}. Use / commands with opencode")
steps_lines.append(" - Use /specify to create specifications")
steps_lines.append(" - Use /plan to create implementation plans")
steps_lines.append(" - Use /tasks to generate tasks")

# Removed script variant step (scripts are transparent to users)
step_num += 1
Expand Down Expand Up @@ -992,6 +1003,7 @@ def check():
tracker.add("qwen", "Qwen Code CLI")
tracker.add("code", "VS Code (for GitHub Copilot)")
tracker.add("cursor-agent", "Cursor IDE agent (optional)")
tracker.add("opencode", "opencode")

# Check each tool
git_ok = check_tool_for_tracker("git", "https://git-scm.com/downloads", tracker)
Expand All @@ -1003,6 +1015,7 @@ def check():
if not code_ok:
code_ok = check_tool_for_tracker("code-insiders", "https://code.visualstudio.com/insiders/", tracker)
cursor_ok = check_tool_for_tracker("cursor-agent", "https://cursor.sh/", tracker)
opencode_ok = check_tool_for_tracker("opencode", "https://opencode.ai/", tracker)

# Render the final tree
console.print(tracker.render())
Expand All @@ -1013,7 +1026,7 @@ def check():
# Recommendations
if not git_ok:
console.print("[dim]Tip: Install git for repository management[/dim]")
if not (claude_ok or gemini_ok or qwen_ok):
if not (claude_ok or gemini_ok or cursor_ok or qwen_ok or opencode_ok):
console.print("[dim]Tip: Install an AI assistant for the best experience[/dim]")


Expand Down
4 changes: 2 additions & 2 deletions templates/plan-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ scripts:
→ Update Progress Tracking: Initial Constitution Check
5. Execute Phase 0 → research.md
→ If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, or `QWEN.md` for Qwen Code).
6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, `QWEN.md` for Qwen Code or `AGENTS.md` for opencode).
7. Re-evaluate Constitution Check section
→ If new violations: Refactor design, return to Phase 1
→ Update Progress Tracking: Post-Design Constitution Check
Expand Down Expand Up @@ -214,4 +214,4 @@ ios/ or android/
- [ ] Complexity deviations documented

---
*Based on Constitution v2.1.1 - See `/memory/constitution.md`*
*Based on Constitution v2.1.1 - See `/memory/constitution.md`*