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
22 changes: 19 additions & 3 deletions .github/workflows/manual-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ jobs:
echo "⚠️ agent_templates/copilot folder not found"
fi

# Create Rovo Dev CLI package
echo "Creating Rovo Dev CLI package..."
mkdir -p sdd-rovodevcli-package
cp -r sdd-package-base/* sdd-rovodevcli-package/
if [ -d "agent_templates/rovodevcli" ]; then
cp agent_templates/rovodevcli/agent.md sdd-rovodevcli-package/
echo "✓ Added Rovo Dev CLI agent file ($(find agent_templates/rovodevcli -type f | wc -l) files)"
else
echo "⚠️ agent_templates/rovodevcli folder not found"
fi
echo "✓ Created Rovo Dev CLI package"

# Create archive files for each package
echo "Creating archive files..."
cd sdd-claude-package && zip -r ../spec-kit-template-claude-${{ steps.version.outputs.new_version }}.zip . && cd ..
Expand All @@ -134,12 +146,14 @@ jobs:

cd sdd-copilot-package && zip -r ../spec-kit-template-copilot-${{ steps.version.outputs.new_version }}.zip . && cd ..

cd sdd-rovodevcli-package && zip -r ../spec-kit-template-rovodevcli-${{ steps.version.outputs.new_version }}.zip . && cd ..

echo ""
echo "📦 Packages created:"
echo "Claude: $(ls -lh spec-kit-template-claude-*.zip | awk '{print $5}')"
echo "Gemini: $(ls -lh spec-kit-template-gemini-*.zip | awk '{print $5}')"
echo "Copilot: $(ls -lh spec-kit-template-copilot-*.zip | awk '{print $5}')"
echo "Copilot: $(ls -lh sdd-template-copilot-*.zip | awk '{print $5}')"
echo "Rovo Dev CLI: $(ls -lh spec-kit-template-rovodevcli-*.zip | awk '{print $5}')"

- name: Generate detailed release notes
run: |
Expand All @@ -164,12 +178,13 @@ jobs:
cat > release_notes.md << EOF
Template release ${{ steps.version.outputs.new_version }}

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

Download the template for your preferred AI assistant:
- spec-kit-template-copilot-${{ steps.version.outputs.new_version }}.zip
- spec-kit-template-claude-${{ steps.version.outputs.new_version }}.zip
- spec-kit-template-gemini-${{ steps.version.outputs.new_version }}.zip
- spec-kit-template-gemini-${{ steps.version.outputs.new_version }}.zip
- spec-kit-template-rovodevcli-${{ steps.version.outputs.new_version }}.zip

Changes since $LAST_TAG:
$COMMITS
Expand All @@ -185,6 +200,7 @@ jobs:
spec-kit-template-copilot-${{ steps.version.outputs.new_version }}.zip \
spec-kit-template-claude-${{ steps.version.outputs.new_version }}.zip \
spec-kit-template-gemini-${{ steps.version.outputs.new_version }}.zip \
spec-kit-template-rovodevcli-${{ steps.version.outputs.new_version }}.zip \
--title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md
env:
Expand Down
22 changes: 20 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,36 @@ jobs:
generate_commands "copilot" "prompt.md" "\$ARGUMENTS" "sdd-copilot-package/.github/prompts"
echo "Created GitHub Copilot package"

# Create Rovo Dev CLI package
echo "Creating Rovo Dev CLI package..."
mkdir -p sdd-rovodevcli-package
cp -r sdd-package-base/* sdd-rovodevcli-package/
if [ -d "agent_templates/rovodevcli" ]; then
cp agent_templates/rovodevcli/agent.md sdd-rovodevcli-package/
echo "✓ Added Rovo Dev CLI agent file"
else
echo "⚠️ agent_templates/rovodevcli folder not found"
fi
echo "✓ Created Rovo Dev CLI package"

# Create archive files for each package
cd sdd-claude-package && zip -r ../spec-kit-template-claude-${{ steps.get_tag.outputs.new_version }}.zip . && cd ..

cd sdd-gemini-package && zip -r ../spec-kit-template-gemini-${{ steps.get_tag.outputs.new_version }}.zip . && cd ..

cd sdd-copilot-package && zip -r ../spec-kit-template-copilot-${{ steps.get_tag.outputs.new_version }}.zip . && cd ..

cd sdd-rovodevcli-package && zip -r ../spec-kit-template-rovodevcli-${{ steps.get_tag.outputs.new_version }}.zip . && cd ..

# List contents for verification
echo "Claude package contents:"
unzip -l spec-kit-template-claude-${{ steps.get_tag.outputs.new_version }}.zip | head -10
echo "Gemini package contents:"
unzip -l spec-kit-template-gemini-${{ steps.get_tag.outputs.new_version }}.zip | head -10
echo "Copilot package contents:"
unzip -l spec-kit-template-copilot-${{ steps.get_tag.outputs.new_version }}.zip | head -10
echo "Rovo Dev CLI package contents:"
unzip -l spec-kit-template-rovodevcli-${{ steps.get_tag.outputs.new_version }}.zip | head -10

- name: Generate release notes
if: steps.check_release.outputs.exists == 'false'
Expand All @@ -183,12 +199,13 @@ jobs:
cat > release_notes.md << EOF
Template release ${{ steps.get_tag.outputs.new_version }}

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

Download the template for your preferred AI assistant:
- spec-kit-template-copilot-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-claude-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-gemini-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-gemini-${{ steps.get_tag.outputs.new_version }}.zip
- spec-kit-template-rovodevcli-${{ steps.get_tag.outputs.new_version }}.zip
EOF

echo "Generated release notes:"
Expand All @@ -205,6 +222,7 @@ jobs:
spec-kit-template-copilot-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-claude-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-gemini-${{ steps.get_tag.outputs.new_version }}.zip \
spec-kit-template-rovodevcli-${{ steps.get_tag.outputs.new_version }}.zip \
--title "Spec Kit Templates - $VERSION_NO_V" \
--notes-file release_notes.md
env:
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,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/), or [Gemini CLI](https://github.com/google-gemini/gemini-cli)
- 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), or [Rovo Dev CLI](https://support.atlassian.com/rovo/docs/install-and-run-rovo-dev-cli-on-your-device/)
- [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 @@ -147,11 +147,12 @@ You will be prompted to select the AI agent you are using. You can also proactiv
specify init <project_name> --ai claude
specify init <project_name> --ai gemini
specify init <project_name> --ai copilot
specify init <project_name> --ai rovodevcli
# Or in current directory:
specify init --here --ai claude
```

The CLI will check if you have Claude Code or Gemini 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, Rovo Dev 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:

```bash
specify init <project_name> --ai claude --ignore-agent-tools
Expand Down
16 changes: 11 additions & 5 deletions scripts/update-agent-context.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Incrementally update agent context files based on new feature plan
# Supports: CLAUDE.md, GEMINI.md, and .github/copilot-instructions.md
# Supports: CLAUDE.md, GEMINI.md, agent.md (Rovo Dev CLI) and .github/copilot-instructions.md
# O(1) operation - only reads current context file and new plan.md

set -e
Expand All @@ -14,6 +14,7 @@ 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"
ROVODEV_FILE="$REPO_ROOT/agent.md"

# Allow override via argument
AGENT_TYPE="$1"
Expand Down Expand Up @@ -197,20 +198,24 @@ case "$AGENT_TYPE" in
"copilot")
update_agent_file "$COPILOT_FILE" "GitHub Copilot"
;;
"rovodevcli")
update_agent_file "$ROVODEV_FILE" "Rovo Dev CLI"
;;
"")
# Update all existing files
[ -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 "$ROVODEV_FILE" ] && update_agent_file "$ROVODEV_FILE" "Rovo Dev CLI"

# If no files exist, create based on current directory or ask user
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ]; then
if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ] && [ ! -f "$ROVODEV_FILE" ]; then
echo "No agent context files found. Creating Claude Code context file by default."
update_agent_file "$CLAUDE_FILE" "Claude Code"
fi
;;
*)
echo "ERROR: Unknown agent type '$AGENT_TYPE'. Use: claude, gemini, copilot, or leave empty for all."
echo "ERROR: Unknown agent type '$AGENT_TYPE'. Use: claude, gemini, copilot, rovodevcli or leave empty for all."
exit 1
;;
esac
Expand All @@ -227,8 +232,9 @@ if [ ! -z "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ]; then
fi

echo ""
echo "Usage: $0 [claude|gemini|copilot]"
echo "Usage: $0 [claude|gemini|copilot|rovodevcli]"
echo " - No argument: Update all existing agent context files"
echo " - claude: Update only CLAUDE.md"
echo " - gemini: Update only GEMINI.md"
echo " - copilot: Update only .github/copilot-instructions.md"
echo " - copilot: Update only .github/copilot-instructions.md"
echo " - rovodevcli: Update only agent.md"
54 changes: 38 additions & 16 deletions src/specify_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
AI_CHOICES = {
"copilot": "GitHub Copilot",
"claude": "Claude Code",
"gemini": "Gemini CLI"
"gemini": "Gemini CLI",
"rovodevcli": "Rovo Dev CLI",
}

# ASCII Art Banner
Expand Down Expand Up @@ -405,23 +406,30 @@ def download_template_from_github(ai_assistant: str, download_dir: Path, *, verb
console.print(f"[red]Error fetching release information:[/red] {e}")
raise typer.Exit(1)

# Find the template asset for the specified AI assistant
# Find the template asset for the specified AI assistant, with fallback for 'rovodevcli' -> 'copilot'
pattern = f"spec-kit-template-{ai_assistant}"
matching_assets = [
asset for asset in release_data.get("assets", [])
if pattern in asset["name"] and asset["name"].endswith(".zip")
]

if not matching_assets:
assets = release_data.get("assets", [])
matching_assets = [a for a in assets if pattern in a["name"] and a["name"].endswith(".zip")]

asset = None
if matching_assets:
asset = matching_assets[0]
Copy link
Preview

Copilot AI Sep 11, 2025

Choose a reason for hiding this comment

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

The fallback logic for rovodevcli -> copilot template mentioned in the comment is not implemented. The code should attempt to find the copilot template when rovodevcli template is not found.

Suggested change
asset = matching_assets[0]
asset = matching_assets[0]
# Fallback: if rovodevcli not found, try copilot
if asset is None and ai_assistant == "rovodevcli":
fallback_pattern = "spec-kit-template-copilot"
fallback_assets = [a for a in assets if fallback_pattern in a["name"] and a["name"].endswith(".zip")]
if fallback_assets:
asset = fallback_assets[0]
if verbose:
console.print("[yellow]Falling back to 'copilot' template as 'rovodevcli' template was not found.[/yellow]")

Copilot uses AI. Check for mistakes.

elif ai_assistant == "rovodevcli":
# Fallback to copilot template if rovodevcli-specific template is not published yet
fallback_pattern = "spec-kit-template-copilot"
fallback_assets = [a for a in assets if fallback_pattern in a["name"] and a["name"].endswith(".zip")]
if fallback_assets:
asset = fallback_assets[0]
if verbose:
console.print("[yellow]No 'rovodevcli' template found; falling back to 'copilot' template.[/yellow]")
Comment on lines +417 to +424
Copy link
Preview

Copilot AI Sep 11, 2025

Choose a reason for hiding this comment

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

[nitpick] The fallback logic is hardcoded specifically for "rovodevcli". Consider extracting this into a configurable fallback mapping (e.g., FALLBACK_TEMPLATES = {"rovodevcli": "copilot"}) to make it more maintainable and extensible for future AI assistants that might need fallbacks.

Copilot uses AI. Check for mistakes.


if asset is None:
if verbose:
console.print(f"[red]Error:[/red] No template found for AI assistant '{ai_assistant}'")
console.print(f"[yellow]Available assets:[/yellow]")
for asset in release_data.get("assets", []):
console.print(f" - {asset['name']}")
for a in assets:
console.print(f" - {a['name']}")
raise typer.Exit(1)

# Use the first matching asset
asset = matching_assets[0]
download_url = asset["browser_download_url"]
filename = asset["name"]
file_size = asset["size"]
Expand Down Expand Up @@ -638,7 +646,7 @@ def download_and_extract_template(project_path: Path, ai_assistant: str, is_curr
@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, or copilot"),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, or rovodevcli"),
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"),
here: bool = typer.Option(False, "--here", help="Initialize project in the current directory instead of creating a new one"),
Expand All @@ -648,7 +656,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, or GitHub Copilot)
2. Let you choose your AI assistant (Claude Code, Gemini CLI, GitHub Copilot, or Rovo Dev CLI)
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 @@ -659,8 +667,10 @@ def init(
specify init my-project --ai claude
specify init my-project --ai gemini
specify init my-project --ai copilot --no-git
specify init my-project --ai rovodevcli
specify init --ignore-agent-tools my-project
specify init --here --ai claude
specify init --here --ai rovodevcli
specify init --here
"""
# Show banner first
Expand Down Expand Up @@ -737,6 +747,10 @@ def init(
if not check_tool("gemini", "Install from: https://github.com/google-gemini/gemini-cli"):
console.print("[red]Error:[/red] Gemini CLI is required for Gemini projects")
agent_tool_missing = True
elif selected_ai == "rovodevcli":
if not check_tool("acli", "Install from: https://support.atlassian.com/rovo/docs/install-and-run-rovo-dev-cli-on-your-device"):
Copy link
Preview

Copilot AI Sep 10, 2025

Choose a reason for hiding this comment

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

[nitpick] The URL is quite long and makes the line exceed reasonable length limits. Consider storing the installation URL in a constant or variable for better readability.

Copilot uses AI. Check for mistakes.

console.print("[red]Error:[/red] Rovo Dev CLI is required for Rovo Dev CLI projects")
Copy link
Preview

Copilot AI Sep 11, 2025

Choose a reason for hiding this comment

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

The error message "Rovo Dev CLI is required for Rovo Dev CLI projects" is redundant. Consider changing to "Rovo Dev CLI (acli) is required for Rovo Dev projects" to be more informative and consistent with other error messages.

Suggested change
console.print("[red]Error:[/red] Rovo Dev CLI is required for Rovo Dev CLI projects")
console.print("[red]Error:[/red] Rovo Dev CLI (acli) is required for Rovo Dev projects")

Copilot uses AI. Check for mistakes.

agent_tool_missing = True
# GitHub Copilot check is not needed as it's typically available in supported IDEs

if agent_tool_missing:
Expand Down Expand Up @@ -823,6 +837,12 @@ def init(
steps_lines.append(" - See GEMINI.md for all available commands")
elif selected_ai == "copilot":
steps_lines.append(f"{step_num}. Open in Visual Studio Code and use [bold cyan]/specify[/], [bold cyan]/plan[/], [bold cyan]/tasks[/] commands with GitHub Copilot")
elif selected_ai == "rovodevcli":
steps_lines.append(f"{step_num}. Use / commands with Rovo Dev CLI")
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")
steps_lines.append(" - See agent.md for all available commands")

step_num += 1
steps_lines.append(f"{step_num}. Update [bold magenta]CONSTITUTION.md[/bold magenta] with your project's non-negotiable principles")
Expand Down Expand Up @@ -855,11 +875,13 @@ def check():
console.print("\n[cyan]Optional AI tools:[/cyan]")
claude_ok = check_tool("claude", "Install from: https://docs.anthropic.com/en/docs/claude-code/setup")
gemini_ok = check_tool("gemini", "Install from: https://github.com/google-gemini/gemini-cli")
rovodevcli_ok = check_tool("acli", "Install from: https://support.atlassian.com/rovo/docs/install-and-run-rovo-dev-cli-on-your-device")


console.print("\n[green]✓ Specify CLI is ready to use![/green]")
if not git_ok:
console.print("[yellow]Consider installing git for repository management[/yellow]")
if not (claude_ok or gemini_ok):
if not (claude_ok or gemini_ok or rovodevcli_ok):
console.print("[yellow]Consider installing an AI assistant for the best experience[/yellow]")


Expand Down