diff --git a/.github/workflows/manual-release.yml b/.github/workflows/manual-release.yml index 02515174..76478118 100644 --- a/.github/workflows/manual-release.yml +++ b/.github/workflows/manual-release.yml @@ -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 .. @@ -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: | @@ -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 @@ -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: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c1ebfbc7..17d470ab 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -146,6 +146,18 @@ 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 .. @@ -153,6 +165,8 @@ jobs: 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 @@ -160,6 +174,8 @@ jobs: 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' @@ -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:" @@ -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: diff --git a/README.md b/README.md index 25953917..643f1ff1 100644 --- a/README.md +++ b/README.md @@ -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) @@ -147,11 +147,12 @@ You will be prompted to select the AI agent you are using. You can also proactiv specify init --ai claude specify init --ai gemini specify init --ai copilot +specify init --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 --ai claude --ignore-agent-tools diff --git a/scripts/update-agent-context.sh b/scripts/update-agent-context.sh index 21b77aaa..c9bf5cb8 100755 --- a/scripts/update-agent-context.sh +++ b/scripts/update-agent-context.sh @@ -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 @@ -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" @@ -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 @@ -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" \ No newline at end of file +echo " - copilot: Update only .github/copilot-instructions.md" +echo " - rovodevcli: Update only agent.md" \ No newline at end of file diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index aa3cf3c8..39950222 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -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 @@ -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] + 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]") + + 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"] @@ -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"), @@ -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) @@ -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 @@ -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"): + console.print("[red]Error:[/red] Rovo Dev CLI is required for Rovo Dev CLI projects") + agent_tool_missing = True # GitHub Copilot check is not needed as it's typically available in supported IDEs if agent_tool_missing: @@ -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") @@ -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]")