Add back post-revert bug fixes and features (Step 2) (#11463)

* fix: cancel backend auto-approval timeout when auto-approve is toggled off mid-countdown (#11439)

Co-authored-by: Sannidhya <sann@Sannidhyas-MacBook-Pro.local>

* fix: prevent chat history loss during cloud/settings navigation (#11371) (#11372)

Co-authored-by: Sannidhya <sann@Sannidhyas-MacBook-Pro.local>

* fix: preserve pasted images in chatbox during chat activity (#11375)

Co-authored-by: Roo Code <roomote@roocode.com>

* fix: resolve chat scroll anchoring and task-switch scroll race condit… (#11385)

* fix: avoid zsh process-substitution false positives in assignments (#11365)

* fix(editor): make tab close best-effort in DiffViewProvider.open (#11363)

* fix(checkpoints): canonicalize core.worktree comparison to prevent Windows path mismatch failures (#11346)

* fix: prevent double notification sound playback (#11283)

* fix: prevent false unsaved changes prompt with OpenAI Compatible headers (#8230) (#11334)

fix: prevent false unsaved changes prompt with OpenAI Compatible headers

Mark automatic header syncs in ApiOptions and OpenAICompatible as
non-user actions (isUserAction: false) and enhance SettingsView change
detection to skip automatic syncs with semantically equal values.

Root cause: two components (ApiOptions and OpenAICompatible) manage
openAiHeaders state and automatically sync it back on mount/remount.
These syncs were treated as user changes, triggering a false dirty state.

Co-authored-by: Robert McIntyre <robertjmcintyre@users.noreply.github.com>

* fix: remove noisy console.warn logs from NativeToolCallParser (#11264)

Remove two console.warn messages that fire excessively when loading tasks
from history:
- 'Attempting to finalize unknown tool call' in finalizeStreamingToolCall()
- 'Received chunk for unknown tool call' in processStreamingChunk()

The defensive null-return behavior is preserved; only the log output is removed.

* refactor: remove footgun prompting (file-based system prompt override) (#11387)

* refactor: delete orphaned per-provider caching transform files (#11388)

* feat: add disabledTools setting to globally disable native tools (#11277)

* feat: add disabledTools setting to globally disable native tools

Add a disabledTools field to GlobalSettings that allows disabling specific
native tools by name. This enables cloud agents to be configured with
restricted tool access.

Schema:
- Add disabledTools: z.array(toolNamesSchema).optional() to globalSettingsSchema
- Add disabledTools to organizationDefaultSettingsSchema.pick()
- Add disabledTools to ExtensionState Pick type

Prompt generation (tool filtering):
- Add disabledTools to BuildToolsOptions interface
- Pass disabledTools through filterSettings to filterNativeToolsForMode()
- Remove disabled tools from allowedToolNames set in filterNativeToolsForMode()

Execution-time validation (safety net):
- Extract disabledTools from state in presentAssistantMessage
- Convert disabledTools to toolRequirements format for validateToolUse()

Wiring:
- Add disabledTools to ClineProvider getState() and getStateToPostToWebview()
- Pass disabledTools to all buildNativeToolsArrayWithRestrictions() call sites

EXT-778

* fix: check toolRequirements before ALWAYS_AVAILABLE_TOOLS

Moves the toolRequirements check before the ALWAYS_AVAILABLE_TOOLS
early-return in isToolAllowedForMode(). This ensures disabledTools
can block always-available tools (switch_mode, new_task, etc.) at
execution time, making the validation layer consistent with the
filtering layer.

* feat: add support for .agents/skills directory (#11181)

* feat: add support for .agents/skills directory

This change adds support for discovering skills from the .agents/skills
directory, following the Agent Skills convention for sharing skills
across different AI coding tools.

Priority order (later entries override earlier ones):
1. Global ~/.agents/skills (shared across AI coding tools, lowest priority)
2. Project .agents/skills
3. Global ~/.roo/skills (Roo-specific)
4. Project .roo/skills (highest priority)

Changes:
- Add getGlobalAgentsDirectory() and getProjectAgentsDirectoryForCwd()
  functions to roo-config
- Update SkillsManager.getSkillsDirectories() to include .agents/skills
- Update SkillsManager.setupFileWatchers() to watch .agents/skills
- Add tests for new functionality

* fix: clarify skill priority comment to match actual behavior

* fix: clarify skill priority comment to explain Map.set replacement mechanism

---------

Co-authored-by: Roo Code <roomote@roocode.com>

* feat(history): render nested subtasks as recursive tree (#11299)

* feat(history): render nested subtasks as recursive tree

* fix(lockfile): resolve missing ai-sdk provider entry

* fix: address review feedback — dedupe countAll, increase SubtaskRow max-h

- HistoryView: replace local countAll with imported countAllSubtasks from types.ts
- SubtaskRow: increase nested children max-h from 500px to 2000px to match TaskGroupItem

* perf(refactor): consolidate getState calls in resolveWebviewView (#11320)

* perf(refactor): consolidate getState calls in resolveWebviewView

Replace three separate this.getState().then() calls with a single
await this.getState() and destructuring. This avoids running the
full getState() method (CloudService calls, ContextProxy reads, etc.)
three times during webview view resolution.

* fix: keep getState consolidation non-blocking to avoid delaying webview render

---------

Co-authored-by: daniel-lxs <ricciodaniel98@gmail.com>

* fix: harden command auto-approval against inline JS false positives (#11382)

* feat: rename search_and_replace tool to edit and unify edit-family UI (#11296)

* Revert "refactor: delete orphaned per-provider caching transform files (#11388)"

This reverts commit 13a45b0361.

* chore: regenerate built-in-skills.ts with updated formatting

* fix: add missing maxReadFileLine property to test baseState

The ExtensionState type now requires maxReadFileLine property (added in commit 63e3f769a).
Update the test to include this property with the default value of -1 (unlimited reading).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* feat: add pnpm serve command for code-server development (#10964)

Co-authored-by: Roo Code <roomote@roocode.com>

* chore: remove Feature Request from issue template options (#11141)

Co-authored-by: Roo Code <roomote@roocode.com>

* refactor(docs-extractor): simplify mode to focus on raw fact extraction (#11129)

* Add cli support for linux (#11167)

* fix: replace heredocs with echo statements in cli-release workflow (#11168)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Drop MacOS-13 cli support (#11169)

* fix(cli): correct example in install script (#11170)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add Kimi K2.5 model to Fireworks provider (#11177)

* feat(cli): improve dev experience and roo provider API key support (#11203)

- Allow --api-key and ROO_API_KEY env var for the roo provider instead of
  requiring cloud auth token
- Switch dev/start scripts to use tsx for running directly from source
  without building first
- Fix path resolution (version.ts, extension.ts, extension-host.ts) to
  work from both source and bundled locations
- Disable debug log file (~/.roo/cli-debug.log) unless --debug is passed
- Update README with complete env var table and dev workflow docs

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Roo Code CLI v0.0.50 (#11204)

* Roo Code CLI v0.0.50

* docs(cli): add --exit-on-error to changelog

---------

Co-authored-by: Roo Code <roomote@roocode.com>

* feat(cli): update default model from Opus 4.5 to Opus 4.6 (#11273)

Co-authored-by: Roo Code <roomote@roocode.com>

* feat(web): replace Roomote Control with Linear Integration in cloud features grid (#11280)

Co-authored-by: Roo Code <roomote@roocode.com>

* Add linux-arm64 for the roo cli (#11314)

* chore: clean up repo-facing mode rules (#11410)

* Make CLI auto-approve by default with require-approval opt-in (#11424)

Co-authored-by: Roo Code <roomote@roocode.com>

* Add new code owners to CODEOWNERS file

* Update next.js (#11108)

* feat(web): Replace bespoke navigation menu with shadcn navigation menu (#11117)

Co-authored-by: Roo Code <roomote@roocode.com>

---------

Co-authored-by: SannidhyaSah <sah_sannidhya@outlook.com>
Co-authored-by: Sannidhya <sann@Sannidhyas-MacBook-Pro.local>
Co-authored-by: roomote[bot] <219738659+roomote[bot]@users.noreply.github.com>
Co-authored-by: Roo Code <roomote@roocode.com>
Co-authored-by: Hannes Rudolph <hrudolph@gmail.com>
Co-authored-by: 0xMink <dennis@dennismink.com>
Co-authored-by: Robert McIntyre <robertjmcintyre@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
Co-authored-by: Chris Estreich <cestreich@gmail.com>
This commit is contained in:
Daniel 2026-02-13 18:40:28 -05:00 committed by GitHub
parent 594ed62f96
commit d52b6834e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
199 changed files with 7225 additions and 9347 deletions

View file

@ -1,8 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Feature Request
url: https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests
about: Share and vote on feature requests for Roo Code
- name: Leave a Review
url: https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline&ssr=false#review-details
about: Enjoying Roo Code? Leave a review here!

394
.github/workflows/cli-release.yml vendored Normal file
View file

@ -0,0 +1,394 @@
name: CLI Release
on:
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.1.0). Leave empty to use package.json version.'
required: false
type: string
dry_run:
description: 'Dry run (build and test but do not create release).'
required: false
type: boolean
default: false
jobs:
# Build CLI for each platform.
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
platform: darwin-arm64
runs-on: macos-latest
- os: ubuntu-latest
platform: linux-x64
runs-on: ubuntu-latest
- os: ubuntu-24.04-arm
platform: linux-arm64
runs-on: ubuntu-24.04-arm
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Get version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./apps/cli/package.json').version")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
echo "Using version: $VERSION"
- name: Build extension bundle
run: pnpm bundle
- name: Build CLI
run: pnpm --filter @roo-code/cli build
- name: Create release tarball
id: tarball
env:
VERSION: ${{ steps.version.outputs.version }}
PLATFORM: ${{ matrix.platform }}
run: |
RELEASE_DIR="roo-cli-${PLATFORM}"
TARBALL="roo-cli-${PLATFORM}.tar.gz"
# Clean up any previous build.
rm -rf "$RELEASE_DIR"
rm -f "$TARBALL"
# Create directory structure.
mkdir -p "$RELEASE_DIR/bin"
mkdir -p "$RELEASE_DIR/lib"
mkdir -p "$RELEASE_DIR/extension"
# Copy CLI dist files.
echo "Copying CLI files..."
cp -r apps/cli/dist/* "$RELEASE_DIR/lib/"
# Create package.json for npm install.
echo "Creating package.json..."
node -e "
const pkg = require('./apps/cli/package.json');
const newPkg = {
name: '@roo-code/cli',
version: '$VERSION',
type: 'module',
dependencies: {
'@inkjs/ui': pkg.dependencies['@inkjs/ui'],
'@trpc/client': pkg.dependencies['@trpc/client'],
'commander': pkg.dependencies.commander,
'fuzzysort': pkg.dependencies.fuzzysort,
'ink': pkg.dependencies.ink,
'p-wait-for': pkg.dependencies['p-wait-for'],
'react': pkg.dependencies.react,
'superjson': pkg.dependencies.superjson,
'zustand': pkg.dependencies.zustand
}
};
console.log(JSON.stringify(newPkg, null, 2));
" > "$RELEASE_DIR/package.json"
# Copy extension bundle.
echo "Copying extension bundle..."
cp -r src/dist/* "$RELEASE_DIR/extension/"
# Add package.json to extension directory for CommonJS.
echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
# Find and copy ripgrep binary.
echo "Looking for ripgrep binary..."
RIPGREP_PATH=$(find node_modules -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
echo "Found ripgrep at: $RIPGREP_PATH"
mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
mkdir -p "$RELEASE_DIR/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
chmod +x "$RELEASE_DIR/bin/rg"
else
echo "Warning: ripgrep binary not found"
fi
# Create the wrapper script
echo "Creating wrapper script..."
printf '%s\n' '#!/usr/bin/env node' \
'' \
"import { fileURLToPath } from 'url';" \
"import { dirname, join } from 'path';" \
'' \
'const __filename = fileURLToPath(import.meta.url);' \
'const __dirname = dirname(__filename);' \
'' \
'// Set environment variables for the CLI' \
"process.env.ROO_CLI_ROOT = join(__dirname, '..');" \
"process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');" \
"process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');" \
'' \
'// Import and run the actual CLI' \
"await import(join(__dirname, '..', 'lib', 'index.js'));" \
> "$RELEASE_DIR/bin/roo"
chmod +x "$RELEASE_DIR/bin/roo"
# Create empty .env file.
touch "$RELEASE_DIR/.env"
# Create tarball.
echo "Creating tarball..."
tar -czvf "$TARBALL" "$RELEASE_DIR"
# Clean up release directory.
rm -rf "$RELEASE_DIR"
# Create checksum.
if command -v sha256sum &> /dev/null; then
sha256sum "$TARBALL" > "${TARBALL}.sha256"
elif command -v shasum &> /dev/null; then
shasum -a 256 "$TARBALL" > "${TARBALL}.sha256"
fi
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
echo "Created: $TARBALL"
ls -la "$TARBALL"
- name: Verify tarball
env:
PLATFORM: ${{ matrix.platform }}
run: |
TARBALL="roo-cli-${PLATFORM}.tar.gz"
# Create temp directory for verification.
VERIFY_DIR=$(mktemp -d)
# Extract and verify structure.
tar -xzf "$TARBALL" -C "$VERIFY_DIR"
echo "Verifying tarball contents..."
ls -la "$VERIFY_DIR/roo-cli-${PLATFORM}/"
# Check required files exist.
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/bin/roo" || { echo "Missing bin/roo"; exit 1; }
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/lib/index.js" || { echo "Missing lib/index.js"; exit 1; }
test -f "$VERIFY_DIR/roo-cli-${PLATFORM}/package.json" || { echo "Missing package.json"; exit 1; }
test -d "$VERIFY_DIR/roo-cli-${PLATFORM}/extension" || { echo "Missing extension directory"; exit 1; }
echo "Tarball verification passed!"
# Cleanup.
rm -rf "$VERIFY_DIR"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cli-${{ matrix.platform }}
path: |
roo-cli-${{ matrix.platform }}.tar.gz
roo-cli-${{ matrix.platform }}.tar.gz.sha256
retention-days: 7
# Create GitHub release with all platform artifacts.
release:
needs: build
runs-on: ubuntu-latest
if: ${{ !inputs.dry_run }}
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get version
id: version
run: |
if [ -n "${{ inputs.version }}" ]; then
VERSION="${{ inputs.version }}"
else
VERSION=$(node -p "require('./apps/cli/package.json').version")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=cli-v$VERSION" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release files
run: |
mkdir -p release
find artifacts -name "*.tar.gz" -exec cp {} release/ \;
find artifacts -name "*.sha256" -exec cp {} release/ \;
ls -la release/
- name: Extract changelog
id: changelog
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
CHANGELOG_FILE="apps/cli/CHANGELOG.md"
if [ -f "$CHANGELOG_FILE" ]; then
# Extract content between version headers.
CONTENT=$(awk -v version="$VERSION" '
BEGIN { found = 0; content = ""; target = "[" version "]" }
/^## \[/ {
if (found) { exit }
if (index($0, target) > 0) { found = 1; next }
}
found { content = content $0 "\n" }
END { print content }
' "$CHANGELOG_FILE")
if [ -n "$CONTENT" ]; then
echo "Found changelog content"
echo "content<<EOF" >> $GITHUB_OUTPUT
echo "$CONTENT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
else
echo "No changelog content found for version $VERSION"
echo "content=" >> $GITHUB_OUTPUT
fi
else
echo "No changelog file found"
echo "content=" >> $GITHUB_OUTPUT
fi
- name: Generate checksums summary
id: checksums
run: |
echo "checksums<<EOF" >> $GITHUB_OUTPUT
cat release/*.sha256 >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Check for existing release
id: check_release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
if gh release view "$TAG" &> /dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Delete existing release
if: steps.check_release.outputs.exists == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
run: |
echo "Deleting existing release $TAG..."
gh release delete "$TAG" --yes || true
git push origin ":refs/tags/$TAG" || true
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
CHANGELOG_CONTENT: ${{ steps.changelog.outputs.content }}
CHECKSUMS: ${{ steps.checksums.outputs.checksums }}
run: |
NOTES_FILE=$(mktemp)
if [ -n "$CHANGELOG_CONTENT" ]; then
echo "## What's New" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "$CHANGELOG_CONTENT" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
fi
echo "## Installation" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "Or install a specific version:" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Requirements" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "- Node.js 20 or higher" >> "$NOTES_FILE"
echo "- macOS Apple Silicon (M1/M2/M3/M4), Linux x64, or Linux ARM64" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Usage" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```bash' >> "$NOTES_FILE"
echo "# Run a task" >> "$NOTES_FILE"
echo 'roo "What is this project?"' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "# See all options" >> "$NOTES_FILE"
echo "roo --help" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Platform Support" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "This release includes binaries for:" >> "$NOTES_FILE"
echo '- `roo-cli-darwin-arm64.tar.gz` - macOS Apple Silicon (M1/M2/M3)' >> "$NOTES_FILE"
echo '- `roo-cli-linux-x64.tar.gz` - Linux x64' >> "$NOTES_FILE"
echo '- `roo-cli-linux-arm64.tar.gz` - Linux ARM64' >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo "## Checksums" >> "$NOTES_FILE"
echo "" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
echo "$CHECKSUMS" >> "$NOTES_FILE"
echo '```' >> "$NOTES_FILE"
gh release create "$TAG" \
--title "Roo Code CLI v$VERSION" \
--notes-file "$NOTES_FILE" \
--prerelease \
release/*
rm -f "$NOTES_FILE"
echo "Release created: https://github.com/${{ github.repository }}/releases/tag/$TAG"
# Summary job for dry runs
summary:
needs: build
runs-on: ubuntu-latest
if: ${{ inputs.dry_run }}
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Show build summary
run: |
echo "## Dry Run Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The following artifacts were built:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
find artifacts -name "*.tar.gz" | while read f; do
SIZE=$(ls -lh "$f" | awk '{print $5}')
echo "- $(basename $f) ($SIZE)" >> $GITHUB_STEP_SUMMARY
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Checksums" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
cat artifacts/*/*.sha256 >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

View file

@ -1,5 +1,5 @@
---
description: "Create a new release of the Roo Code CLI"
description: "Prepare a new release of the Roo Code CLI"
argument-hint: "[version-description]"
mode: code
---
@ -84,41 +84,3 @@ mode: code
- [ ] All CI checks pass" \
--base main
```
7. Wait for PR approval and merge:
- Request review if required by your workflow
- Ensure CI checks pass
- Merge the PR using: `gh pr merge --squash --delete-branch`
- Or merge via the GitHub UI
8. Run the release script from the monorepo root:
```bash
# Ensure you're on the updated main branch after the PR merge
git checkout main
git pull origin main
# Run the release script
./apps/cli/scripts/release.sh
```
The release script will automatically:
- Build the extension and CLI
- Create a platform-specific tarball
- Verify the installation works correctly (runs --help, --version, and e2e test)
- Extract changelog content and include it in the GitHub release notes
- Create the GitHub release with the tarball attached
9. After a successful release, verify:
- Check the release page: https://github.com/RooCodeInc/Roo-Code/releases
- Verify the "What's New" section contains the changelog content
- Test installation: `curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh`
**Notes:**
- The release script requires GitHub CLI (`gh`) to be installed and authenticated
- If a release already exists for the tag, the script will prompt to delete and recreate it
- The script creates a tarball for the current platform only (darwin-arm64, darwin-x64, linux-arm64, or linux-x64)
- Multi-platform releases require running the script on each platform and manually uploading additional tarballs

View file

@ -1,163 +1,113 @@
<extraction_workflow>
<mode_overview>
The Docs Extractor mode has exactly two workflow paths:
1) Verify provided documentation for factual accuracy against the codebase
2) Generate source material for user-facing docs about a requested feature or aspect of the codebase
<overview>
Extract raw facts from a codebase about a feature or aspect.
Output is structured data for documentation teams to use.
Do NOT write documentation. Do NOT format prose. Do NOT make structure decisions.
</overview>
Outputs are designed to support explanatory documentation (not merely descriptive):
- Capture why users need steps and why certain actions are restricted
- Surface constraints, limitations, and tradeoffs
- Provide troubleshooting playbooks (symptoms → causes → fixes → prevention)
- Recommend targeted visuals for complex states (not stepbystep screenshots)
This mode does not generate final user documentation; it produces verification and source-material reports for docs teams.
</mode_overview>
<initialization_phase>
<process>
<step number="1">
<title>Parse Request</title>
<title>Identify Target</title>
<actions>
<action>Identify the feature/aspect in the user's request.</action>
<action>Decide path: verification vs. source-material generation.</action>
<action>For source-material: capture audience (user or developer) and depth (overview vs task-focused).</action>
<action>For verification: identify the documentation to be verified (provided text/links/files).</action>
<action>Note any specific areas to emphasize or check.</action>
<action>Parse the user's request to identify the feature/aspect</action>
<action>Clarify scope if ambiguous (ask one question max)</action>
</actions>
</step>
<step number="2">
<title>Discover Feature</title>
<title>Discover Code</title>
<actions>
<action>Locate relevant code and assets using appropriate discovery methods.</action>
<action>Identify entry points and key components that affect user experience.</action>
<action>Map the high-level workflow a user follows.</action>
<action>Use codebase_search to find relevant files</action>
<action>Identify entry points, components, and related code</action>
<action>Map the boundaries of the feature</action>
</actions>
</step>
</initialization_phase>
<analysis_focus>
<area>UI components and their interactions</area>
<area>User workflows and decision points</area>
<area>Configuration that changes user-visible behavior</area>
<area>Error states, messages, and recovery</area>
<area>Benefits, limits, prerequisites, and version notes</area>
<area>Why this exists: user goals, constraints, and design intent</area>
<area>“Cannot do” boundaries: permissions, invariants, and business rules</area>
<area>Troubleshooting: symptoms, likely causes, diagnostics, fixes, prevention</area>
<area>Common pitfalls and antipatterns (what to avoid and why)</area>
<area>Decision rationale and tradeoffs that affect user choices</area>
<area>Complex UI states that merit visuals (criteria for screenshots/diagrams)</area>
</analysis_focus>
<step number="3">
<title>Extract Facts</title>
<actions>
<action>Read code and extract facts into categories (see fact_categories)</action>
<action>Record file paths as sources for each fact</action>
<action>Do NOT interpret, summarize, or explain - just extract</action>
</actions>
</step>
<workflow_paths>
<path name="source_material">
<title>Generate Source Material for User-Facing Docs</title>
<description>Extract concise, user-oriented facts and structure them for documentation teams.</description>
<steps>
<step number="1">
<title>Scope and Audience</title>
<actions>
<action>Confirm the feature/aspect and intended audience.</action>
<action>List primary tasks the audience performs with this feature.</action>
</actions>
</step>
<step number="2">
<title>Extract User-Facing Facts</title>
<actions>
<action>Summarize what the feature does and key benefits.</action>
<action>Explain why users need this (jobs-to-be-done, outcomes) and when to use it.</action>
<action>Document step-by-step user workflows and UI interactions.</action>
<action>Capture configuration options that impact user behavior (name, default, effect).</action>
<action>Clarify constraints, limits, and “cannot do” cases with rationale.</action>
<action>Identify common pitfalls and anti-patterns; include “Do/Dont” guidance.</action>
<action>List common errors with user-facing messages, diagnostics, fixes, and prevention.</action>
<action>Record prerequisites, permissions, and compatibility/version notes.</action>
<action>Flag complex states that warrant visuals (what to show and why), not every step.</action>
</actions>
</step>
<step number="3">
<title>Create Source Material Report</title>
<actions>
<action>Organize findings using user-focused structure (benefits, use cases, how it works, configuration, FAQ, troubleshooting).</action>
<action>Include short code/UI snippets or paths where relevant.</action>
<action>Create `EXTRACTION-[feature].md` with findings.</action>
<action>Highlight items that need visuals (screenshots/diagrams).</action>
</actions>
<output_format>
- Executive summary of the feature/aspect
- Why it matters (goals, value, when to use)
- User workflows and interactions
- Configuration and setup affecting users (with defaults and impact)
- Constraints and limitations (with rationale)
- Common scenarios and troubleshooting playbooks (symptoms → causes → fixes → prevention)
- Do/Dont and antipatterns
- Recommended visuals (what complex states to illustrate and why)
- FAQ and tips
- Version/compatibility notes
</output_format>
</step>
</steps>
</path>
<step number="4">
<title>Output Structured Data</title>
<actions>
<action>Write extraction to .roo/extraction/EXTRACT-[feature].yaml</action>
<action>Use the output schema (see output_format.xml)</action>
</actions>
</step>
</process>
<path name="verification">
<title>Verify Documentation Accuracy</title>
<description>Check provided documentation against codebase reality and actual UX.</description>
<steps>
<step number="1">
<title>Analyze Provided Documentation</title>
<actions>
<action>Parse the documentation to identify claims and descriptions.</action>
<action>Extract technical or user-facing specifics mentioned.</action>
<action>Note workflows, configuration, and examples described.</action>
</actions>
</step>
<step number="2">
<title>Verify Against Codebase</title>
<actions>
<action>Check claims against actual implementation and UX.</action>
<action>Verify endpoints/parameters if referenced.</action>
<action>Confirm configuration options and defaults.</action>
<action>Validate code snippets and examples.</action>
<action>Ensure described workflows match implementation.</action>
</actions>
</step>
<step number="3">
<title>Create Verification Report</title>
<actions>
<action>Categorize findings by severity (Critical, Major, Minor).</action>
<action>List inaccuracies with the correct information.</action>
<action>Identify missing important information.</action>
<action>Provide specific corrections and suggestions.</action>
<action>Create `VERIFICATION-[feature].md` with findings.</action>
</actions>
<output_format>
- Verification summary (Accurate/Needs Updates)
- Critical inaccuracies that could mislead users
- Corrections and missing information
- Explanatory gaps (missing “why”, constraints, or decision rationale)
- Troubleshooting coverage gaps (missing symptoms/diagnostics/fixes/prevention)
- Visual recommendations (which complex states warrant screenshots/diagrams)
- Suggestions for clarity improvements
</output_format>
</step>
</steps>
</path>
</workflow_paths>
<fact_categories>
<category name="identity">
<extracts>
<extract>Feature name as it appears in code</extract>
<extract>File paths where feature is implemented</extract>
<extract>Entry points (commands, UI elements, API endpoints)</extract>
</extracts>
</category>
<completion_criteria>
<for_source_material>
<criterion>Audience and scope captured</criterion>
<criterion>User workflows and UI interactions documented</criterion>
<criterion>User-impacting configuration recorded</criterion>
<criterion>Common errors and troubleshooting documented</criterion>
<criterion>Report organized for documentation team use</criterion>
</for_source_material>
<for_verification>
<criterion>All documentation claims verified</criterion>
<criterion>Inaccuracies identified and corrected</criterion>
<criterion>Missing information noted</criterion>
<criterion>Suggestions for improvement provided</criterion>
<criterion>Clear verification report created</criterion>
</for_verification>
</completion_criteria>
<category name="behavior">
<extracts>
<extract>What the feature does (from code logic)</extract>
<extract>Inputs it accepts</extract>
<extract>Outputs it produces</extract>
<extract>Side effects (files created, state changed, etc.)</extract>
</extracts>
</category>
<category name="configuration">
<extracts>
<extract>Settings/options that affect behavior</extract>
<extract>Default values</extract>
<extract>Valid ranges or allowed values</extract>
<extract>Where configured (settings file, env var, UI)</extract>
</extracts>
</category>
<category name="constraints">
<extracts>
<extract>Prerequisites and dependencies</extract>
<extract>Limitations (what it cannot do)</extract>
<extract>Permissions required</extract>
<extract>Compatibility requirements</extract>
</extracts>
</category>
<category name="errors">
<extracts>
<extract>Error conditions in code</extract>
<extract>Error messages (exact text)</extract>
<extract>Recovery paths in code</extract>
</extracts>
</category>
<category name="ui">
<extracts>
<extract>UI components involved</extract>
<extract>User-visible labels and text</extract>
<extract>Interaction patterns</extract>
</extracts>
</category>
<category name="integration">
<extracts>
<extract>Other features this interacts with</extract>
<extract>External APIs or services called</extract>
<extract>Events emitted or consumed</extract>
</extracts>
</category>
</fact_categories>
<rules>
<rule>Extract facts, not opinions</rule>
<rule>Include source file paths for every fact</rule>
<rule>Use code identifiers and exact strings from source</rule>
<rule>Do NOT paraphrase - quote when possible</rule>
<rule>Do NOT decide what's important - extract everything relevant</rule>
<rule>Do NOT format for end users - output is for docs team</rule>
</rules>
</extraction_workflow>

View file

@ -1,357 +0,0 @@
<documentation_patterns>
<overview>
Standard templates for structuring extracted documentation.
</overview>
<output_structure>
<user_focused_template>
# [Feature Name]
[Description of what the feature does and why a user should care.]
### Key Features
- [Benefit-oriented feature 1]
- [Benefit-oriented feature 2]
- [Benefit-oriented feature 3]
---
## Use Case
**Before**: [Description of the old way]
- [Pain point 1]
- [Pain point 2]
**With this feature**: [Description of the new experience.]
## How it Works
[Simple explanation of the feature's operation.]
[Suggest visual representations where helpful.]
---
## Configuration
[Explanation of relevant settings.]
1. **[Setting Name]**:
- **Setting**: `[technical_name]`
- **Description**: [What this does.]
- **Default**: [Default value and its meaning.]
2. **[Setting Name]**:
- **Setting**: `[technical_name]`
- **Description**: [What this does.]
- **Default**: [Default value and its meaning.]
---
## FAQ
**"[User question]"**
- [Answer.]
- [Optional tip.]
**"[User question]"**
- [Answer.]
- [Optional tip.]
</user_focused_template>
<comprehensive_template>
# [Feature Name] Technical Documentation
## Table of Contents
1. Overview
2. Quick Start
3. Architecture
4. API Reference
5. Configuration
6. User Guide
7. Developer Guide
8. Security
9. Performance
10. Troubleshooting
11. FAQ
12. Changelog
13. References
[Use this as an internal source-material outline for technical sections; not for final docs.]
</comprehensive_template>
</output_structure>
<documentation_patterns>
<before_after>
<template>
**Before**: Multiple, sequential file read requests:
- "Read `src/app.js`?" → Approve
- "Read `src/utils.js`?" → Approve
- "Read `src/config.json`?" → Approve
**Now**: One request to read all related files.
</template>
</before_after>
<visual_separator>
<format>---</format>
<purpose>Separate sections.</purpose>
</visual_separator>
<faq>
<template>
## FAQ
**"Why disable this?"**
- Your AI model handles single files better.
- You need more control over file access.
- You are working with very large files.
**"What if some files are blocked?"**
- Roo reads approved files and works with what it has.
- `.rooignore` files are excluded automatically.
- Individual files can still be denied in the batch dialog.
</template>
</faq>
<examples>
<guideline>Show tool output or UI elements.</guideline>
<guideline>Use actual file paths and setting names.</guideline>
<guideline>Include common errors and solutions.</guideline>
</examples>
<troubleshooting>
<template>
## Troubleshooting
**"Too many files requested"**
- Lower the concurrent file limit in settings.
- Deny individual files in the batch dialog.
**"Feature isn't working"**
- Ensure "Enable concurrent file reads" is on in settings.
- Verify the file limit is set correctly (default: 100).
- Some AI models may not support this feature.
</template>
</troubleshooting>
<help>
<template>
## Help
- See the [FAQ](#faq) for common issues.
- Report problems on [GitHub Issues](https://github.com/RooCodeInc/Roo-Code/issues).
- Include reproduction steps and error messages.
</template>
</help>
</documentation_patterns>
<audience_sections>
<audience type="user">
<focus>
<area>Tutorials</area>
<area>Use cases</area>
<area>Troubleshooting</area>
<area>Benefits</area>
</focus>
<style>
<guideline>Simple language</guideline>
<guideline>Visual aids</guideline>
<guideline>Focus on outcomes</guideline>
<guideline>Clear action steps</guideline>
</style>
</audience>
<audience type="developer">
<focus>
<area>Code examples</area>
<area>API specs</area>
<area>Integration patterns</area>
<area>Performance</area>
</focus>
<style>
<guideline>Precise terminology</guideline>
<guideline>Code samples</guideline>
<guideline>Document edge cases</guideline>
<guideline>Debugging guidance</guideline>
</style>
</audience>
</audience_sections>
<metadata_patterns>
<version_info>
<template>
### Version Compatibility
| Component | Min | Recommended | Max | Notes |
|-----------|-----|-------------|-----|-------|
| [Component] | [version] | [version] | [version] | [notes] |
</template>
</version_info>
<deprecation_notice>
<template>
> ⚠️ **Deprecated**
>
> Deprecated since: [vX.Y.Z] on [date]
> Removal target: [vA.B.C]
> Migration: See [migration guide](#migration).
> Replacement: [new feature/method].
</template>
</deprecation_notice>
<security_warning>
<template>
> 🔒 **Security Warning**
>
> [Description of concern]
> - **Risk**: [High/Medium/Low]
> - **Affected**: [versions]
> - **Mitigation**: [steps]
> - **References**: [links]
</template>
</security_warning>
<performance_note>
<template>
> ⚡ **Performance Note**
>
> [Description of performance consideration]
> - **Impact**: [metrics]
> - **Optimization**: [approach]
> - **Trade-offs**: [considerations]
</template>
</performance_note>
</metadata_patterns>
<code_documentation_patterns>
<api_endpoint>
<template>
### `[METHOD] /api/[path]`
**Description**: [What this endpoint does]
**Authentication**: [Required/Optional] - [Type]
**Parameters**:
| Name | Type | Required | Description | Example |
|------|------|----------|-------------|---------|
| [param] | [type] | [Yes/No] | [description] | [example] |
**Request Body**:
```json
{
"field": "value"
}
```
**Response**:
- **Success (200)**:
```json
{
"status": "success",
"data": {}
}
```
- **Error (4xx/5xx)**:
```json
{
"error": "error_code",
"message": "Human readable message"
}
```
**Example**:
```bash
curl -X [METHOD] https://api.example.com/[path] \
-H "Authorization: Bearer [token]" \
-H "Content-Type: application/json" \
-d '{"field": "value"}'
```
</template>
</api_endpoint>
<function_documentation>
<template>
### `functionName(parameters)`
**Purpose**: [What this function does]
**Parameters**:
- `param1` (Type): [Description]
- `param2` (Type, optional): [Description] - Default: [value]
**Returns**: `Type` - [Description of return value]
**Throws**:
- `ErrorType`: [When this error occurs]
**Example**:
```typescript
const result = functionName(value1, value2);
// Expected output: [description]
```
**Notes**:
- [Important consideration 1]
- [Important consideration 2]
</template>
</function_documentation>
<configuration_option>
<template>
### `CONFIG_NAME`
**Type**: `string | number | boolean`
**Default**: `default_value`
**Environment Variable**: `APP_CONFIG_NAME`
**Description**: [What this configuration controls]
**Valid Values**:
- `value1`: [Description]
- `value2`: [Description]
**Example**:
```yaml
config:
name: value
```
**Impact**: [What changes when this is modified]
</template>
</configuration_option>
</code_documentation_patterns>
<cross_reference_patterns>
<internal_link>
<format>[Link Text](#section-anchor)</format>
<example>[See Configuration Guide](#configuration)</example>
</internal_link>
<external_link>
<format>[Link Text](https://external.url)</format>
<example>[Official Documentation](https://docs.example.com)</example>
</external_link>
<related_feature>
<template>
> 📌 **Related Features**
> - [Feature A](../feature-a/README.md): [How it relates]
> - [Feature B](../feature-b/README.md): [How it relates]
</template>
</related_feature>
<see_also>
<template>
> 👉 **See Also**
> - [Related Topic 1](#anchor1)
> - [Related Topic 2](#anchor2)
> - [External Resource](https://example.com)
</template>
</see_also>
</cross_reference_patterns>
</documentation_patterns>

View file

@ -0,0 +1,85 @@
<verification_workflow>
<overview>
Compare provided documentation against actual codebase implementation.
Output is a structured diff of claims vs reality.
Do NOT rewrite the docs. Do NOT suggest wording. Just report discrepancies.
</overview>
<process>
<step number="1">
<title>Receive Documentation</title>
<actions>
<action>User provides documentation to verify (text, file, or URL)</action>
<action>Identify the feature/aspect being documented</action>
</actions>
</step>
<step number="2">
<title>Extract Claims</title>
<actions>
<action>Parse the documentation into discrete claims</action>
<action>Tag each claim with a category (behavior, config, constraint, etc.)</action>
<action>Record the exact quote from the documentation</action>
</actions>
</step>
<step number="3">
<title>Verify Against Code</title>
<actions>
<action>For each claim, find the relevant code</action>
<action>Compare claim to actual implementation</action>
<action>Record: ACCURATE, INACCURATE, OUTDATED, MISSING_CONTEXT, or UNVERIFIABLE</action>
<action>For inaccuracies, record what the code actually does</action>
</actions>
</step>
<step number="4">
<title>Output Verification Report</title>
<actions>
<action>Write verification to .roo/extraction/VERIFY-[feature].yaml</action>
<action>Use the output schema (see output_format.xml)</action>
</actions>
</step>
</process>
<verification_statuses>
<status name="ACCURATE">
<meaning>Claim matches implementation</meaning>
</status>
<status name="INACCURATE">
<meaning>Claim contradicts implementation</meaning>
<requires>What the code actually does</requires>
</status>
<status name="OUTDATED">
<meaning>Claim was once true but code has changed</meaning>
<requires>Current behavior</requires>
</status>
<status name="MISSING_CONTEXT">
<meaning>Claim is true but omits important information</meaning>
<requires>The missing context</requires>
</status>
<status name="UNVERIFIABLE">
<meaning>Cannot find code to verify this claim</meaning>
<requires>Search paths attempted</requires>
</status>
</verification_statuses>
<claim_categories>
<category>behavior</category>
<category>configuration</category>
<category>constraint</category>
<category>error_handling</category>
<category>ui</category>
<category>integration</category>
<category>prerequisite</category>
</claim_categories>
<rules>
<rule>Verify facts, not writing quality</rule>
<rule>Report what code does, not what docs should say</rule>
<rule>Include source file paths as evidence</rule>
<rule>Do NOT suggest documentation rewrites</rule>
<rule>Do NOT evaluate if docs are "good" - only if they're accurate</rule>
<rule>Quote exact code when showing discrepancies</rule>
</rules>
</verification_workflow>

View file

@ -1,349 +0,0 @@
<analysis_techniques>
<overview>
Heuristics for analyzing a codebase to extract reliable, user-facing documentation.
This file contains technique checklists only—no tool instructions or invocations.
</overview>
<ui_ux_analysis_techniques>
<technique name="component_discovery">
<description>Find and analyze UI components and their interactions</description>
<heuristics>
<rule>Start from feature or route directories and enumerate components related to the requested topic.</rule>
<rule>Differentiate container vs presentational components; note composition patterns.</rule>
<rule>Trace inputs/outputs: props, state, context, events, and side effects.</rule>
<rule>Record conditional rendering that affects user-visible states.</rule>
</heuristics>
<evidence_to_collect>
<item>Primary components and responsibilities.</item>
<item>Props/state/context that change behavior.</item>
<item>High-level dependency/composition map.</item>
</evidence_to_collect>
</technique>
<technique name="style_analysis">
<description>Analyze styling and visual elements</description>
<heuristics>
<rule>Identify design tokens and utility classes used to drive layout and state.</rule>
<rule>Capture responsive behavior and breakpoint rules that materially change UX.</rule>
<rule>Document visual affordances tied to state (loading, error, disabled).</rule>
</heuristics>
<evidence_to_collect>
<item>Key classes/selectors influencing layout/state.</item>
<item>Responsive behavior summary and breakpoints.</item>
</evidence_to_collect>
</technique>
<technique name="user_flow_mapping">
<description>Map user interactions and navigation flows</description>
<analysis_areas>
<area>Route definitions and navigation</area>
<area>Form submissions and validations</area>
<area>Button clicks and event handlers</area>
<area>State changes and UI updates</area>
<area>Loading and error states</area>
</analysis_areas>
<heuristics>
<rule>Outline entry points and expected outcomes for each primary flow.</rule>
<rule>Summarize validation rules and failure states the user can encounter.</rule>
<rule>Record redirects and deep-link behavior relevant to the feature.</rule>
</heuristics>
<evidence_to_collect>
<item>Flow diagrams or bullet sequences for main tasks.</item>
<item>Validation conditions and error messages.</item>
<item>Navigation transitions and guards.</item>
</evidence_to_collect>
</technique>
<technique name="user_feedback_analysis">
<description>Analyze how the system communicates with users</description>
<elements_to_find>
<element>Error messages and alerts</element>
<element>Success notifications</element>
<element>Loading indicators</element>
<element>Tooltips and help text</element>
<element>Confirmation dialogs</element>
<element>Progress indicators</element>
</elements_to_find>
<heuristics>
<rule>Map message triggers to the user actions that cause them.</rule>
<rule>Capture severity, persistence, and dismissal behavior.</rule>
<rule>Note localization or accessibility considerations in messages.</rule>
</heuristics>
<evidence_to_collect>
<item>Catalog of messages with purpose and conditions.</item>
<item>Loading/progress patterns and timeouts.</item>
</evidence_to_collect>
</technique>
<technique name="accessibility_analysis">
<description>Check for accessibility features and compliance</description>
<accessibility_checks>
<check>ARIA labels and roles</check>
<check>Keyboard navigation support</check>
<check>Screen reader compatibility</check>
<check>Focus management</check>
<check>Color contrast considerations</check>
</accessibility_checks>
<heuristics>
<rule>Confirm interactive elements have clear focus and labels.</rule>
<rule>Describe keyboard-only navigation paths for core flows.</rule>
</heuristics>
<evidence_to_collect>
<item>Accessibility gaps affecting task completion.</item>
</evidence_to_collect>
</technique>
<technique name="responsive_design_analysis">
<description>Analyze responsive design and mobile experience</description>
<analysis_points>
<point>Breakpoint definitions</point>
<point>Mobile-specific components</point>
<point>Touch event handlers</point>
<point>Viewport configurations</point>
<point>Media queries</point>
</analysis_points>
<heuristics>
<rule>Summarize layout changes across breakpoints that alter workflow.</rule>
<rule>Note touch targets and gestures required on mobile.</rule>
</heuristics>
<evidence_to_collect>
<item>Table of key differences per breakpoint.</item>
</evidence_to_collect>
</technique>
</ui_ux_analysis_techniques>
<code_analysis_techniques>
<technique name="entry_point_analysis">
<description>Understand feature entry points and control flow</description>
<steps>
<step>Identify main functions, controllers, or route handlers.</step>
<step>Trace execution and decision branches.</step>
<step>Document input validation and preconditions.</step>
</steps>
<evidence_to_collect>
<item>Entry points list and short purpose statements.</item>
<item>Decision matrix or flow sketch.</item>
</evidence_to_collect>
</technique>
<technique name="api_extraction">
<description>Extract API specifications from code</description>
<patterns>
<pattern type="rest">
<extraction>
<item>HTTP method and route path</item>
<item>Path/query parameters</item>
<item>Request/response schemas</item>
<item>Status codes and error bodies</item>
</extraction>
</pattern>
<pattern type="graphql">
<extraction>
<item>Schema and input types</item>
<item>Resolvers and return types</item>
<item>Field arguments and constraints</item>
</extraction>
</pattern>
</patterns>
</technique>
<technique name="dependency_mapping">
<description>Map dependencies and integration points</description>
<analysis_points>
<point>Imports and module boundaries</point>
<point>Package and runtime dependencies</point>
<point>External API/SDK usage</point>
<point>DB connections and migrations</point>
<point>Messaging/queue/event streams</point>
<point>Filesystem or network side effects</point>
</analysis_points>
<evidence_to_collect>
<item>Dependency graph summary and hot spots.</item>
<item>List of external integrations and auth methods.</item>
</evidence_to_collect>
</technique>
<technique name="data_model_extraction">
<description>Extract data models, schemas, and type definitions</description>
<sources>
<source type="typescript">
<patterns>- interfaces, types, classes, enums</patterns>
</source>
<source type="database">
<patterns>- Schema definitions, migration files, ORM models</patterns>
</source>
<source type="validation">
<patterns>- JSON Schema, Joi/Yup/Zod schemas, validation decorators</patterns>
</source>
</sources>
<evidence_to_collect>
<item>Canonical definitions and field constraints.</item>
<item>Entity relationships and ownership.</item>
</evidence_to_collect>
</technique>
<technique name="business_logic_extraction">
<description>Identify and document business rules</description>
<indicators>
<indicator>Complex conditionals</indicator>
<indicator>Calculation functions</indicator>
<indicator>Validation rules</indicator>
<indicator>State machines</indicator>
<indicator>Domain-specific constants and algorithms</indicator>
</indicators>
<documentation_focus>
<focus>Why the logic exists (business need)</focus>
<focus>When the logic applies (conditions)</focus>
<focus>What the logic does (transformation)</focus>
<focus>Edge cases and invariants</focus>
<focus>Impact of changes</focus>
</documentation_focus>
</technique>
<technique name="error_handling_analysis">
<description>Document error handling and recovery</description>
<analysis_areas>
<area>try/catch blocks and error boundaries</area>
<area>Custom error classes and codes</area>
<area>Logging, fallbacks, retries, circuit breakers</area>
</analysis_areas>
<evidence_to_collect>
<item>Error taxonomy and user-facing messages.</item>
<item>Recovery/rollback strategies and timeouts.</item>
</evidence_to_collect>
</technique>
<technique name="security_analysis">
<description>Identify security measures and vulnerabilities</description>
<security_checks>
<check category="authentication">JWT, sessions, OAuth, API keys</check>
<check category="authorization">RBAC, permission checks, ownership validation</check>
<check category="data_protection">Encryption, hashing, sensitive data handling</check>
<check category="input_validation">Sanitization and injection prevention</check>
</security_checks>
<evidence_to_collect>
<item>Threat surfaces and mitigations relevant to the feature.</item>
</evidence_to_collect>
</technique>
<technique name="performance_analysis">
<description>Identify performance factors and optimization opportunities</description>
<analysis_points>
<point>Expensive loops/algorithms</point>
<point>DB query patterns (e.g., N+1)</point>
<point>Caching strategies</point>
<point>Concurrency and async usage</point>
<point>Batching and resource pooling</point>
<point>Memory management and object lifetimes</point>
</analysis_points>
<metrics_to_document>
<metric>Time/space complexity</metric>
<metric>DB query counts</metric>
<metric>API response times</metric>
<metric>Memory usage</metric>
<metric>Concurrency handling</metric>
</metrics_to_document>
</technique>
<technique name="test_coverage_analysis">
<description>Assess test coverage at a useful granularity</description>
<test_types>
<type name="unit">
<analysis>Function-level coverage and edge cases</analysis>
</type>
<type name="integration">
<analysis>Workflow coverage and contract boundaries</analysis>
</type>
<type name="api">
<analysis>Endpoint success/failure paths and schemas</analysis>
</type>
</test_types>
<evidence_to_collect>
<item>List of critical behaviors missing tests.</item>
</evidence_to_collect>
</technique>
<technique name="configuration_extraction">
<description>Extract configuration options and their impacts</description>
<configuration_sources>
<source>.env files, config files, CLI args, feature flags</source>
</configuration_sources>
<documentation_requirements>
<requirement>Default values and valid ranges</requirement>
<requirement>Behavioral impact of each option</requirement>
<requirement>Dependencies between options</requirement>
<requirement>Security implications</requirement>
</documentation_requirements>
</technique>
</code_analysis_techniques>
<workflow_analysis>
<technique name="user_journey_mapping">
<description>Map user workflows through the feature</description>
<steps>
<step>Identify entry points (UI, API, CLI)</step>
<step>Trace user actions and decision points</step>
<step>Map data transformations</step>
<step>Identify outcomes and completion criteria</step>
</steps>
<deliverables>
<deliverable>Flow diagrams, procedures, decision trees, state diagrams</deliverable>
</deliverables>
</technique>
<technique name="integration_flow_analysis">
<description>Document integration with other systems</description>
<integration_types>
<type>Sync API calls, async messaging, events, batch processing, streaming</type>
</integration_types>
<documentation_focus>
<focus>Protocols, auth, error handling, data transforms, SLAs</focus>
</documentation_focus>
</technique>
</workflow_analysis>
<metadata_extraction>
<technique name="version_compatibility">
<description>Summarize version constraints and compatibility</description>
<sources>
<source>package manifests, READMEs, migration guides, breaking changes docs</source>
</sources>
<evidence_to_collect>
<item>Minimum/recommended versions and notable constraints.</item>
</evidence_to_collect>
</technique>
<technique name="deprecation_tracking">
<description>Track deprecations and migrations</description>
<indicators>
<indicator>Explicit deprecation notices and TODO markers</indicator>
<indicator>Legacy code paths and adapters</indicator>
</indicators>
<documentation_requirements>
<requirement>Deprecation date and removal timeline</requirement>
<requirement>Migration path and alternatives</requirement>
</documentation_requirements>
</technique>
</metadata_extraction>
<quality_indicators>
<indicator name="documentation_completeness">
<checks>
<check>Public APIs documented with inputs/outputs and errors</check>
<check>Examples for complex features</check>
<check>Error scenarios covered with recovery guidance</check>
<check>Config options explained with defaults and impacts</check>
<check>Security considerations addressed</check>
</checks>
</indicator>
<indicator name="code_quality_metrics">
<metrics>
<metric>Cyclomatic complexity</metric>
<metric>Code duplication</metric>
<metric>Test coverage and gaps</metric>
<metric>Documentation coverage for user-visible behaviors</metric>
<metric>Known technical debt affecting UX</metric>
</metrics>
</indicator>
</quality_indicators>
</analysis_techniques>

View file

@ -0,0 +1,133 @@
<output_format>
<overview>
Structured data output formats for extraction and verification.
All output is YAML. No prose. No markdown formatting.
This data feeds into documentation-writer mode.
</overview>
<extraction_schema>
<description>Schema for EXTRACT-[feature].yaml files</description>
<template>
feature:
name: [feature name from code]
slug: [lowercase-hyphenated identifier]
extracted_at: [ISO timestamp]
source_files:
- [list of primary files]
identity:
entry_points:
- type: [command|ui|api|event]
name: [identifier]
location: [file:line]
components:
- name: [component name]
file: [path]
purpose: [one line from code comments or inferred]
behavior:
primary_action: [what it does - from code]
inputs:
- name: [input name]
type: [data type]
required: [true|false]
source: [file:line]
outputs:
- name: [output name]
type: [data type]
source: [file:line]
side_effects:
- description: [what changes]
source: [file:line]
configuration:
- name: [setting name]
key: [config key path]
type: [data type]
default: [default value]
valid_values: [list or range]
effect: [what it changes]
source: [file:line]
constraints:
prerequisites:
- description: [requirement]
source: [file:line]
limitations:
- description: [what cannot be done]
source: [file:line]
permissions:
- description: [permission needed]
source: [file:line]
errors:
- condition: [when this error occurs]
message: "[exact error message text]"
code: [error code if any]
source: [file:line]
ui:
components:
- name: [component name]
type: [button|panel|input|etc]
label: "[visible text]"
source: [file:line]
interactions:
- trigger: [user action]
result: [what happens]
source: [file:line]
integration:
internal:
- feature: [other feature name]
relationship: [how they interact]
source: [file:line]
external:
- service: [external service]
api: [endpoint or method]
source: [file:line]
</template>
</extraction_schema>
<verification_schema>
<description>Schema for VERIFY-[feature].yaml files</description>
<template>
verification:
feature: [feature name]
doc_source: [where the docs came from]
verified_at: [ISO timestamp]
summary:
total_claims: [count]
accurate: [count]
inaccurate: [count]
outdated: [count]
missing_context: [count]
unverifiable: [count]
claims:
- id: [claim-1]
quote: "[exact text from documentation]"
category: [behavior|configuration|constraint|error_handling|ui|integration|prerequisite]
status: [ACCURATE|INACCURATE|OUTDATED|MISSING_CONTEXT|UNVERIFIABLE]
evidence:
code_file: [file:line]
actual_behavior: [what code does - only if status is not ACCURATE]
code_quote: "[relevant code snippet]"
</template>
</verification_schema>
<output_rules>
<rule>Use YAML, not JSON or markdown</rule>
<rule>Include source file:line for every fact</rule>
<rule>Quote exact strings from code using double quotes</rule>
<rule>Use null for unknown/missing values, not empty strings</rule>
<rule>Keep descriptions factual and brief - one line max</rule>
<rule>Do NOT add commentary, suggestions, or explanations</rule>
</output_rules>
<file_naming>
<extraction>EXTRACT-[feature-slug].yaml</extraction>
<verification>VERIFY-[feature-slug].yaml</verification>
<location>.roo/extraction/</location>
</file_naming>
</output_format>

View file

@ -1,298 +0,0 @@
<communication_guidelines>
<overview>
Guidelines for user communication and output formatting.
</overview>
<user_interaction>
<initial_contact>
<principle>Act on the user's request immediately.</principle>
<principle>Only ask for clarification if the request is ambiguous.</principle>
</initial_contact>
<clarification>
<when_to_ask>
<scenario>Multiple features with similar names are found.</scenario>
<scenario>The request is ambiguous.</scenario>
<scenario>The user explicitly asks for options.</scenario>
</when_to_ask>
</clarification>
<progress_updates>
<when_to_update>
<trigger>Starting a major analysis phase.</trigger>
<trigger>Extraction is complete.</trigger>
<trigger>Unexpected complexity is found.</trigger>
</when_to_update>
<update_format>
<template>
Analyzing [component]...
- Found [X] related files.
- Identified [Y] API endpoints.
- Found [Z] config options.
</template>
</update_format>
</progress_updates>
<findings_communication>
<important_findings>
<discovery type="security_issue">
Alert user to security concerns found during analysis.
</discovery>
<discovery type="deprecated_code">
Note deprecated features needing migration docs.
</discovery>
<discovery type="missing_docs">
Highlight code that lacks inline documentation.
</discovery>
<discovery type="complex_dependencies">
Warn about complex dependency chains.
</discovery>
</important_findings>
<extraction_findings>
<template>
Feature extraction complete for [feature name].
**Extraction Report**: `EXTRACTION-[feature].md`
**Key Findings**:
- Technical Components: [X] classes, [Y] APIs, [Z] configurations
- User Workflows: [number] primary use cases identified
- Business Logic: [summary of core functionality]
- Integration Points: [list of external dependencies]
**Documentation Considerations**:
- [Important aspect that needs clear explanation]
- [Complex area that may need diagrams]
- [Edge cases that should be documented]
The extraction report provides comprehensive details for your documentation team.
</template>
</extraction_findings>
<verification_findings>
<template>
Documentation verification complete.
**Verification Report**: `VERIFICATION-[feature].md`
**Overall Assessment**: [Accurate/Needs Updates/Contains Critical Errors]
**Summary of Findings**:
- Critical Inaccuracies: [number]
- Technical Corrections Needed: [number]
- Missing Information: [number]
- Clarity Improvements: [number]
**Most Important Issues**:
1. [Critical issue that could mislead users]
2. [Important technical inaccuracy]
3. [Key missing information]
See the full verification report for detailed corrections and suggestions.
</template>
</verification_findings>
</findings_communication>
</user_interaction>
<output_formatting>
<markdown_standards>
<headings>
<rule>Use # for main title, ## for major sections, ### for subsections.</rule>
<rule>Never skip heading levels.</rule>
</headings>
<code_blocks>
<rule>Always specify language for syntax highlighting (e.g., typescript, json, bash).</rule>
<rule>Include file paths as comments where relevant.</rule>
<example>
```typescript
// src/auth/auth.service.ts
export class AuthService {
async validateUser(email: string, password: string): Promise<User> {
// Implementation
}
}
```
</example>
</code_blocks>
<tables>
<rule>Use tables for structured data like configs.</rule>
<rule>Include headers and align columns.</rule>
<rule>Keep cell content brief.</rule>
<example>
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `JWT_SECRET` | string | - | Secret key for JWT signing |
| `JWT_EXPIRATION` | string | '15m' | Token expiration time |
</example>
</tables>
<lists>
<rule>Use bullets for unordered lists, numbers for sequential steps.</rule>
<rule>Keep list items parallel in structure.</rule>
</lists>
</markdown_standards>
<cross_references>
<internal_links>
<format>[Link text](#section-anchor)</format>
<rule>Use lowercase, hyphenated anchors. Test all links.</rule>
</internal_links>
<external_links>
<format>[Link text](https://example.com)</format>
<rule>Use HTTPS. Link to official docs.</rule>
</external_links>
<file_references>
<format>`path/to/file.ts`</format>
<rule>Use relative paths from project root, in backticks.</rule>
</file_references>
</cross_references>
<special_sections>
<alerts>
<type name="warning">
<format>> ⚠️ **Warning**: [message]</format>
<use_for>Security, breaking changes, deprecations.</use_for>
</type>
<type name="note">
<format>> 📝 **Note**: [message]</format>
<use_for>Important info, clarifications.</use_for>
</type>
<type name="tip">
<format>> 💡 **Tip**: [message]</format>
<use_for>Best practices, optimizations.</use_for>
</type>
</alerts>
<metadata_blocks>
<version_info>
---
Feature: Authentication System
Version: 2.1.0
Last Updated: 2024-01-15
Status: Stable
---
</version_info>
</metadata_blocks>
</special_sections>
</output_formatting>
<documentation_tone>
<general>
<principle>Be direct, not conversational.</principle>
<principle>Use active voice.</principle>
<principle>Lead with benefits.</principle>
<principle>Use concrete examples.</principle>
<principle>Keep paragraphs short.</principle>
<principle>Avoid unnecessary technical details.</principle>
</general>
<audience_tone>
<audience type="developer">
<tone>Technical and direct.</tone>
<vocabulary>Standard programming terms.</vocabulary>
<examples>Code snippets, implementation details.</examples>
</audience>
<audience type="user">
<tone>Instructional, step-by-step.</tone>
<vocabulary>Simple language, no jargon.</vocabulary>
<examples>Screenshots, real-world scenarios.</examples>
</audience>
</audience_tone>
</documentation_tone>
<completion_message>
<structure>
<element>Summary of analysis performed.</element>
<element>Key findings or issues identified.</element>
<element>Report file location.</element>
<element>Recommended next steps.</element>
</structure>
<extraction_example>
Feature extraction complete for the authentication system.
**Extraction Report**: `EXTRACTION-authentication-system.md`
**Technical Summary**:
- JWT-based authentication with refresh tokens
- 5 API endpoints (login, logout, refresh, register, profile)
- 12 configuration options
- bcrypt password hashing, rate limiting
**Non-Technical Summary**:
- Users can register, login, and manage sessions
- Supports "remember me" functionality
- Automatic session refresh for seamless experience
- Account lockout after failed attempts
**Documentation Considerations**:
- Token expiration times need clear explanation
- Password requirements should be prominently displayed
- Error messages need user-friendly translations
The extraction report contains all details needed for comprehensive documentation.
</extraction_example>
<verification_example>
Documentation verification complete for the authentication system.
**Verification Report**: `VERIFICATION-authentication-system.md`
**Overall Assessment**: Needs Updates
**Critical Issues Found**:
1. JWT_SECRET documented as optional, but it's required
2. Token expiration listed as 30m, actual is 15m
3. Missing documentation for rate limiting feature
**Technical Corrections**: 7 items
**Missing Information**: 4 sections
**Clarity Improvements**: 3 suggestions
Please review the verification report for specific corrections needed.
</verification_example>
</completion_message>
<error_handling>
<scenarios>
<scenario type="feature_not_found">
<response>
Could not find a feature matching "[feature name]". Similar features found:
- [List similar features]
Document one of these instead?
</response>
</scenario>
<scenario type="insufficient_docs">
<response>
Code for [feature] has limited inline documentation. Extracting from code structure, tests, and usage patterns.
</response>
</scenario>
<scenario type="complex_feature">
<response>
This feature is complex. Choose documentation scope:
- Document comprehensively
- Focus on core functionality
- Split into multiple documents
</response>
</scenario>
</scenarios>
</error_handling>
<quality_checks>
<before_completion>
<check>No placeholder content remains.</check>
<check>Code examples are correct.</check>
<check>Links and cross-references work.</check>
<check>Tables are formatted correctly.</check>
<check>Version info is included.</check>
<check>Filename follows conventions.</check>
</before_completion>
</quality_checks>
</communication_guidelines>

View file

@ -1,198 +0,0 @@
<workflow>
<step number="1">
<name>Understand Test Requirements</name>
<instructions>
Use ask_followup_question to determine what type of integration test is needed:
<ask_followup_question>
<question>What type of integration test would you like me to create or work on?</question>
<follow_up>
<suggest>New E2E test for a specific feature or workflow</suggest>
<suggest>Fix or update an existing integration test</suggest>
<suggest>Create test utilities or helpers for common patterns</suggest>
<suggest>Debug failing integration tests</suggest>
</follow_up>
</ask_followup_question>
</instructions>
</step>
<step number="2">
<name>Gather Test Specifications</name>
<instructions>
Based on the test type, gather detailed requirements:
For New E2E Tests:
- What specific user workflow or feature needs testing?
- What are the expected inputs and outputs?
- What edge cases or error scenarios should be covered?
- Are there specific API interactions to validate?
- What events should be monitored during the test?
For Existing Test Issues:
- Which test file is failing or needs updates?
- What specific error messages or failures are occurring?
- What changes in the codebase might have affected the test?
For Test Utilities:
- What common patterns are being repeated across tests?
- What helper functions would improve test maintainability?
Use multiple ask_followup_question calls if needed to gather complete information.
</instructions>
</step>
<step number="3">
<name>Explore Existing Test Patterns</name>
<instructions>
Use codebase_search FIRST to understand existing test patterns and similar functionality:
For New Tests:
- Search for similar test scenarios in apps/vscode-e2e/src/suite/
- Find existing test utilities and helpers
- Identify patterns for the type of functionality being tested
For Test Fixes:
- Search for the failing test file and related code
- Find similar working tests for comparison
- Look for recent changes that might have broken the test
Example searches:
- "file creation test mocha" for file operation tests
- "task completion waitUntilCompleted" for task monitoring patterns
- "api message validation" for API interaction tests
After codebase_search, use:
- read_file on relevant test files to understand structure
- list_code_definition_names on test directories
- search_files for specific test patterns or utilities
</instructions>
</step>
<step number="4">
<name>Analyze Test Environment and Setup</name>
<instructions>
Examine the test environment configuration:
1. Read the test runner configuration:
- apps/vscode-e2e/package.json for test scripts
- apps/vscode-e2e/src/runTest.ts for test setup
- Any test configuration files
2. Understand the test workspace setup:
- How test workspaces are created
- What files are available during tests
- How the extension API is accessed
3. Review existing test utilities:
- Helper functions for common operations
- Event listening patterns
- Assertion utilities
- Cleanup procedures
Document findings including:
- Test environment structure
- Available utilities and helpers
- Common patterns and best practices
</instructions>
</step>
<step number="5">
<name>Design Test Structure</name>
<instructions>
Plan the test implementation based on gathered information:
For New Tests:
- Define test suite structure with suite/test blocks
- Plan setup and teardown procedures
- Identify required test data and fixtures
- Design event listeners and validation points
- Plan for both success and failure scenarios
For Test Fixes:
- Identify the root cause of the failure
- Plan the minimal changes needed to fix the issue
- Consider if the test needs to be updated due to code changes
- Plan for improved error handling or debugging
Create a detailed test plan including:
- Test file structure and organization
- Required setup and cleanup
- Specific assertions and validations
- Error handling and edge cases
</instructions>
</step>
<step number="6">
<name>Implement Test Code</name>
<instructions>
Implement the test following established patterns:
CRITICAL: Never write a test file with a single write_to_file call.
Always implement tests in parts:
1. Start with the basic test structure (suite, setup, teardown)
2. Add individual test cases one by one
3. Implement helper functions separately
4. Add event listeners and validation logic incrementally
Follow these implementation guidelines:
- Use suite() and test() blocks following Mocha TDD style
- Always use the global api object for extension interactions
- Implement proper async/await patterns with waitFor utility
- Use waitUntilCompleted and waitUntilAborted helpers for task monitoring
- Listen to and validate appropriate events (message, taskCompleted, etc.)
- Test both positive flows and error scenarios
- Validate message content using proper type assertions
- Create reusable test utilities when patterns emerge
- Use meaningful test descriptions that explain the scenario
- Always clean up tasks with cancelCurrentTask or clearCurrentTask
- Ensure tests are independent and can run in any order
</instructions>
</step>
<step number="7">
<name>Run and Validate Tests</name>
<instructions>
Execute the tests to ensure they work correctly:
ALWAYS use the correct working directory and commands:
- Working directory: apps/vscode-e2e
- Test command: npm run test:run
- For specific tests: TEST_FILE="filename.test" npm run test:run
- Example: cd apps/vscode-e2e && TEST_FILE="apply-diff.test" npm run test:run
Test execution process:
1. Run the specific test file first
2. Check for any failures or errors
3. Analyze test output and logs
4. Debug any issues found
5. Re-run tests after fixes
If tests fail:
- Add console.log statements to track execution flow
- Log important events like task IDs, file paths, and AI responses
- Check test output carefully for error messages and stack traces
- Verify file creation in correct workspace directories
- Ensure proper event handling and timeouts
</instructions>
</step>
<step number="8">
<name>Document and Complete</name>
<instructions>
Finalize the test implementation:
1. Add comprehensive comments explaining complex test logic
2. Document any new test utilities or patterns created
3. Ensure test descriptions clearly explain what is being tested
4. Verify all cleanup procedures are in place
5. Confirm tests can run independently and in any order
Provide the user with:
- Summary of tests created or fixed
- Instructions for running the tests
- Any new patterns or utilities that can be reused
- Recommendations for future test improvements
</instructions>
</step>
</workflow>

View file

@ -1,303 +0,0 @@
<test_patterns>
<mocha_tdd_structure>
<description>Standard Mocha TDD structure for integration tests</description>
<pattern>
<name>Basic Test Suite Structure</name>
<example>
```typescript
import { suite, test, suiteSetup, suiteTeardown } from 'mocha';
import * as assert from 'assert';
import * as vscode from 'vscode';
import { waitFor, waitUntilCompleted, waitUntilAborted } from '../utils/testUtils';
suite('Feature Name Tests', () => {
let testWorkspaceDir: string;
let testFiles: { [key: string]: string } = {};
suiteSetup(async () => {
// Setup test workspace and files
testWorkspaceDir = vscode.workspace.workspaceFolders![0].uri.fsPath;
// Create test files in workspace
});
suiteTeardown(async () => {
// Cleanup test files and tasks
await api.cancelCurrentTask();
});
test('should perform specific functionality', async () => {
// Test implementation
});
});
```
</example>
</pattern>
<pattern>
<name>Event Listening Pattern</name>
<example>
```typescript
test('should handle task completion events', async () => {
const events: any[] = [];
const messageListener = (message: any) => {
events.push({ type: 'message', data: message });
};
const taskCompletedListener = (result: any) => {
events.push({ type: 'taskCompleted', data: result });
};
api.onDidReceiveMessage(messageListener);
api.onTaskCompleted(taskCompletedListener);
try {
// Perform test actions
await api.startTask('test prompt');
await waitUntilCompleted();
// Validate events
assert(events.some(e => e.type === 'taskCompleted'));
} finally {
// Cleanup listeners
api.onDidReceiveMessage(() => {});
api.onTaskCompleted(() => {});
}
});
```
</example>
</pattern>
<pattern>
<name>File Creation Test Pattern</name>
<example>
```typescript
test('should create files in workspace', async () => {
const fileName = 'test-file.txt';
const expectedContent = 'test content';
await api.startTask(`Create a file named ${fileName} with content: ${expectedContent}`);
await waitUntilCompleted();
// Check multiple possible locations
const possiblePaths = [
path.join(testWorkspaceDir, fileName),
path.join(process.cwd(), fileName),
// Add other possible locations
];
let fileFound = false;
let actualContent = '';
for (const filePath of possiblePaths) {
if (fs.existsSync(filePath)) {
actualContent = fs.readFileSync(filePath, 'utf8');
fileFound = true;
break;
}
}
assert(fileFound, `File ${fileName} not found in any expected location`);
assert.strictEqual(actualContent.trim(), expectedContent);
});
```
</example>
</pattern>
</mocha_tdd_structure>
<api_interaction_patterns>
<pattern>
<name>Basic Task Execution</name>
<example>
```typescript
// Start a task and wait for completion
await api.startTask('Your prompt here');
await waitUntilCompleted();
```
</example>
</pattern>
<pattern>
<name>Task with Auto-Approval Settings</name>
<example>
```typescript
// Enable auto-approval for specific actions
await api.updateSettings({
alwaysAllowWrite: true,
alwaysAllowExecute: true
});
await api.startTask('Create and execute a script');
await waitUntilCompleted();
```
</example>
</pattern>
<pattern>
<name>Message Validation</name>
<example>
```typescript
const messages: any[] = [];
api.onDidReceiveMessage((message) => {
messages.push(message);
});
await api.startTask('test prompt');
await waitUntilCompleted();
// Validate specific message types
const toolMessages = messages.filter(m =>
m.type === 'say' && m.say === 'api_req_started'
);
assert(toolMessages.length > 0, 'Expected tool execution messages');
```
</example>
</pattern>
</api_interaction_patterns>
<error_handling_patterns>
<pattern>
<name>Task Abortion Handling</name>
<example>
```typescript
test('should handle task abortion', async () => {
await api.startTask('long running task');
// Abort after short delay
setTimeout(() => api.abortTask(), 1000);
await waitUntilAborted();
// Verify task was properly aborted
const status = await api.getTaskStatus();
assert.strictEqual(status, 'aborted');
});
```
</example>
</pattern>
<pattern>
<name>Error Message Validation</name>
<example>
```typescript
test('should handle invalid input gracefully', async () => {
const errorMessages: any[] = [];
api.onDidReceiveMessage((message) => {
if (message.type === 'error' || message.text?.includes('error')) {
errorMessages.push(message);
}
});
await api.startTask('invalid prompt that should fail');
await waitFor(() => errorMessages.length > 0, 5000);
assert(errorMessages.length > 0, 'Expected error messages');
});
```
</example>
</pattern>
</error_handling_patterns>
<utility_patterns>
<pattern>
<name>File Location Helper</name>
<example>
```typescript
function findFileInWorkspace(fileName: string, workspaceDir: string): string | null {
const possiblePaths = [
path.join(workspaceDir, fileName),
path.join(process.cwd(), fileName),
path.join(os.tmpdir(), fileName),
// Add other common locations
];
for (const filePath of possiblePaths) {
if (fs.existsSync(filePath)) {
return filePath;
}
}
return null;
}
```
</example>
</pattern>
<pattern>
<name>Event Collection Helper</name>
<example>
```typescript
class EventCollector {
private events: any[] = [];
constructor(private api: any) {
this.setupListeners();
}
private setupListeners() {
this.api.onDidReceiveMessage((message: any) => {
this.events.push({ type: 'message', timestamp: Date.now(), data: message });
});
this.api.onTaskCompleted((result: any) => {
this.events.push({ type: 'taskCompleted', timestamp: Date.now(), data: result });
});
}
getEvents(type?: string) {
return type ? this.events.filter(e => e.type === type) : this.events;
}
clear() {
this.events = [];
}
}
```
</example>
</pattern>
</utility_patterns>
<debugging_patterns>
<pattern>
<name>Comprehensive Logging</name>
<example>
```typescript
test('should log execution flow for debugging', async () => {
console.log('Starting test execution');
const events: any[] = [];
api.onDidReceiveMessage((message) => {
console.log('Received message:', JSON.stringify(message, null, 2));
events.push(message);
});
console.log('Starting task with prompt');
await api.startTask('test prompt');
console.log('Waiting for task completion');
await waitUntilCompleted();
console.log('Task completed, events received:', events.length);
console.log('Final workspace state:', fs.readdirSync(testWorkspaceDir));
});
```
</example>
</pattern>
<pattern>
<name>State Validation</name>
<example>
```typescript
function validateTestState(description: string) {
console.log(`=== ${description} ===`);
console.log('Workspace files:', fs.readdirSync(testWorkspaceDir));
console.log('Current working directory:', process.cwd());
console.log('Task status:', api.getTaskStatus?.() || 'unknown');
console.log('========================');
}
```
</example>
</pattern>
</debugging_patterns>
</test_patterns>

View file

@ -1,104 +0,0 @@
<best_practices>
<test_structure>
- Always use suite() and test() blocks following Mocha TDD style
- Use descriptive test names that explain the scenario being tested
- Implement proper setup and teardown in suiteSetup() and suiteTeardown()
- Create test files in the VSCode workspace directory during suiteSetup()
- Store file paths in a test-scoped object for easy reference across tests
- Ensure tests are independent and can run in any order
- Clean up all test files and tasks in suiteTeardown() to avoid test pollution
</test_structure>
<api_interactions>
- Always use the global api object for extension interactions
- Implement proper async/await patterns with the waitFor utility
- Use waitUntilCompleted and waitUntilAborted helpers for task monitoring
- Set appropriate auto-approval settings (alwaysAllowWrite, alwaysAllowExecute) for the functionality being tested
- Listen to and validate appropriate events (message, taskCompleted, taskAborted, etc.)
- Always clean up tasks with cancelCurrentTask or clearCurrentTask after tests
- Use meaningful timeouts that account for actual task execution time
</api_interactions>
<file_system_handling>
- Be aware that files may be created in the workspace directory (/tmp/roo-test-workspace-*) rather than expected locations
- Always check multiple possible file locations when verifying file creation
- Use flexible file location checking that searches workspace directories
- Verify files exist after creation to catch setup issues early
- Account for the fact that the workspace directory is created by runTest.ts
- The AI may use internal tools instead of the documented tools - verify outcomes rather than methods
</file_system_handling>
<event_handling>
- Add multiple event listeners (taskStarted, taskCompleted, taskAborted) for better debugging
- Don't rely on parsing AI messages to detect tool usage - the AI's message format may vary
- Use terminal shell execution events (onDidStartTerminalShellExecution, onDidEndTerminalShellExecution) for command tracking
- Tool executions are reported via api_req_started messages with type="say" and say="api_req_started"
- Focus on testing outcomes (files created, commands executed) rather than message parsing
- There is no "tool_result" message type - tool results appear in "completion_result" or "text" messages
</event_handling>
<error_scenarios>
- Test both positive flows and error scenarios
- Validate message content using proper type assertions
- Implement proper error handling and edge cases
- Use try-catch blocks around critical test operations
- Log important events like task IDs, file paths, and AI responses for debugging
- Check test output carefully for error messages and stack traces
</error_scenarios>
<test_reliability>
- Remove unnecessary waits for specific tool executions - wait for task completion instead
- Simplify message handlers to only capture essential error information
- Use the simplest possible test structure that verifies the outcome
- Avoid complex message parsing logic that depends on AI behavior
- Terminal events are more reliable than message parsing for command execution verification
- Keep prompts simple and direct - complex instructions may confuse the AI
</test_reliability>
<debugging_and_troubleshooting>
- Add console.log statements to track test execution flow
- Log important events like task IDs, file paths, and AI responses
- Use codebase_search first to find similar test patterns before writing new tests
- Create helper functions for common file location checks
- Use descriptive variable names for file paths and content
- Always log the expected vs actual locations when tests fail
- Add comprehensive comments explaining complex test logic
</debugging_and_troubleshooting>
<test_utilities>
- Create reusable test utilities when patterns emerge
- Implement helper functions for common operations like file finding
- Use event collection utilities for consistent event handling
- Create assertion helpers for common validation patterns
- Document any new test utilities or patterns created
- Share common utilities across test files to reduce duplication
</test_utilities>
<ai_interaction_considerations>
- Keep prompts simple and direct - complex instructions may lead to unexpected behavior
- Allow for variations in how the AI accomplishes tasks
- The AI may not always use the exact tool you specify in the prompt
- Be prepared to adapt tests based on actual AI behavior rather than expected behavior
- The AI may interpret instructions creatively - test results rather than implementation details
- The AI will not see the files in the workspace directory, you must tell it to assume they exist and proceed
</ai_interaction_considerations>
<test_execution>
- ALWAYS use the correct working directory: apps/vscode-e2e
- The test command is: npm run test:run
- To run specific tests use environment variable: TEST_FILE="filename.test" npm run test:run
- Example: cd apps/vscode-e2e && TEST_FILE="apply-diff.test" npm run test:run
- Never use npm test directly as it doesn't exist
- Always check available scripts with npm run if unsure
- Run tests incrementally during development to catch issues early
</test_execution>
<code_organization>
- Never write a test file with a single write_to_file tool call
- Always implement tests in parts: structure first, then individual test cases
- Group related tests in the same suite
- Use consistent naming conventions for test files and functions
- Separate test utilities into their own files when they become substantial
- Follow the existing project structure and conventions
</code_organization>
</best_practices>

View file

@ -1,109 +0,0 @@
<common_mistakes_to_avoid>
<test_structure_mistakes>
- Writing a test file with a single write_to_file tool call instead of implementing in parts
- Not using proper Mocha TDD structure with suite() and test() blocks
- Forgetting to implement suiteSetup() and suiteTeardown() for proper cleanup
- Creating tests that depend on each other or specific execution order
- Not cleaning up tasks and files after test completion
- Using describe/it blocks instead of the required suite/test blocks
</test_structure_mistakes>
<api_interaction_mistakes>
- Not using the global api object for extension interactions
- Forgetting to set auto-approval settings (alwaysAllowWrite, alwaysAllowExecute) when testing functionality that requires user approval
- Not implementing proper async/await patterns with waitFor utilities
- Using incorrect timeout values that are too short for actual task execution
- Not properly cleaning up tasks with cancelCurrentTask or clearCurrentTask
- Assuming the AI will use specific tools instead of testing outcomes
</api_interaction_mistakes>
<file_system_mistakes>
- Assuming files will be created in the expected location without checking multiple paths
- Not accounting for the workspace directory being created by runTest.ts
- Creating test files in temporary directories instead of the VSCode workspace directory
- Not verifying files exist after creation during setup
- Forgetting that the AI may not see files in the workspace directory
- Not using flexible file location checking that searches workspace directories
</file_system_mistakes>
<event_handling_mistakes>
- Relying on parsing AI messages to detect tool usage instead of using proper event listeners
- Expecting tool results in "tool_result" message type (which doesn't exist)
- Not listening to terminal shell execution events for command tracking
- Depending on specific message formats that may vary
- Not implementing proper event cleanup after tests
- Parsing complex AI conversation messages instead of focusing on outcomes
</event_handling_mistakes>
<test_execution_mistakes>
- Using npm test instead of npm run test:run
- Not using the correct working directory (apps/vscode-e2e)
- Running tests from the wrong directory
- Not checking available scripts with npm run when unsure
- Forgetting to use TEST_FILE environment variable for specific tests
- Not running tests incrementally during development
</test_execution_mistakes>
<debugging_mistakes>
- Not adding sufficient logging to track test execution flow
- Not logging important events like task IDs, file paths, and AI responses
- Not using codebase_search to find similar test patterns before writing new tests
- Not checking test output carefully for error messages and stack traces
- Not validating test state at critical points
- Assuming test failures are due to code issues without checking test logic
</debugging_mistakes>
<ai_interaction_mistakes>
- Using complex instructions that may confuse the AI
- Expecting the AI to use exact tools specified in prompts
- Not allowing for variations in how the AI accomplishes tasks
- Testing implementation details instead of outcomes
- Not adapting tests based on actual AI behavior
- Forgetting to tell the AI to assume files exist in the workspace directory
</ai_interaction_mistakes>
<reliability_mistakes>
- Adding unnecessary waits for specific tool executions
- Using complex message parsing logic that depends on AI behavior
- Not using the simplest possible test structure
- Depending on specific AI message formats
- Not using terminal events for reliable command execution verification
- Making tests too brittle by depending on exact AI responses
</reliability_mistakes>
<workspace_mistakes>
- Not understanding that files may be created in /tmp/roo-test-workspace-* directories
- Assuming the AI can see files in the workspace directory
- Not checking multiple possible file locations when verifying creation
- Creating files outside the VSCode workspace during tests
- Not properly setting up the test workspace in suiteSetup()
- Forgetting to clean up workspace files in suiteTeardown()
</workspace_mistakes>
<message_handling_mistakes>
- Expecting specific message types for tool execution results
- Not understanding that ClineMessage types have specific values
- Trying to parse tool execution from AI conversation messages
- Not checking packages/types/src/message.ts for valid message types
- Depending on message parsing instead of outcome verification
- Not using api_req_started messages to verify tool execution
</message_handling_mistakes>
<timeout_and_timing_mistakes>
- Using timeouts that are too short for actual task execution
- Not accounting for AI processing time in test timeouts
- Waiting for specific tool executions instead of task completion
- Not implementing proper retry logic for flaky operations
- Using fixed delays instead of condition-based waiting
- Not considering that some operations may take longer in CI environments
</timeout_and_timing_mistakes>
<test_data_mistakes>
- Not creating test files in the correct workspace directory
- Using hardcoded paths that don't work across different environments
- Not storing file paths in test-scoped objects for easy reference
- Creating test data that conflicts with other tests
- Not cleaning up test data properly after tests complete
- Using test data that's too complex for the AI to handle reliably
</test_data_mistakes>
</common_mistakes_to_avoid>

View file

@ -1,209 +0,0 @@
<test_environment_and_tools>
<test_framework>
<description>VSCode E2E testing framework using Mocha and VSCode Test</description>
<key_components>
- Mocha TDD framework for test structure
- VSCode Test framework for extension testing
- Custom test utilities and helpers
- Event-driven testing patterns
- Workspace-based test execution
</key_components>
</test_framework>
<directory_structure>
<test_files_location>apps/vscode-e2e/src/suite/</test_files_location>
<test_utilities>apps/vscode-e2e/src/utils/</test_utilities>
<test_runner>apps/vscode-e2e/src/runTest.ts</test_runner>
<package_config>apps/vscode-e2e/package.json</package_config>
<type_definitions>packages/types/</type_definitions>
</directory_structure>
<test_execution_commands>
<working_directory>apps/vscode-e2e</working_directory>
<commands>
<run_all_tests>npm run test:run</run_all_tests>
<run_specific_test>TEST_FILE="filename.test" npm run test:run</run_specific_test>
<example>cd apps/vscode-e2e && TEST_FILE="apply-diff.test" npm run test:run</example>
<check_scripts>npm run</check_scripts>
</commands>
<important_notes>
- Never use npm test directly as it doesn't exist
- Always use the correct working directory
- Use TEST_FILE environment variable for specific tests
- Check available scripts with npm run if unsure
</important_notes>
</test_execution_commands>
<api_object>
<description>Global api object for extension interactions</description>
<key_methods>
<task_management>
- api.startTask(prompt: string): Start a new task
- api.cancelCurrentTask(): Cancel the current task
- api.clearCurrentTask(): Clear the current task
- api.abortTask(): Abort the current task
- api.getTaskStatus(): Get current task status
</task_management>
<event_listeners>
- api.onDidReceiveMessage(callback): Listen to messages
- api.onTaskCompleted(callback): Listen to task completion
- api.onTaskAborted(callback): Listen to task abortion
- api.onTaskStarted(callback): Listen to task start
- api.onDidStartTerminalShellExecution(callback): Terminal start events
- api.onDidEndTerminalShellExecution(callback): Terminal end events
</event_listeners>
<settings>
- api.updateSettings(settings): Update extension settings
- api.getSettings(): Get current settings
</settings>
</key_methods>
</api_object>
<test_utilities>
<wait_functions>
<waitFor>
<description>Wait for a condition to be true</description>
<usage>await waitFor(() => condition, timeout)</usage>
<example>await waitFor(() => fs.existsSync(filePath), 5000)</example>
</waitFor>
<waitUntilCompleted>
<description>Wait until current task is completed</description>
<usage>await waitUntilCompleted()</usage>
<timeout>Default timeout for task completion</timeout>
</waitUntilCompleted>
<waitUntilAborted>
<description>Wait until current task is aborted</description>
<usage>await waitUntilAborted()</usage>
<timeout>Default timeout for task abortion</timeout>
</waitUntilAborted>
</wait_functions>
<helper_patterns>
<file_location_helper>
<description>Helper to find files in multiple possible locations</description>
<usage>Use when files might be created in different workspace directories</usage>
</file_location_helper>
<event_collector>
<description>Utility to collect and analyze events during test execution</description>
<usage>Use for comprehensive event tracking and validation</usage>
</event_collector>
<assertion_helpers>
<description>Custom assertion functions for common test patterns</description>
<usage>Use for consistent validation across tests</usage>
</assertion_helpers>
</helper_patterns>
</test_utilities>
<workspace_management>
<workspace_creation>
<description>Test workspaces are created by runTest.ts</description>
<location>/tmp/roo-test-workspace-*</location>
<access>vscode.workspace.workspaceFolders![0].uri.fsPath</access>
</workspace_creation>
<file_creation_strategy>
<setup_phase>Create all test files in suiteSetup() before any tests run</setup_phase>
<location>Always create files in the VSCode workspace directory</location>
<verification>Verify files exist after creation to catch setup issues early</verification>
<cleanup>Clean up all test files in suiteTeardown() to avoid test pollution</cleanup>
<storage>Store file paths in a test-scoped object for easy reference</storage>
</file_creation_strategy>
<ai_visibility>
<important_note>The AI will not see the files in the workspace directory</important_note>
<solution>Tell the AI to assume files exist and proceed as if they do</solution>
<verification>Always verify outcomes rather than relying on AI file visibility</verification>
</ai_visibility>
</workspace_management>
<message_types>
<description>Understanding message types for proper event handling</description>
<reference>Check packages/types/src/message.ts for valid message types</reference>
<key_message_types>
<api_req_started>
<type>say</type>
<say>api_req_started</say>
<description>Indicates tool execution started</description>
<text_content>JSON with tool name and execution details</text_content>
<usage>Most reliable way to verify tool execution</usage>
</api_req_started>
<completion_result>
<description>Contains tool execution results</description>
<usage>Tool results appear here, not in "tool_result" type</usage>
</completion_result>
<text_messages>
<description>General AI conversation messages</description>
<caution>Format may vary, don't rely on parsing these for tool detection</caution>
</text_messages>
</key_message_types>
</message_types>
<auto_approval_settings>
<description>Settings to enable automatic approval of AI actions</description>
<critical_settings>
<alwaysAllowWrite>Enable for file creation/modification tests</alwaysAllowWrite>
<alwaysAllowExecute>Enable for command execution tests</alwaysAllowExecute>
<alwaysAllowBrowser>Enable for browser-related tests</alwaysAllowBrowser>
</critical_settings>
<usage>
```typescript
await api.updateSettings({
alwaysAllowWrite: true,
alwaysAllowExecute: true
});
```
</usage>
<importance>Without proper auto-approval settings, the AI won't be able to perform actions without user approval</importance>
</auto_approval_settings>
<debugging_tools>
<console_logging>
<description>Use console.log for tracking test execution flow</description>
<best_practices>
- Log test phase transitions
- Log important events and data
- Log file paths and workspace state
- Log expected vs actual outcomes
</best_practices>
</console_logging>
<state_validation>
<description>Helper functions to validate test state at critical points</description>
<includes>
- Workspace file listing
- Current working directory
- Task status
- Event counts
</includes>
</state_validation>
<error_analysis>
<description>Tools for analyzing test failures</description>
<techniques>
- Stack trace analysis
- Event timeline reconstruction
- File system state comparison
- Message flow analysis
</techniques>
</error_analysis>
</debugging_tools>
<performance_considerations>
<timeouts>
<description>Appropriate timeout values for different operations</description>
<task_completion>Use generous timeouts for task completion (30+ seconds)</task_completion>
<file_operations>Shorter timeouts for file system operations (5-10 seconds)</file_operations>
<event_waiting>Medium timeouts for event waiting (10-15 seconds)</event_waiting>
</timeouts>
<resource_management>
<description>Proper cleanup to avoid resource leaks</description>
<event_listeners>Always clean up event listeners after tests</event_listeners>
<tasks>Cancel or clear tasks in teardown</tasks>
<files>Remove test files to avoid disk space issues</files>
</resource_management>
</performance_considerations>
</test_environment_and_tools>

View file

@ -70,7 +70,7 @@
</step>
<step>
<title>Draft Comment</title>
<description>Draft a comment for the GitHub issue that explains your findings and suggested solution in a conversational, human-like tone.</description>
<description>Draft a comment for the GitHub issue that explains your findings and suggested solution in a conversational, human-like tone. Start the comment with "Hey @roomote-agent,".</description>
</step>
</steps>
</phase>

View file

@ -52,6 +52,7 @@
</category>
<category name="communication">
<item>Does the draft comment sound conversational and human?</item>
<item>Does the draft comment start with "Hey @roomote-agent,"?</item>
<item>Have I avoided technical jargon where possible?</item>
<item>Is the tone helpful and not condescending?</item>
</category>

View file

@ -23,10 +23,16 @@
<practice>Use `gh issue view [URL] --json title,body,labels,comments` to fetch initial details.</practice>
<practice>Use `gh issue comment [URL] --body "..."` to add comments, but only after explicit user approval.</practice>
<practice>Always wrap the comment body in quotes to handle special characters.</practice>
<practice>When posting a comment, the body must start with "Hey @roomote-agent," exactly.</practice>
</best_practices>
<example><![CDATA[
<execute_command>
<command>gh issue view https://github.com/RooCodeInc/Roo-Code/issues/123 --json title,body</command>
</execute_command>
]]></example>
<example><![CDATA[
<execute_command>
<command>gh issue comment https://github.com/RooCodeInc/Roo-Code/issues/123 --body "Hey @roomote-agent, I've investigated and proposed a theoretical fix above."</command>
</execute_command>
]]></example>
</tool>

View file

@ -70,7 +70,7 @@
<step number="6">
<description>Formulate a solution and draft a comment.</description>
<draft>
"Hey, I took a look at this issue and it seems like the problem is in the `handleLogin` function in `src/auth/login.ts`. There's an empty `try...catch` block that is likely catching the login error and preventing any message from being shown to the user.
"Hey @roomote-agent, I took a look at this issue and it seems like the problem is in the `handleLogin` function in `src/auth/login.ts`. There's an empty `try...catch` block that is likely catching the login error and preventing any message from being shown to the user.
A good first step to fixing this would be to add some logging to the `catch` block to see what error is actually happening. Then, we should probably implement proper error feedback to the user on the login page. This should solve the issue of the silent failure."
</draft>

View file

@ -2,18 +2,20 @@
<tone_and_style>
<principle>Be conversational and helpful, not robotic.</principle>
<principle>Write comments as if you are a human developer collaborating on the project.</principle>
<principle>Always start any GitHub issue comment body with "Hey @roomote-agent,".</principle>
<avoid>
<phrase>Analysis complete.</phrase>
<phrase>The investigation has yielded the following result.</phrase>
<phrase>Starting comments with "Hey," instead of "Hey @roomote-agent,".</phrase>
</avoid>
<prefer>
<phrase>Hey, I took a look at this and found something interesting...</phrase>
<phrase>I've been digging into this issue, and I think I've found a possible cause.</phrase>
<phrase>Hey @roomote-agent, I took a look at this and found something interesting...</phrase>
<phrase>Hey @roomote-agent, I've been digging into this issue, and I think I've found a possible cause.</phrase>
</prefer>
</tone_and_style>
<comment_structure>
<element>Start with a friendly opening.</element>
<element>Start every GitHub issue comment with "Hey @roomote-agent,".</element>
<element>State your main finding or hypothesis clearly but not definitively.</element>
<element>Provide context, like file paths and function names.</element>
<element>Propose a next step or a theoretical solution.</element>

File diff suppressed because it is too large Load diff

View file

@ -1,190 +0,0 @@
<github_issue_templates>
<overview>
This mode prioritizes using repository-specific issue templates over hardcoded ones.
If no templates exist in the repository, simple generic templates are created on the fly.
</overview>
<template_detection>
<locations>
<location priority="1">.github/ISSUE_TEMPLATE/*.yml</location>
<location priority="2">.github/ISSUE_TEMPLATE/*.yaml</location>
<location priority="3">.github/ISSUE_TEMPLATE/*.md</location>
<location priority="4">.github/issue_template.md</location>
<location priority="5">.github/ISSUE_TEMPLATE.md</location>
</locations>
<yaml_template_structure>
<field name="name">Display name of the template</field>
<field name="description">Brief description of when to use this template</field>
<field name="title">Default issue title (optional)</field>
<field name="labels">Array of labels to apply</field>
<field name="assignees">Array of default assignees</field>
<field name="body">Array of form elements or markdown content</field>
</yaml_template_structure>
<yaml_form_elements>
<element type="markdown">
<description>Static markdown content</description>
<attributes>
<attr name="value">The markdown content to display</attr>
</attributes>
</element>
<element type="input">
<description>Single-line text input</description>
<attributes>
<attr name="id">Unique identifier</attr>
<attr name="label">Display label</attr>
<attr name="description">Help text</attr>
<attr name="placeholder">Placeholder text</attr>
<attr name="value">Default value</attr>
<attr name="required">Boolean</attr>
</attributes>
</element>
<element type="textarea">
<description>Multi-line text input</description>
<attributes>
<attr name="id">Unique identifier</attr>
<attr name="label">Display label</attr>
<attr name="description">Help text</attr>
<attr name="placeholder">Placeholder text</attr>
<attr name="value">Default value</attr>
<attr name="required">Boolean</attr>
<attr name="render">Language for syntax highlighting</attr>
</attributes>
</element>
<element type="dropdown">
<description>Dropdown selection</description>
<attributes>
<attr name="id">Unique identifier</attr>
<attr name="label">Display label</attr>
<attr name="description">Help text</attr>
<attr name="options">Array of options</attr>
<attr name="required">Boolean</attr>
</attributes>
</element>
<element type="checkboxes">
<description>Multiple checkbox options</description>
<attributes>
<attr name="id">Unique identifier</attr>
<attr name="label">Display label</attr>
<attr name="description">Help text</attr>
<attr name="options">Array of checkbox items</attr>
</attributes>
</element>
</yaml_form_elements>
<markdown_template_structure>
<front_matter>
Optional YAML front matter with:
- name: Template name
- about: Template description
- title: Default title
- labels: Comma-separated or array
- assignees: Comma-separated or array
</front_matter>
<body>
Markdown content with sections and placeholders
Common patterns:
- Headers with ##
- Placeholder text in brackets or as comments
- Checklists with - [ ]
- Code blocks with ```
</body>
</markdown_template_structure>
</template_detection>
<generic_templates>
<description>
When no repository templates exist, create simple templates based on issue type.
These should be minimal and focused on gathering essential information.
</description>
<bug_template>
<structure>
- Description: Clear explanation of the bug
- Steps to Reproduce: Numbered list
- Expected Behavior: What should happen
- Actual Behavior: What actually happens
- Additional Context: Version, environment, logs
- Code Investigation: Findings from exploration (if any)
</structure>
<labels>["bug"]</labels>
</bug_template>
<feature_template>
<structure>
- Problem Description: What problem this solves
- Current Behavior: How it works now
- Proposed Solution: What should change
- Impact: Who benefits and how
- Technical Context: Code findings (if any)
</structure>
<labels>["enhancement", "proposal"]</labels>
</feature_template>
</generic_templates>
<template_parsing_guidelines>
<guideline>
When parsing YAML templates:
1. Use a YAML parser to extract the structure
2. Convert form elements to markdown sections
3. Preserve required field indicators
4. Include descriptions as help text
5. Maintain the intended flow of the template
</guideline>
<guideline>
When parsing Markdown templates:
1. Extract front matter if present
2. Identify section headers
3. Look for placeholder patterns
4. Preserve formatting and structure
5. Replace generic placeholders with user's information
</guideline>
<guideline>
For template selection:
1. If only one template exists, use it automatically
2. If multiple exist, let user choose based on name/description
3. Match template to issue type when possible (bug vs feature)
4. Respect template metadata (labels, assignees, etc.)
</guideline>
</template_parsing_guidelines>
<filling_templates>
<principle>
Fill templates intelligently using gathered information:
- Map user's description to appropriate sections
- Include code investigation findings where relevant
- Preserve template structure and formatting
- Don't leave placeholder text unfilled
- Add contributor scoping if user is contributing
</principle>
<mapping_examples>
<example from="Steps to Reproduce" to="User's reproduction steps + code paths"/>
<example from="Expected behavior" to="What user expects + code logic verification"/>
<example from="System information" to="Detected versions + environment"/>
<example from="Additional context" to="Code findings + architecture insights"/>
</mapping_examples>
</filling_templates>
<no_template_behavior>
<description>
When no templates exist, create appropriate generic templates on the fly.
Keep them simple and focused on essential information.
</description>
<guidelines>
- Don't overwhelm with too many fields
- Focus on problem description first
- Include technical details only if user is contributing
- Use clear, simple section headers
- Adapt based on issue type (bug vs feature)
</guidelines>
</no_template_behavior>
</github_issue_templates>

View file

@ -1,172 +1,147 @@
<best_practices>
<mode_scope>
This mode assembles a template-free issue body grounded by codebase exploration and can submit it via GitHub CLI after explicit confirmation.
Submission uses Title and Body only and targets the detected repository after the merged Review and Submit step.
</mode_scope>
<mode_behavior>
- CRITICAL: This mode assumes the user's FIRST message is already an issue description
- Do NOT ask "What would you like to do?" or "Do you want to create an issue?"
- Immediately start the issue creation workflow when the user begins talking
- Treat their initial message as the problem/feature description
- Begin with repository detection and codebase discovery right away
- The user is already in "issue creation mode" by choosing this mode
- Treat the user's FIRST message as the issue description; do not ask if they want to create an issue.
- Start with repository detection (verify git repo; resolve OWNER/REPO from origin), then determine repository structure (monorepo/standard).
- After detection, begin codebase discovery scoped to the repository root or the selected package (in monorepos).
- Keep final output non-technical; implementation details remain internal.
</mode_behavior>
<template_usage>
- ALWAYS check for repository-specific issue templates before creating issues
- Use templates from .github/ISSUE_TEMPLATE/ directory if they exist
- Parse both YAML (.yml/.yaml) and Markdown (.md) template formats
- If multiple templates exist, let the user choose the appropriate one
- If no templates exist, create a simple generic template on the fly
- NEVER fall back to hardcoded templates - always use repo templates or generate minimal ones
- Respect template metadata like labels, assignees, and title patterns
- Fill templates intelligently using gathered information from codebase exploration
</template_usage>
<value_framing>
<principles>
- Always pair the problem with user-facing value: who is impacted, when it occurs, and why it matters.
- Keep value non-technical (clarity, time saved, fewer errors, better UX, improved accessibility, reduced confusion).
</principles>
<lightweight_impact_options>
- Severity: Blocker | High | Medium | Low (optional)
- Reach: Few | Some | Many (optional)
</lightweight_impact_options>
</value_framing>
<problem_reporting_focus>
- Focus on helping users describe problems clearly, not solutions
- The project team will design solutions unless the user explicitly wants to contribute
- Don't push users to provide technical details they may not have
- Make it easy for non-technical users to report issues effectively
<sourcing_and_provenance>
<direct_from_user_only>
- Reproduction steps
- Variations tried
- Environment details
</direct_from_user_only>
<inference_allowed_with_care>
- Problem/Value statement (plain-language synthesis from user wording)
- Context (who/when) based on user input; keep code-based signals internal
</inference_allowed_with_care>
<hallucination_guards>
- Never fabricate “Variations tried.” If not provided, omit.
- If critical details are missing, ask targeted questions; otherwise proceed with omissions.
</hallucination_guards>
</sourcing_and_provenance>
CRITICAL: Lead with user impact:
- Always explain WHO is affected and WHEN the problem occurs
- Use concrete examples with actual values, not abstractions
- Show before/after scenarios with specific data
- Example: "Users trying to [action] see [actual result] instead of [expected result]"
</problem_reporting_focus>
<cli_submission>
<confirmation>
Use a single merged "Review and Submit" step with options:
- Submit now
- Submit now and assign to me
Any other response is treated as a change request and the step is rerun after applying edits.
</confirmation>
<repo_detection>
Submission requires repository detection (git present, origin configured). Capture normalized OWNER/REPO (e.g., owner/repo) and store as [OWNER_REPO] for submission.
</repo_detection>
<target_repo>
Always specify the target using --repo "[OWNER_REPO]" to avoid ambiguity and ensure the correct repository is used.
</target_repo>
<assignment>
When "Submit now and assign to me" is chosen, create using: --assignee "@me".
If creation with --assignee fails (e.g., permissions), create the issue without an assignee and immediately run:
gh issue edit <issue-url-or-number> --add-assignee "@me".
</assignment>
<command_safety>
Use --body with robust quoting (for example: --body "$(printf '%s\n' "[ISSUE_BODY]")") or a heredoc; do not create temporary files or reference file paths. Always include --repo "[OWNER_REPO]" and echo the resulting issue URL.
In execute_command calls, output only the command string; never include XML tags, CDATA markers, code fences, or backticks in the command payload.
</command_safety>
<error_handling>
On gh errors (installation/auth), present the error and offer to retry after fixing gh setup. Surface the computed Title and Body inline
so the user can submit manually if needed.
</error_handling>
</cli_submission>
<fact_driven_verification>
- ALWAYS verify user claims against actual code implementation
- For feature requests, aggressively check if current behavior matches user's description
- If code shows different intent than user describes, it might be a bug not a feature
- Present code evidence when challenging user assumptions
- Do not be agreeable - be fact-driven and question discrepancies
- Continue verification until facts are established
- A "feature request" where code shows the feature should already work is likely a bug
<codebase_exploration>
<principles>
- Use semantic search first to find relevant areas.
- Refine with targeted regex for exact strings (errors, component names, flags).
- Read key files to verify behavior; keep evidence internal.
- Early-stop when hits converge (~70%) or you can name the exact feature/component.
- Escalate-once if signals conflict; run one refined batch, then proceed.
</principles>
<tool_sequence>
1) codebase_search → 2) search_files → 3) read_file (as needed)
</tool_sequence>
<scoping>
In monorepos, scope searches to the selected package when the context is clear; otherwise ask for the relevant package/app if ambiguous.
</scoping>
<internal_only>
Keep language plain and exclude technical artifacts (paths, line numbers, stack traces, diffs) from the final issue body.
</internal_only>
</codebase_exploration>
CRITICAL additions for thorough analysis:
- Trace data flow from where values are created to where they're used
- Look for existing variables/functions that already contain needed data
- Check if the issue is just missing usage of existing code
- Follow imports and exports to understand data availability
- Identify patterns in similar features that work correctly
</fact_driven_verification>
<questioning>
<guidelines>
- Ask minimal, targeted questions based on what you found in code.
- For bugs: request a minimal reproduction (environment, steps, expected, actual, variations).
- For enhancements: capture user goal, desired behavior in plain language, and any constraints.
- Present discrepancies in plain language (no code) and confirm understanding.
</guidelines>
</questioning>
<general_practices>
- Always search for existing similar issues before creating a new one
- Check for and use repository issue templates before creating content
- Include specific version numbers and environment details
- Use code blocks with syntax highlighting for code snippets
- Make titles descriptive but concise (e.g., "Dark theme: Submit button invisible due to white-on-grey text")
- For bugs, always test if the issue is reproducible
- Include screenshots or mockups when relevant (ask user to provide)
- Link to related issues or PRs if found during exploration
<issue_output_rules>
<format>
<![CDATA[
## Type
Bug | Enhancement
CRITICAL: Use concrete examples throughout:
- Show actual data values, not just descriptions
- Include specific file paths and line numbers
- Demonstrate the data flow with real examples
- Bad: "The value is incorrect"
- Good: "The function returns '123' when it should return '456'"
</general_practices>
## Problem / Value
[One or two sentences that capture the problem and why it matters in plain language]
<contributor_specific>
- Only perform issue scoping if user wants to contribute
- Reference specific files and line numbers from codebase exploration
- Ensure technical proposals align with project architecture
- Include implementation steps and issue scoping
- Provide clear acceptance criteria in Given/When/Then format
- Consider trade-offs and alternative approaches
## Context
[Who is affected and when it happens]
[Enhancement: desired behavior conceptually, in the user's words]
[Bug: current observed behavior in plain language]
CRITICAL: Prioritize simple solutions:
- ALWAYS check if needed functionality already exists before proposing new code
- Look for existing variables that just need to be passed/used differently
- Prefer using existing patterns over creating new ones
- The best fix often involves minimal code changes
- Example: "Use existing `modeInfo` from line 234 in export" vs "Create new mode tracking system"
</contributor_specific>
## Reproduction (Bug only, if available)
1) Steps (each action/command)
2) Expected result
3) Actual result
4) Variations tried (only if explicitly provided)
<backwards_compatibility_focus>
ALWAYS consider backwards compatibility:
- Think about existing data/configurations already in use
- Propose solutions that handle both old and new formats gracefully
- Consider migration paths for existing users
- Document any breaking changes clearly
- Prefer additive changes over breaking changes when possible
</backwards_compatibility_focus>
## Constraints/Preferences
[Performance, accessibility, UX, or other considerations]
]]>
</format>
<rules>
- Omit sections that would be empty.
- Do not include "Variations tried" unless explicitly provided by the user.
- Keep language plain and user-centric.
- Exclude technical artifacts (paths, lines, stacks, diffs).
</rules>
</issue_output_rules>
<review_stage_presentation>
- At each review stage, present the full current issue details (Title + Body) in a markdown code block.
- Offer "Submit now" or "Submit now and assign to me" suggestions; treat any other response as a change request and rerun the step after applying edits.
</review_stage_presentation>
<autonomy_and_budgets>
- Tool preambles: restate goal briefly, outline a short plan, narrate progress succinctly, summarize final delta.
- One-tool-per-message: await results before continuing.
- Discovery budget: default max 3 searches before escalate-once; stop when sufficient.
- Early-stop: when top hits converge or target is identifiable.
- Verbosity: low narrative; detail appears only in structured outputs.
</autonomy_and_budgets>
<communication_guidelines>
- Be supportive and encouraging to problem reporters
- Don't overwhelm users with technical questions upfront
- Clearly indicate when technical sections are optional
- Guide contributors through the additional requirements
- Make the "submit now" option clear for problem reporters
- When presenting template choices, include template descriptions to help users choose
- Explain that you're using the repository's own templates for consistency
- Be direct and concise; avoid jargon in the final issue body.
- Keep questions optional and easy to answer with suggested options.
- Emphasize WHO is affected and WHEN it happens.
</communication_guidelines>
<template_best_practices>
<practice name="template_detection">
Always check these locations in order:
1. .github/ISSUE_TEMPLATE/*.yml or *.yaml (GitHub form syntax)
2. .github/ISSUE_TEMPLATE/*.md (Markdown templates)
3. .github/issue_template.md (single template)
4. .github/ISSUE_TEMPLATE.md (alternate naming)
</practice>
<practice name="template_parsing">
For YAML templates:
- Extract form elements and convert to appropriate markdown sections
- Preserve required field indicators
- Include field descriptions as context
- Respect dropdown options and checkbox lists
For Markdown templates:
- Parse front matter for metadata
- Identify section headers and structure
- Replace placeholder text with actual information
- Maintain formatting and hierarchy
</practice>
<practice name="template_filling">
- Map gathered information to template sections intelligently
- Don't leave placeholder text in the final issue
- Add code investigation findings to relevant sections
- Include contributor scoping in appropriate section if applicable
- Preserve the template's intended structure and flow
</practice>
<practice name="no_template_handling">
When no templates exist:
- Create minimal, focused templates
- Use simple section headers
- Focus on essential information only
- Adapt structure based on issue type
- Don't overwhelm with unnecessary fields
</practice>
</template_best_practices>
<technical_accuracy_guidelines>
<guideline name="thorough_code_analysis">
Before proposing ANY solution:
1. Use codebase_search extensively to find all related code
2. Read multiple files to understand the full context
3. Trace variable usage from creation to consumption
4. Look for similar working features to understand patterns
5. Identify what already exists vs what's actually missing
</guideline>
<guideline name="simplicity_first">
When designing solutions:
1. Check if the data/function already exists somewhere
2. Look for configuration options before code changes
3. Prefer passing existing variables over creating new ones
4. Use established patterns from similar features
5. Aim for minimal diff size
</guideline>
<guideline name="precise_technical_details">
Always include:
- Exact file paths and line numbers
- Variable/function names as they appear in code
- Before/after code snippets showing minimal changes
- Clear explanation of why the simple fix works
</guideline>
</technical_accuracy_guidelines>
</best_practices>

View file

@ -1,126 +1,109 @@
<common_mistakes_to_avoid>
<mode_initialization_mistakes>
- CRITICAL: Asking "What would you like to do?" when mode starts
- Waiting for user to say "create an issue" or "make me an issue"
- Not treating the first user message as the issue description
- Delaying the workflow start with unnecessary questions
- Asking if they want to create an issue when they've already chosen this mode
- Not immediately beginning repository detection and codebase discovery
- Asking "What would you like to do?" at start instead of treating the first message as the issue description
- Delaying the workflow with unnecessary questions before discovery
- Not immediately beginning codebase-aware discovery (semantic search → regex refine → read key files)
- Skipping repository detection (git + origin) before discovery or submission
- Not validating repository context before gh commands
</mode_initialization_mistakes>
<scope_mistakes>
- Submitting without explicit user confirmation ("Submit now")
- Targeting the wrong repository by relying on current directory defaults; always pass --repo OWNER/REPO detected in Step 2
- Performing PR prep, complexity estimates, or technical scoping
</scope_mistakes>
<submission_mistakes>
<mistake_block>
<mistake>Splitting final review and submission into multiple steps</mistake>
<impact>Creates redundant prompts and inconsistent state; leads to janky UX</impact>
<correct_approach>Use a single merged "Review and Submit" step offering only: Submit now, Submit now and assign to me; treat any other response as a change request</correct_approach>
</mistake_block>
<mistake_block>
<mistake>Not offering "Submit now and assign to me"</mistake>
<impact>Forces manual assignment later; reduces efficiency</impact>
<correct_approach>Provide the assignment option and use gh issue create --assignee "@me"; if that fails, immediately run gh issue edit <issue-url-or-number> --add-assignee "@me"</correct_approach>
</mistake_block>
<mistake_block>
<mistake>Using temporary files or --body-file for issue body submission</mistake>
<impact>Introduces filesystem dependencies and leaks paths; contradicts single-command policy</impact>
<correct_approach>Use inline --body with robust quoting, e.g., --body "$(printf '%s\n' "[ISSUE_BODY]")"; do not reference any file paths</correct_approach>
</mistake_block>
<mistake_block>
<mistake>Omitting --repo or relying on current directory defaults</mistake>
<impact>May submit to the wrong repository in multi-repo or worktree contexts</impact>
<correct_approach>Always pass --repo [OWNER_REPO] detected in Step 2</correct_approach>
</mistake_block>
<mistake_block>
<mistake>Attempting submission without prior repository detection</mistake>
<impact>Commands may target the wrong repo or fail</impact>
<correct_approach>Detect git repo and ensure origin is configured before any gh commands</correct_approach>
</mistake_block>
</submission_mistakes>
<sourcing_mistakes>
<mistake_block>
<mistake>Inventing or inferring “Variations tried” when the user didnt provide any</mistake>
<impact>Misleads triage and wastes time reproducing non-existent attempts</impact>
<correct_approach>Omit the “Variations tried” line entirely unless explicitly provided; if needed, ask a targeted question first</correct_approach>
</mistake_block>
<mistake_block>
<mistake>Framing only the problem without the value/impact</mistake>
<impact>Makes prioritization harder; obscures who benefits and why it matters</impact>
<correct_approach>Pair the problem with a plain-language value statement (who, when, why it matters)</correct_approach>
</mistake_block>
<mistake_block>
<mistake>Overstating impact without user signal</mistake>
<impact>Damages credibility and misguides prioritization</impact>
<correct_approach>Use conservative, plain language; if unsure, omit severity/reach or ask a single targeted question</correct_approach>
</mistake_block>
</sourcing_mistakes>
<problem_reporting_mistakes>
- Vague descriptions like "doesn't work" or "broken"
- Missing reproduction steps for bugs
- Feature requests without clear problem statements
- Not explaining the impact on users
- Forgetting to specify when/how the problem occurs
- Using wrong labels or no labels
- Titles that don't summarize the issue
- Not checking for duplicates
- Vague descriptions like "doesn't work" without who/when impact
- Missing minimal reproduction for bugs (environment, steps, expected, actual, variations)
- Enhancement requests that skip the user goal or desired behavior in plain language
- Titles/summaries that don't quickly communicate the issue
</problem_reporting_mistakes>
<workflow_mistakes>
- Asking for technical details from non-contributing users
- Performing issue scoping before confirming user wants to contribute
- Requiring acceptance criteria from problem reporters
- Making the process too complex for simple problem reports
- Not clearly indicating the "submit now" option
- Overwhelming users with contributor requirements upfront
- Using hardcoded templates instead of repository templates
- Not checking for issue templates before creating content
- Ignoring template metadata like labels and assignees
</workflow_mistakes>
<output_mistakes>
- Including code paths, line numbers, stack traces, or diffs in the final issue body
- Adding labels, metadata, or repository details to the body
- Leaving empty section placeholders instead of omitting the section
- Using technical jargon instead of plain, user-centric language
</output_mistakes>
<contributor_mistakes>
- Starting implementation before approval
- Not providing detailed issue scoping when contributing
- Missing acceptance criteria for contributed features
- Forgetting to include technical context from code exploration
- Not considering trade-offs and alternatives
- Proposing solutions without understanding current architecture
</contributor_mistakes>
<technical_analysis_mistakes>
<mistake>Not tracing data flow completely through the system</mistake>
<impact>Missing that data already exists leads to proposing unnecessary new code</impact>
<code_exploration_mistakes>
<mistake>Skipping semantic search and jumping straight to assumptions</mistake>
<impact>Leads to misclassification and inaccurate context</impact>
<correct_approach>
- Use codebase_search extensively to find ALL related code
- Trace variables from creation to consumption
- Check if needed data is already calculated but not used
- Look for similar working features as patterns
- Start with codebase_search on extracted keywords
- Refine with search_files for exact strings (errors, component names, flags)
- read_file only as needed to verify behavior; keep evidence internal
- Early-stop when hits converge or you can name the exact feature/component
- Escalate-once if signals conflict (one refined pass), then proceed
</correct_approach>
<example>
Bad: "Add mode tracking to import function"
Good: "The export already includes mode info at line 234, just use it in import at line 567"
</example>
</technical_analysis_mistakes>
</code_exploration_mistakes>
<solution_design_mistakes>
<mistake>Proposing complex new systems when simple fixes exist</mistake>
<impact>Creates unnecessary complexity, maintenance burden, and potential bugs</impact>
<discrepancy_handling_mistakes>
<mistake>Accepting user claims that contradict the codebase without verification</mistake>
<impact>Produces misleading or incorrect issue framing</impact>
<correct_approach>
- ALWAYS check if functionality already exists first
- Look for minimal changes that solve the problem
- Prefer using existing variables/functions differently
- Aim for the smallest possible diff
- Verify claims against the implementation; trace data from creation → usage
- Compare with similar working features to ground expectations
- If discrepancies arise, present concrete, plain-language examples (no code) and confirm
</correct_approach>
<example>
Bad: "Create new state management system for mode tracking"
Good: "Pass existing modeInfo variable from line 45 to the function at line 78"
</example>
</solution_design_mistakes>
</discrepancy_handling_mistakes>
<code_verification_mistakes>
<mistake>Not reading actual code before proposing solutions</mistake>
<impact>Solutions don't match the actual codebase structure</impact>
<correct_approach>
- Always read the relevant files first
- Verify exact line numbers and content
- Check imports/exports to understand data availability
- Look at similar features that work correctly
</correct_approach>
</code_verification_mistakes>
<questioning_mistakes>
- Asking broad, unfocused questions instead of targeted ones based on findings
- Demanding technical details from non-technical users
- Failing to provide easy, suggested answer formats (repro scaffold, goal statement)
</questioning_mistakes>
<pattern_recognition_mistakes>
<mistake>Creating new patterns instead of following existing ones</mistake>
<impact>Inconsistent codebase, harder to maintain</impact>
<correct_approach>
- Find similar features that work correctly
- Follow the same patterns and structures
- Reuse existing utilities and helpers
- Maintain consistency with the codebase style
</correct_approach>
</pattern_recognition_mistakes>
<template_usage_mistakes>
<mistake>Using hardcoded templates when repository templates exist</mistake>
<impact>Issues don't follow repository conventions, may be rejected or need reformatting</impact>
<correct_approach>
- Always check .github/ISSUE_TEMPLATE/ directory first
- Parse and use repository templates when available
- Only create generic templates when none exist
</correct_approach>
</template_usage_mistakes>
<template_parsing_mistakes>
<mistake>Not properly parsing YAML template structure</mistake>
<impact>Missing required fields, incorrect formatting, lost metadata</impact>
<correct_approach>
- Parse YAML templates to extract all form elements
- Convert form elements to appropriate markdown sections
- Preserve field requirements and descriptions
- Maintain dropdown options and checkbox lists
</correct_approach>
</template_parsing_mistakes>
<template_filling_mistakes>
<mistake>Leaving placeholder text in final issue</mistake>
<impact>Unprofessional appearance, confusion about what information is needed</impact>
<correct_approach>
- Replace all placeholders with actual information
- Remove instruction text meant for template users
- Fill every section with relevant content
- Add "N/A" for truly inapplicable sections
</correct_approach>
</template_filling_mistakes>
<consistency_mistakes>
- Mixing internal technical evidence into the final body
- Ignoring the issue format or adding extra sections
- Using inconsistent tone or switching between technical and non-technical language
</consistency_mistakes>
</common_mistakes_to_avoid>

View file

@ -0,0 +1,134 @@
<issue_examples>
<overview>
Examples of assembling template-free issue prompts grounded by codebase exploration, with optional CLI submission after explicit confirmation.
Repository detection precedes submission; review and submission occur in a single merged step offering "Submit now" or "Submit now and assign to me". Any other response is treated as a change request.
</overview>
<example name="bug_dark_theme_button_invisible">
<user_input>
In dark theme the Submit button is almost invisible on the New Run page.
</user_input>
<discovery>
<tool_calls>
<![CDATA[
<codebase_search>
<query>dark theme submit button visibility</query>
</codebase_search>
<search_files>
<path>.</path>
<regex>Submit|button|dark|theme</regex>
</search_files>
]]>
</tool_calls>
<notes>
Internal: matches found in UI components related to theme; wording grounded to user impact.
</notes>
</discovery>
<final_issue_body><![CDATA[
## Type
Bug
## Problem / Value
In dark theme, the Submit button is hard to see on the new run form, making it difficult for users to complete new runs.
## Context
Affects users creating new runs with dark theme enabled; the button appears low-contrast and is difficult to locate.
## Reproduction
1) Steps: Open "New Run" -> Scroll to bottom -> Look for Submit
2) Expected result: Clearly visible, high-contrast Submit button
3) Actual result: Button appears nearly invisible in dark theme
4) Variations tried: Different browsers (Chrome/Firefox) show same result
]]></final_issue_body>
</example>
<example name="enhancement_copy_run_confirmation">
<user_input>
I accidentally click "Copy Run" sometimes; would be great to have a simple confirmation.
</user_input>
<discovery>
<tool_calls>
<![CDATA[
<codebase_search>
<query>Copy Run confirmation</query>
</codebase_search>
]]>
</tool_calls>
<notes>
Internal: feature entry point identified; keep final output non-technical and user-centric.
</notes>
</discovery>
<final_issue_body><![CDATA[
## Type
Enhancement
## Problem / Value
Add a confirmation dialog before copying an existing run to prevent accidental duplication.
## Context
Users sometimes click "Copy Run" by mistake when browsing runs; a simple confirmation would prevent accidental duplication.
## Constraints/Preferences
Keep the flow lightweight and unobtrusive; avoid slowing down intentional copies.
]]></final_issue_body>
</example>
<example name="bug_submission_review_and_assign">
<user_input>
Dark theme Submit button is invisible; I'd like to file this.
</user_input>
<final_issue_body><![CDATA[
## Type
Bug
## Problem / Value
In dark theme, the Submit button is hard to see on the new run form, making it difficult for users to complete new runs.
## Context
Affects users creating new runs with dark theme enabled; the button appears low-contrast and is difficult to locate.
## Reproduction
1) Steps: Open "New Run" -> Scroll to bottom -> Look for Submit
2) Expected result: Clearly visible, high-contrast Submit button
3) Actual result: Button appears nearly invisible in dark theme
]]></final_issue_body>
<review_and_submit>
<ask_followup_question>
<question>Review the current issue details. Select one of the options below or specify any changes or other workflow you would like me to perform:
```md
Title: [ISSUE_TITLE]
[ISSUE_BODY]
```</question>
<follow_up>
<suggest>Submit now</suggest>
<suggest>Submit now and assign to me</suggest>
</follow_up>
</ask_followup_question>
<execute_command for="submit_now">
<command>gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")"</command>
</execute_command>
<execute_command for="submit_now_and_assign_to_me">
<command>ISSUE_URL=$(gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")" --assignee "@me") || true; if [ -z "$ISSUE_URL" ]; then ISSUE_URL=$(gh issue create --repo "[OWNER_REPO]" --title "[ISSUE_TITLE]" --body "$(printf '%s\n' "[ISSUE_BODY]")"); gh issue edit "$ISSUE_URL" --add-assignee "@me"; fi; echo "$ISSUE_URL"</command>
</execute_command>
<loopback_note>
If a change request is provided, collect the requested edits, update the draft (re-run discovery if new info affects context), then rerun this merged step.
</loopback_note>
<expected_output>https://github.com/OWNER/REPO/issues/123</expected_output>
</review_and_submit>
</example>
<policies>
<policy>Issues are template-free (Title + Body only).</policy>
<policy>Repository detection (git + origin → OWNER/REPO) occurs before submission and is passed explicitly via --repo [OWNER_REPO].</policy>
<policy>Never use --body-file or temporary files; submit with inline --body only (no file paths).</policy>
<policy>Review and submission happen in one merged step offering "Submit now" or "Submit now and assign to me"; any other response is treated as a change request.</policy>
<policy>All discovery is internal; keep final output plain-language.</policy>
</policies>
</issue_examples>

View file

@ -1,342 +0,0 @@
<github_cli_usage>
<overview>
The GitHub CLI (gh) provides comprehensive tools for interacting with GitHub.
Here's when and how to use each command in the issue creation workflow.
Note: This mode prioritizes using repository-specific issue templates over
hardcoded ones. Templates are detected and used dynamically from the repository.
</overview>
<pre_creation_commands>
<command name="gh issue list">
<when_to_use>
ALWAYS use this FIRST before creating any issue to check for duplicates.
Search for keywords from the user's problem description.
</when_to_use>
<example>
<execute_command>
<command>gh issue list --repo $REPO_FULL_NAME --search "dark theme button visibility" --state all --limit 20</command>
</execute_command>
</example>
<options>
--search: Search query for issue titles and bodies
--state: all, open, or closed
--label: Filter by specific labels
--limit: Number of results to show
--json: Get structured JSON output
</options>
</command>
<command name="gh search issues">
<when_to_use>
Use for more advanced searches across issues and pull requests.
Supports GitHub's advanced search syntax.
</when_to_use>
<example>
<execute_command>
<command>gh search issues --repo $REPO_FULL_NAME "dark theme button" --limit 10</command>
</execute_command>
</example>
</command>
<command name="gh issue view">
<when_to_use>
Use when you find a potentially related issue and need full details.
Check if the user's issue is already reported or related.
</when_to_use>
<example>
<execute_command>
<command>gh issue view 123 --repo $REPO_FULL_NAME --comments</command>
</execute_command>
</example>
<options>
--comments: Include issue comments
--json: Get structured data
--web: Open in browser
</options>
</command>
</pre_creation_commands>
<template_detection_commands>
<command name="list_files">
<when_to_use>
Use to check for issue templates in the repository before creating issues.
This is not a gh command but necessary for template detection.
</when_to_use>
<examples>
Check for templates in standard location:
<list_files>
<path>.github/ISSUE_TEMPLATE</path>
<recursive>true</recursive>
</list_files>
Check for single template file:
<list_files>
<path>.github</path>
<recursive>false</recursive>
</list_files>
</examples>
</command>
<command name="read_file">
<when_to_use>
Read template files to parse their structure and content.
Used after detecting template files.
</when_to_use>
<examples>
Read YAML template:
<read_file>
<path>.github/ISSUE_TEMPLATE/bug_report.yml</path>
</read_file>
Read Markdown template:
<read_file>
<path>.github/ISSUE_TEMPLATE/feature_request.md</path>
</read_file>
</examples>
</command>
</template_detection_commands>
<contributor_only_commands>
<note>
These commands should ONLY be used if the user has indicated they want to
contribute the implementation. Skip these for problem reporters.
</note>
<command name="gh repo view">
<when_to_use>
Get repository information and recent activity.
</when_to_use>
<example>
<execute_command>
<command>gh repo view $REPO_FULL_NAME --json defaultBranchRef,description,updatedAt</command>
</execute_command>
</example>
</command>
<command name="gh search prs">
<when_to_use>
Check recent PRs that might be related to the issue.
Look for PRs that modified relevant code.
</when_to_use>
<example>
<execute_command>
<command>gh search prs --repo $REPO_FULL_NAME "dark theme" --limit 10 --state all</command>
</execute_command>
</example>
</command>
<command name="git log">
<when_to_use>
For bug reports from contributors, check recent commits that might have introduced the issue.
Use after cloning the repository locally.
</when_to_use>
<example>
<execute_command>
<command>git log --oneline --grep="theme" -n 20</command>
</execute_command>
</example>
</command>
</contributor_only_commands>
<issue_creation_command>
<command name="gh issue create">
<when_to_use>
Only use after:
1. Confirming no duplicates exist
2. Checking for and using repository templates
3. Gathering all required information
4. Determining if user is contributing or just reporting
5. Getting user confirmation
</when_to_use>
<bug_report_example>
<execute_command>
<command>gh issue create --repo $REPO_FULL_NAME --title "[Descriptive title of the bug]" --body-file /tmp/issue_body.md --label "bug"</command>
</execute_command>
</bug_report_example>
<feature_request_example>
<execute_command>
<command>gh issue create --repo $REPO_FULL_NAME --title "[Problem-focused title]" --body-file /tmp/issue_body.md --label "proposal" --label "enhancement"</command>
</execute_command>
</feature_request_example>
<options>
--title: Issue title (required)
--body: Issue body text
--body-file: Read body from file
--label: Add labels (can use multiple times)
--assignee: Assign to user
--project: Add to project
--web: Open in browser to create
</options>
</command>
</issue_creation_command>
<post_creation_commands>
<command name="gh issue comment">
<when_to_use>
ONLY use if user wants to add additional information after creation.
</when_to_use>
<example>
<execute_command>
<command>gh issue comment 456 --repo $REPO_FULL_NAME --body "Additional context or comments."</command>
</execute_command>
</example>
</command>
<command name="gh issue edit">
<when_to_use>
Use if user realizes they need to update the issue after creation.
Can update title, body, or labels.
</when_to_use>
<example>
<execute_command>
<command>gh issue edit 456 --repo $REPO_FULL_NAME --title "[Updated title]" --body "[Updated body]"</command>
</execute_command>
</example>
</command>
</post_creation_commands>
<workflow_integration>
<step_1_integration>
After user selects issue type, immediately search for related issues:
1. Use `gh issue list --search` with keywords from their description
2. Show any similar issues found
3. Ask if they want to continue or comment on existing issue
</step_1_integration>
<step_2_integration>
Template detection (NEW):
1. Use list_files to check .github/ISSUE_TEMPLATE/ directory
2. Read any template files found (YAML or Markdown)
3. Parse template structure and metadata
4. If multiple templates, let user choose
5. If no templates, prepare to create generic one
</step_2_integration>
<step_3_integration>
Decision point for contribution:
1. Ask user if they want to contribute implementation
2. If yes: Use contributor commands for codebase investigation
3. If no: Skip directly to creating a problem-focused issue
4. This saves time for problem reporters
</step_3_integration>
<step_4_integration>
During codebase exploration (CONTRIBUTORS ONLY):
1. Clone repo locally if needed: `gh repo clone $REPO_FULL_NAME`
2. Use `git log` to find recent changes to affected files
3. Use `gh search prs` for related pull requests
4. Include findings in the technical context section
</step_4_integration>
<step_5_integration>
When creating the issue:
1. Use repository template if found, or generic template if not
2. Fill template with gathered information
3. Format differently based on contributor vs problem reporter
4. Save formatted body to temporary file
5. Use `gh issue create` with appropriate labels from template
6. Capture the returned issue URL
7. Show user the created issue URL
</step_5_integration>
</workflow_integration>
<best_practices>
<practice name="file_handling">
When creating issues with long bodies:
1. Save to temporary file: `cat > /tmp/issue_body.md << 'EOF'`
2. Use --body-file flag with gh issue create
3. Clean up after: `rm /tmp/issue_body.md`
</practice>
<practice name="search_efficiency">
Use specific search terms:
- Include error messages in quotes
- Use label filters when appropriate
- Limit results to avoid overwhelming output
</practice>
<practice name="json_output">
Use --json flag for structured data when needed:
- Easier to parse programmatically
- Consistent format across commands
- Example: `gh issue list --json number,title,state`
</practice>
</best_practices>
<error_handling>
<duplicate_found>
If search finds exact duplicate:
- Show the existing issue to user using `gh issue view`
- Ask if they want to add a comment instead
- Use `gh issue comment` if they agree
</duplicate_found>
<creation_failed>
If `gh issue create` fails:
- Check error message (auth, permissions, network)
- Ensure gh is authenticated: `gh auth status`
- Save the drafted issue content for user
- Suggest using --web flag to create in browser
</creation_failed>
<authentication>
Ensure GitHub CLI is authenticated:
- Check status: `gh auth status`
- Login if needed: `gh auth login`
- Select appropriate scopes for issue creation
</authentication>
</error_handling>
<command_reference>
<issues>
gh issue create - Create new issue
gh issue list - List and search issues
gh issue view - View issue details
gh issue comment - Add comment to issue
gh issue edit - Edit existing issue
gh issue close - Close an issue
gh issue reopen - Reopen closed issue
</issues>
<search>
gh search issues - Search issues and PRs
gh search prs - Search pull requests
gh search repos - Search repositories
</search>
<repository>
gh repo view - View repository info
gh repo clone - Clone repository
</repository>
</command_reference>
<template_handling_reference>
<yaml_template_parsing>
When parsing YAML templates:
- Extract 'name' for template identification
- Get 'labels' array for automatic labeling
- Parse 'body' array for form elements
- Convert form elements to markdown sections
- Preserve 'required' field indicators
</yaml_template_parsing>
<markdown_template_parsing>
When parsing Markdown templates:
- Check for YAML front matter
- Extract metadata (labels, assignees)
- Identify section headers
- Replace placeholder text
- Maintain formatting structure
</markdown_template_parsing>
<template_usage_flow>
1. Detect templates with list_files
2. Read templates with read_file
3. Parse structure and metadata
4. Let user choose if multiple exist
5. Fill template with information
6. Create issue with template content
</template_usage_flow>
</template_handling_reference>
</github_cli_usage>

View file

@ -1,301 +0,0 @@
<mode_management_workflow>
<overview>
This workflow guides you through creating new custom modes or editing existing modes
for the Roo Code Software, ensuring comprehensive understanding and cohesive implementation.
</overview>
<initial_determination>
<step number="1">
<title>Determine User Intent</title>
<description>
Identify whether the user wants to create a new mode or edit an existing one
</description>
<detection_patterns>
<pattern type="edit_existing">
<indicators>
<indicator>User mentions a specific mode by name or slug</indicator>
<indicator>User references a mode directory path (e.g., .roo/rules-[mode-slug])</indicator>
<indicator>User asks to modify, update, enhance, or fix an existing mode</indicator>
<indicator>User says "edit this mode" or "change this mode"</indicator>
</indicators>
</pattern>
<pattern type="create_new">
<indicators>
<indicator>User asks to create a new mode</indicator>
<indicator>User describes a new capability not covered by existing modes</indicator>
<indicator>User says "make a mode for" or "create a mode that"</indicator>
</indicators>
</pattern>
</detection_patterns>
<clarification_question>
<ask_followup_question>
<question>I want to make sure I understand correctly. Are you looking to create a brand new mode or modify an existing one?</question>
<follow_up>
<suggest>Create a new mode for a specific purpose</suggest>
<suggest>Edit an existing mode to add new capabilities</suggest>
<suggest>Fix issues in an existing mode</suggest>
<suggest>Enhance an existing mode with better workflows</suggest>
</follow_up>
</ask_followup_question>
</clarification_question>
</step>
</initial_determination>
<workflow_branches>
<branch name="create_new_mode">
<step number="2a">
<title>Gather Requirements for New Mode</title>
<description>
Understand what the user wants the new mode to accomplish
</description>
<actions>
<action>Ask about the mode's primary purpose and use cases</action>
<action>Identify what types of tasks the mode should handle</action>
<action>Determine what tools and file access the mode needs</action>
<action>Clarify any special behaviors or restrictions</action>
</actions>
<example>
<ask_followup_question>
<question>What is the primary purpose of this new mode? What types of tasks should it handle?</question>
<follow_up>
<suggest>A mode for writing and maintaining documentation</suggest>
<suggest>A mode for database schema design and migrations</suggest>
<suggest>A mode for API endpoint development and testing</suggest>
<suggest>A mode for performance optimization and profiling</suggest>
</follow_up>
</ask_followup_question>
</example>
</step>
<step number="3a">
<title>Design Mode Configuration</title>
<description>
Create the mode definition with all required fields
</description>
<required_fields>
<field name="slug">
<description>Unique identifier (lowercase, hyphens allowed)</description>
<best_practice>Keep it short and descriptive (e.g., "api-dev", "docs-writer")</best_practice>
</field>
<field name="name">
<description>Display name with optional emoji</description>
<best_practice>Use an emoji that represents the mode's purpose</best_practice>
</field>
<field name="roleDefinition">
<description>Detailed description of the mode's role and expertise</description>
<best_practice>
Start with "You are Roo Code, a [specialist type]..."
List specific areas of expertise
Mention key technologies or methodologies
</best_practice>
</field>
<field name="groups">
<description>Tool groups the mode can access</description>
<options>
<option name="read">File reading and searching tools</option>
<option name="edit">File editing tools (can be restricted by regex)</option>
<option name="command">Command execution tools</option>
<option name="browser">Browser interaction tools</option>
<option name="mcp">MCP server tools</option>
</options>
</field>
</required_fields>
<recommended_fields>
<field name="whenToUse">
<description>Clear description for the Orchestrator</description>
<best_practice>Explain specific scenarios and task types</best_practice>
</field>
</recommended_fields>
<important_note>
Do not include customInstructions in the .roomodes configuration.
All detailed instructions should be placed in XML files within
the .roo/rules-[mode-slug]/ directory instead.
</important_note>
</step>
<step number="4a">
<title>Implement File Restrictions</title>
<description>
Configure appropriate file access permissions
</description>
<example>
<comment>Restrict edit access to specific file types</comment>
<code>
groups:
- read
- - edit
- fileRegex: \.(md|txt|rst)$
description: Documentation files only
- command
</code>
</example>
<guidelines>
<guideline>Use regex patterns to limit file editing scope</guideline>
<guideline>Provide clear descriptions for restrictions</guideline>
<guideline>Consider the principle of least privilege</guideline>
</guidelines>
</step>
<step number="5a">
<title>Create XML Instruction Files</title>
<description>
Design structured instruction files in .roo/rules-[mode-slug]/
</description>
<file_structure>
<file name="1_workflow.xml">Main workflow and step-by-step processes</file>
<file name="2_best_practices.xml">Guidelines and conventions</file>
<file name="3_common_patterns.xml">Reusable code patterns and examples</file>
<file name="4_tool_usage.xml">Specific tool usage instructions</file>
<file name="5_examples.xml">Complete workflow examples</file>
</file_structure>
<xml_best_practices>
<practice>Use semantic tag names that describe content</practice>
<practice>Nest tags hierarchically for better organization</practice>
<practice>Include code examples in CDATA sections when needed</practice>
<practice>Add comments to explain complex sections</practice>
</xml_best_practices>
</step>
</branch>
<branch name="edit_existing_mode">
<step number="2b">
<title>Immerse in Existing Mode</title>
<description>
Fully understand the existing mode before making any changes
</description>
<actions>
<action>Locate and read the mode configuration in .roomodes</action>
<action>Read all XML instruction files in .roo/rules-[mode-slug]/</action>
<action>Analyze the mode's current capabilities and limitations</action>
<action>Understand the mode's role in the broader ecosystem</action>
</actions>
<questions_to_ask>
<ask_followup_question>
<question>What specific aspects of the mode would you like to change or enhance?</question>
<follow_up>
<suggest>Add new capabilities or tool permissions</suggest>
<suggest>Fix issues with current workflows or instructions</suggest>
<suggest>Improve the mode's roleDefinition or whenToUse description</suggest>
<suggest>Enhance XML instructions for better clarity</suggest>
</follow_up>
</ask_followup_question>
</questions_to_ask>
</step>
<step number="3b">
<title>Analyze Change Impact</title>
<description>
Understand how proposed changes will affect the mode
</description>
<analysis_areas>
<area>Compatibility with existing workflows</area>
<area>Impact on file permissions and tool access</area>
<area>Consistency with mode's core purpose</area>
<area>Integration with other modes</area>
</analysis_areas>
<validation_questions>
<ask_followup_question>
<question>I've analyzed the existing mode. Here's what I understand about your requested changes. Is this correct?</question>
<follow_up>
<suggest>Yes, that's exactly what I want to change</suggest>
<suggest>Mostly correct, but let me clarify some details</suggest>
<suggest>No, I meant something different</suggest>
<suggest>I'd like to add additional changes</suggest>
</follow_up>
</ask_followup_question>
</validation_questions>
</step>
<step number="4b">
<title>Plan Modifications</title>
<description>
Create a detailed plan for modifying the mode
</description>
<planning_steps>
<step>Identify which files need to be modified</step>
<step>Determine if new XML instruction files are needed</step>
<step>Check for potential conflicts or contradictions</step>
<step>Plan the order of changes for minimal disruption</step>
</planning_steps>
</step>
<step number="5b">
<title>Implement Changes</title>
<description>
Apply the planned modifications to the mode
</description>
<implementation_order>
<change>Update .roomodes configuration if needed</change>
<change>Modify existing XML instruction files</change>
<change>Create new XML instruction files if required</change>
<change>Update examples and documentation</change>
</implementation_order>
</step>
</branch>
</workflow_branches>
<validation_and_cohesion>
<step number="6">
<title>Validate Cohesion and Consistency</title>
<description>
Ensure all changes are cohesive and don't contradict each other
</description>
<validation_checks>
<check type="configuration">
<item>Mode slug follows naming conventions</item>
<item>File restrictions align with mode purpose</item>
<item>Tool permissions are appropriate</item>
<item>whenToUse clearly differentiates from other modes</item>
</check>
<check type="instructions">
<item>All XML files follow consistent structure</item>
<item>No contradicting instructions between files</item>
<item>Examples align with stated workflows</item>
<item>Tool usage matches granted permissions</item>
</check>
<check type="integration">
<item>Mode integrates well with Orchestrator</item>
<item>Clear boundaries with other modes</item>
<item>Handoff points are well-defined</item>
</check>
</validation_checks>
<cohesion_questions>
<ask_followup_question>
<question>I've completed the validation checks. Would you like me to review any specific aspect in more detail?</question>
<follow_up>
<suggest>Review the file permission patterns</suggest>
<suggest>Check for workflow contradictions</suggest>
<suggest>Verify integration with other modes</suggest>
<suggest>Everything looks good, proceed to testing</suggest>
</follow_up>
</ask_followup_question>
</cohesion_questions>
</step>
<step number="7">
<title>Test and Refine</title>
<description>
Verify the mode works as intended
</description>
<checklist>
<item>Mode appears in the mode list</item>
<item>File restrictions work correctly</item>
<item>Instructions are clear and actionable</item>
<item>Mode integrates well with Orchestrator</item>
<item>All examples are accurate and helpful</item>
<item>Changes don't break existing functionality (for edits)</item>
<item>New capabilities work as expected</item>
</checklist>
</step>
</validation_and_cohesion>
<quick_reference>
<command>Create mode in .roomodes for project-specific modes</command>
<command>Create mode in global custom_modes.yaml for system-wide modes</command>
<command>Use list_files to verify .roo folder structure</command>
<command>Test file regex patterns with search_files</command>
<command>Use codebase_search to find existing mode implementations</command>
<command>Read all XML files in a mode directory to understand its structure</command>
<command>Always validate changes for cohesion and consistency</command>
</quick_reference>
</mode_management_workflow>

View file

@ -1,220 +0,0 @@
<xml_structuring_best_practices>
<overview>
XML tags help Claude parse prompts more accurately, leading to higher-quality outputs.
This guide covers best practices for structuring mode instructions using XML.
</overview>
<why_use_xml_tags>
<benefit type="clarity">
Clearly separate different parts of your instructions and ensure well-structured content
</benefit>
<benefit type="accuracy">
Reduce errors caused by Claude misinterpreting parts of your instructions
</benefit>
<benefit type="flexibility">
Easily find, add, remove, or modify parts of instructions without rewriting everything
</benefit>
<benefit type="parseability">
Having Claude use XML tags in its output makes it easier to extract specific parts of responses
</benefit>
</why_use_xml_tags>
<core_principles>
<principle name="consistency">
<description>Use the same tag names throughout your instructions</description>
<example>
Always use <step> for workflow steps, not sometimes <action> or <task>
</example>
</principle>
<principle name="semantic_naming">
<description>Tag names should clearly describe their content</description>
<good_examples>
<tag>detailed_steps</tag>
<tag>error_handling</tag>
<tag>validation_rules</tag>
</good_examples>
<bad_examples>
<tag>stuff</tag>
<tag>misc</tag>
<tag>data1</tag>
</bad_examples>
</principle>
<principle name="hierarchical_nesting">
<description>Nest tags to show relationships and structure</description>
<example>
<workflow>
<phase name="preparation">
<step>Gather requirements</step>
<step>Validate inputs</step>
</phase>
<phase name="execution">
<step>Process data</step>
<step>Generate output</step>
</phase>
</workflow>
</example>
</principle>
</core_principles>
<common_tag_patterns>
<pattern name="workflow_structure">
<usage>For step-by-step processes</usage>
<template><![CDATA[
<workflow>
<overview>High-level description</overview>
<prerequisites>
<prerequisite>Required condition 1</prerequisite>
<prerequisite>Required condition 2</prerequisite>
</prerequisites>
<steps>
<step number="1">
<title>Step Title</title>
<description>What this step accomplishes</description>
<actions>
<action>Specific action to take</action>
</actions>
<validation>How to verify success</validation>
</step>
</steps>
</workflow>
]]></template>
</pattern>
<pattern name="examples_structure">
<usage>For providing code examples and demonstrations</usage>
<template><![CDATA[
<examples>
<example name="descriptive_name">
<description>What this example demonstrates</description>
<context>When to use this approach</context>
<code language="typescript">
// Your code example here
</code>
<explanation>
Key points about the implementation
</explanation>
</example>
</examples>
]]></template>
</pattern>
<pattern name="guidelines_structure">
<usage>For rules and best practices</usage>
<template><![CDATA[
<guidelines category="category_name">
<guideline priority="high">
<rule>The specific rule or guideline</rule>
<rationale>Why this is important</rationale>
<exceptions>When this doesn't apply</exceptions>
</guideline>
</guidelines>
]]></template>
</pattern>
<pattern name="tool_usage_structure">
<usage>For documenting how to use specific tools</usage>
<template><![CDATA[
<tool_usage tool="tool_name">
<purpose>What this tool accomplishes</purpose>
<when_to_use>Specific scenarios for this tool</when_to_use>
<syntax>
<command>The exact command format</command>
<parameters>
<parameter name="param1" required="true">
<description>What this parameter does</description>
<type>string|number|boolean</type>
<example>example_value</example>
</parameter>
</parameters>
</syntax>
<examples>
<example scenario="common_use_case">
<code>Actual usage example</code>
<output>Expected output</output>
</example>
</examples>
</tool_usage>
]]></template>
</pattern>
</common_tag_patterns>
<formatting_guidelines>
<guideline name="indentation">
Use consistent indentation (2 or 4 spaces) for nested elements
</guideline>
<guideline name="line_breaks">
Add line breaks between major sections for readability
</guideline>
<guideline name="comments">
Use XML comments <!-- like this --> to explain complex sections
</guideline>
<guideline name="cdata_sections">
Use CDATA for code blocks or content with special characters:
<![CDATA[<code><![CDATA[your code here]]></code>]]>
</guideline>
<guideline name="attributes_vs_elements">
Use attributes for metadata, elements for content:
<example type="good">
<step number="1" priority="high">
<description>The actual step content</description>
</step>
</example>
</guideline>
</formatting_guidelines>
<anti_patterns>
<anti_pattern name="flat_structure">
<description>Avoid completely flat structures without hierarchy</description>
<bad><![CDATA[
<instructions>
<item1>Do this</item1>
<item2>Then this</item2>
<item3>Finally this</item3>
</instructions>
]]></bad>
<good><![CDATA[
<instructions>
<steps>
<step order="1">Do this</step>
<step order="2">Then this</step>
<step order="3">Finally this</step>
</steps>
</instructions>
]]></good>
</anti_pattern>
<anti_pattern name="inconsistent_naming">
<description>Don't mix naming conventions</description>
<bad>
Mixing camelCase, snake_case, and kebab-case in tag names
</bad>
<good>
Pick one convention (preferably snake_case for XML) and stick to it
</good>
</anti_pattern>
<anti_pattern name="overly_generic_tags">
<description>Avoid tags that don't convey meaning</description>
<bad>data, info, stuff, thing, item</bad>
<good>user_input, validation_result, error_message, configuration</good>
</anti_pattern>
</anti_patterns>
<integration_tips>
<tip>
Reference XML content in instructions:
"Using the workflow defined in &lt;workflow&gt; tags..."
</tip>
<tip>
Combine XML structure with other techniques like multishot prompting
</tip>
<tip>
Use XML tags in expected outputs to make parsing easier
</tip>
<tip>
Create reusable XML templates for common patterns
</tip>
</integration_tips>
</xml_structuring_best_practices>

View file

@ -1,261 +0,0 @@
<mode_configuration_patterns>
<overview>
Common patterns and templates for creating different types of modes, with examples from existing modes in the Roo-Code software.
</overview>
<mode_types>
<type name="specialist_mode">
<description>
Modes focused on specific technical domains or tasks
</description>
<characteristics>
<characteristic>Deep expertise in a particular area</characteristic>
<characteristic>Restricted file access based on domain</characteristic>
<characteristic>Specialized tool usage patterns</characteristic>
</characteristics>
<example_template><![CDATA[
- slug: api-specialist
name: 🔌 API Specialist
roleDefinition: >-
You are Roo Code, an API development specialist with expertise in:
- RESTful API design and implementation
- GraphQL schema design
- API documentation with OpenAPI/Swagger
- Authentication and authorization patterns
- Rate limiting and caching strategies
- API versioning and deprecation
You ensure APIs are:
- Well-documented and discoverable
- Following REST principles or GraphQL best practices
- Secure and performant
- Properly versioned and maintainable
whenToUse: >-
Use this mode when designing, implementing, or refactoring APIs.
This includes creating new endpoints, updating API documentation,
implementing authentication, or optimizing API performance.
groups:
- read
- - edit
- fileRegex: (api/.*\.(ts|js)|.*\.openapi\.yaml|.*\.graphql|docs/api/.*)$
description: API implementation files, OpenAPI specs, and API documentation
- command
- mcp
]]></example_template>
</type>
<type name="workflow_mode">
<description>
Modes that guide users through multi-step processes
</description>
<characteristics>
<characteristic>Step-by-step workflow guidance</characteristic>
<characteristic>Heavy use of ask_followup_question</characteristic>
<characteristic>Process validation at each step</characteristic>
</characteristics>
<example_template><![CDATA[
- slug: migration-guide
name: 🔄 Migration Guide
roleDefinition: >-
You are Roo Code, a migration specialist who guides users through
complex migration processes:
- Database schema migrations
- Framework version upgrades
- API version migrations
- Dependency updates
- Breaking change resolutions
You provide:
- Step-by-step migration plans
- Automated migration scripts
- Rollback strategies
- Testing approaches for migrations
whenToUse: >-
Use this mode when performing any kind of migration or upgrade.
This mode will analyze the current state, plan the migration,
and guide you through each step with validation.
groups:
- read
- edit
- command
]]></example_template>
</type>
<type name="analysis_mode">
<description>
Modes focused on code analysis and reporting
</description>
<characteristics>
<characteristic>Read-heavy operations</characteristic>
<characteristic>Limited or no edit permissions</characteristic>
<characteristic>Comprehensive reporting outputs</characteristic>
</characteristics>
<example_template><![CDATA[
- slug: security-auditor
name: 🔒 Security Auditor
roleDefinition: >-
You are Roo Code, a security analysis specialist focused on:
- Identifying security vulnerabilities
- Analyzing authentication and authorization
- Reviewing data validation and sanitization
- Checking for common security anti-patterns
- Evaluating dependency vulnerabilities
- Assessing API security
You provide detailed security reports with:
- Vulnerability severity ratings
- Specific remediation steps
- Security best practice recommendations
whenToUse: >-
Use this mode to perform security audits on codebases.
This mode will analyze code for vulnerabilities, check
dependencies, and provide actionable security recommendations.
groups:
- read
- command
- - edit
- fileRegex: (SECURITY\.md|\.github/security/.*|docs/security/.*)$
description: Security documentation files only
]]></example_template>
</type>
<type name="creative_mode">
<description>
Modes for generating new content or features
</description>
<characteristics>
<characteristic>Broad file creation permissions</characteristic>
<characteristic>Template and boilerplate generation</characteristic>
<characteristic>Interactive design process</characteristic>
</characteristics>
<example_template><![CDATA[
- slug: component-designer
name: 🎨 Component Designer
roleDefinition: >-
You are Roo Code, a UI component design specialist who creates:
- Reusable React/Vue/Angular components
- Component documentation and examples
- Storybook stories
- Unit tests for components
- Accessibility-compliant interfaces
You follow design system principles and ensure components are:
- Highly reusable and composable
- Well-documented with examples
- Fully tested
- Accessible (WCAG compliant)
- Performance optimized
whenToUse: >-
Use this mode when creating new UI components or refactoring
existing ones. This mode helps design component APIs, implement
the components, and create comprehensive documentation.
groups:
- read
- - edit
- fileRegex: (components/.*|stories/.*|__tests__/.*\.test\.(tsx?|jsx?))$
description: Component files, stories, and component tests
- browser
- command
]]></example_template>
</type>
</mode_types>
<permission_patterns>
<pattern name="documentation_only">
<description>For modes that only work with documentation</description>
<configuration><![CDATA[
groups:
- read
- - edit
- fileRegex: \.(md|mdx|rst|txt)$
description: Documentation files only
]]></configuration>
</pattern>
<pattern name="test_focused">
<description>For modes that work with test files</description>
<configuration><![CDATA[
groups:
- read
- command
- - edit
- fileRegex: (__tests__/.*|__mocks__/.*|.*\.test\.(ts|tsx|js|jsx)$|.*\.spec\.(ts|tsx|js|jsx)$)
description: Test files and mocks
]]></configuration>
</pattern>
<pattern name="config_management">
<description>For modes that manage configuration</description>
<configuration><![CDATA[
groups:
- read
- - edit
- fileRegex: (.*\.config\.(js|ts|json)|.*rc\.json|.*\.yaml|.*\.yml|\.env\.example)$
description: Configuration files (not .env)
]]></configuration>
</pattern>
<pattern name="full_stack">
<description>For modes that need broad access</description>
<configuration><![CDATA[
groups:
- read
- edit # No restrictions
- command
- browser
- mcp
]]></configuration>
</pattern>
</permission_patterns>
<naming_conventions>
<convention category="slug">
<rule>Use lowercase with hyphens</rule>
<good>api-dev, test-writer, docs-manager</good>
<bad>apiDev, test_writer, DocsManager</bad>
</convention>
<convention category="name">
<rule>Use title case with descriptive emoji</rule>
<good>🔧 API Developer, 📝 Documentation Writer</good>
<bad>api developer, DOCUMENTATION WRITER</bad>
</convention>
<convention category="emoji_selection">
<common_emojis>
<emoji meaning="testing">🧪</emoji>
<emoji meaning="documentation">📝</emoji>
<emoji meaning="design">🎨</emoji>
<emoji meaning="debugging">🪲</emoji>
<emoji meaning="building">🏗️</emoji>
<emoji meaning="security">🔒</emoji>
<emoji meaning="api">🔌</emoji>
<emoji meaning="database">🗄️</emoji>
<emoji meaning="performance"></emoji>
<emoji meaning="configuration">⚙️</emoji>
</common_emojis>
</convention>
</naming_conventions>
<integration_guidelines>
<guideline name="orchestrator_compatibility">
<description>Ensure whenToUse is clear for Orchestrator mode</description>
<checklist>
<item>Specify concrete task types the mode handles</item>
<item>Include trigger keywords or phrases</item>
<item>Differentiate from similar modes</item>
<item>Mention specific file types or areas</item>
</checklist>
</guideline>
<guideline name="mode_boundaries">
<description>Define clear boundaries between modes</description>
<checklist>
<item>Avoid overlapping responsibilities</item>
<item>Make handoff points explicit</item>
<item>Use switch_mode when appropriate</item>
<item>Document mode interactions</item>
</checklist>
</guideline>
</integration_guidelines>
</mode_configuration_patterns>

View file

@ -1,367 +0,0 @@
<instruction_file_templates>
<overview>
Templates and examples for creating XML instruction files that provide
detailed guidance for each mode's behavior and workflows.
</overview>
<file_organization>
<principle>Number files to indicate execution order</principle>
<principle>Use descriptive names that indicate content</principle>
<principle>Keep related instructions together</principle>
<standard_structure>
<file>1_workflow.xml - Main workflow and processes</file>
<file>2_best_practices.xml - Guidelines and conventions</file>
<file>3_common_patterns.xml - Reusable code patterns</file>
<file>4_tool_usage.xml - Specific tool instructions</file>
<file>5_examples.xml - Complete workflow examples</file>
<file>6_error_handling.xml - Error scenarios and recovery</file>
<file>7_communication.xml - User interaction guidelines</file>
</standard_structure>
</file_organization>
<workflow_file_template>
<description>Template for main workflow files (1_workflow.xml)</description>
<template><![CDATA[
<workflow_instructions>
<mode_overview>
Brief description of what this mode does and its primary purpose
</mode_overview>
<initialization_steps>
<step number="1">
<action>Understand the user's request</action>
<details>
Parse the user's input to identify:
- Primary objective
- Specific requirements
- Constraints or limitations
</details>
</step>
<step number="2">
<action>Gather necessary context</action>
<tools>
<tool>codebase_search - Find relevant existing code</tool>
<tool>list_files - Understand project structure</tool>
<tool>read_file - Examine specific implementations</tool>
</tools>
</step>
</initialization_steps>
<main_workflow>
<phase name="analysis">
<description>Analyze the current state and requirements</description>
<steps>
<step>Identify affected components</step>
<step>Assess impact of changes</step>
<step>Plan implementation approach</step>
</steps>
</phase>
<phase name="implementation">
<description>Execute the planned changes</description>
<steps>
<step>Create/modify necessary files</step>
<step>Ensure consistency across codebase</step>
<step>Add appropriate documentation</step>
</steps>
</phase>
<phase name="validation">
<description>Verify the implementation</description>
<steps>
<step>Check for errors or inconsistencies</step>
<step>Validate against requirements</step>
<step>Ensure no regressions</step>
</steps>
</phase>
</main_workflow>
<completion_criteria>
<criterion>All requirements have been addressed</criterion>
<criterion>Code follows project conventions</criterion>
<criterion>Changes are properly documented</criterion>
<criterion>No breaking changes introduced</criterion>
</completion_criteria>
</workflow_instructions>
]]></template>
</workflow_file_template>
<best_practices_template>
<description>Template for best practices files (2_best_practices.xml)</description>
<template><![CDATA[
<best_practices>
<general_principles>
<principle priority="high">
<name>Principle Name</name>
<description>Detailed explanation of the principle</description>
<rationale>Why this principle is important</rationale>
<example>
<scenario>When this applies</scenario>
<good>Correct approach</good>
<bad>What to avoid</bad>
</example>
</principle>
</general_principles>
<code_conventions>
<convention category="naming">
<rule>Specific naming convention</rule>
<examples>
<good>goodExampleName</good>
<bad>bad_example-name</bad>
</examples>
</convention>
<convention category="structure">
<rule>How to structure code/files</rule>
<template>
// Example structure
</template>
</convention>
</code_conventions>
<common_pitfalls>
<pitfall>
<description>Common mistake to avoid</description>
<why_problematic>Explanation of issues it causes</why_problematic>
<correct_approach>How to do it properly</correct_approach>
</pitfall>
</common_pitfalls>
<quality_checklist>
<category name="before_starting">
<item>Understand requirements fully</item>
<item>Check existing implementations</item>
</category>
<category name="during_implementation">
<item>Follow established patterns</item>
<item>Write clear documentation</item>
</category>
<category name="before_completion">
<item>Review all changes</item>
<item>Verify requirements met</item>
</category>
</quality_checklist>
</best_practices>
]]></template>
</best_practices_template>
<tool_usage_template>
<description>Template for tool usage files (4_tool_usage.xml)</description>
<template><![CDATA[
<tool_usage_guide>
<tool_priorities>
<priority level="1">
<tool>codebase_search</tool>
<when>Always use first to find relevant code</when>
<why>Semantic search finds functionality better than keywords</why>
</priority>
<priority level="2">
<tool>read_file</tool>
<when>After identifying files with codebase_search</when>
<why>Get full context of implementations</why>
</priority>
</tool_priorities>
<tool_specific_guidance>
<tool name="apply_diff">
<best_practices>
<practice>Always read file first to ensure exact content match</practice>
<practice>Make multiple changes in one diff when possible</practice>
<practice>Include line numbers for accuracy</practice>
</best_practices>
<example><![CDATA[
<apply_diff>
<path>src/config.ts</path>
<diff>
<<<<<<< SEARCH
:start_line:10
-------
export const config = {
apiUrl: 'http://localhost:3000',
timeout: 5000
};
=======
export const config = {
apiUrl: process.env.API_URL || 'http://localhost:3000',
timeout: parseInt(process.env.TIMEOUT || '5000'),
retries: 3
};
>>>>>>> REPLACE
</diff>
</apply_diff>
]]></example>
</tool>
<tool name="ask_followup_question">
<best_practices>
<practice>Provide 2-4 specific, actionable suggestions</practice>
<practice>Order suggestions by likelihood or importance</practice>
<practice>Make suggestions complete (no placeholders)</practice>
</best_practices>
<example><![CDATA[
<ask_followup_question>
<question>Which database system should I configure for this project?</question>
<follow_up>
<suggest>PostgreSQL with the default configuration</suggest>
<suggest>MySQL 8.0 with InnoDB storage engine</suggest>
<suggest>SQLite for local development only</suggest>
<suggest>MongoDB for document-based storage</suggest>
</follow_up>
</ask_followup_question>
]]></example>
</tool>
</tool_specific_guidance>
<tool_combination_patterns>
<pattern name="explore_then_modify">
<sequence>
<step>codebase_search - Find relevant files</step>
<step>list_code_definition_names - Understand structure</step>
<step>read_file - Get full context</step>
<step>apply_diff or write_to_file - Make changes</step>
</sequence>
</pattern>
<pattern name="verify_then_proceed">
<sequence>
<step>list_files - Check file exists</step>
<step>read_file - Verify current content</step>
<step>ask_followup_question - Confirm approach</step>
<step>apply_diff - Implement changes</step>
</sequence>
</pattern>
</tool_combination_patterns>
</tool_usage_guide>
]]></template>
</tool_usage_template>
<examples_file_template>
<description>Template for example files (5_examples.xml)</description>
<template><![CDATA[
<complete_examples>
<example name="descriptive_example_name">
<scenario>
Detailed description of the use case this example covers
</scenario>
<user_request>
The initial request from the user
</user_request>
<workflow>
<step number="1">
<description>First step description</description>
<tool_use><![CDATA[
<codebase_search>
<query>search query here</query>
</codebase_search>
]]></tool_use>
<expected_outcome>What we learn from this step</expected_outcome>
</step>
<step number="2">
<description>Second step description</description>
<tool_use><![CDATA[
<read_file>
<path>path/to/file.ts</path>
</read_file>
]]></tool_use>
<analysis>How we interpret the results</analysis>
</step>
<step number="3">
<description>Implementation step</description>
<tool_use><![CDATA[
<apply_diff>
<path>path/to/file.ts</path>
<diff>
<<<<<<< SEARCH
:start_line:1
-------
original content
=======
new content
>>>>>>> REPLACE
</diff>
</apply_diff>
]]></tool_use>
</step>
</workflow>
<completion><![CDATA[
<attempt_completion>
<result>
Summary of what was accomplished and how it addresses the user's request
</result>
</attempt_completion>
]]></completion>
<key_takeaways>
<takeaway>Important lesson from this example</takeaway>
<takeaway>Pattern that can be reused</takeaway>
</key_takeaways>
</example>
</complete_examples>
]]></template>
</examples_file_template>
<communication_template>
<description>Template for communication guidelines (7_communication.xml)</description>
<template><![CDATA[
<communication_guidelines>
<tone_and_style>
<principle>Be direct and technical, not conversational</principle>
<principle>Focus on actions taken and results achieved</principle>
<avoid>
<phrase>Great! I'll help you with that...</phrase>
<phrase>Certainly! Let me...</phrase>
<phrase>Sure thing!</phrase>
</avoid>
<prefer>
<phrase>I'll analyze the codebase to...</phrase>
<phrase>Implementing the requested changes...</phrase>
<phrase>The analysis shows...</phrase>
</prefer>
</tone_and_style>
<user_interaction>
<when_to_ask_questions>
<scenario>Missing critical information</scenario>
<scenario>Multiple valid approaches exist</scenario>
<scenario>Potential breaking changes</scenario>
</when_to_ask_questions>
<question_format>
<guideline>Be specific about what you need</guideline>
<guideline>Provide actionable options</guideline>
<guideline>Explain implications of choices</guideline>
</question_format>
</user_interaction>
<progress_updates>
<when>During long-running operations</when>
<format>
<update>Analyzing [X] files for [purpose]...</update>
<update>Implementing [feature] in [location]...</update>
<update>Validating changes against [criteria]...</update>
</format>
</progress_updates>
<completion_messages>
<structure>
<element>What was accomplished</element>
<element>Key changes made</element>
<element>Any important notes or warnings</element>
</structure>
<avoid>
<element>Questions at the end</element>
<element>Offers for further assistance</element>
<element>Conversational closings</element>
</avoid>
</completion_messages>
</communication_guidelines>
]]></template>
</communication_template>
</instruction_file_templates>

View file

@ -1,214 +0,0 @@
<complete_examples>
<example name="mode_editing_enhancement">
<scenario>
Edit the test mode to add support for performance testing and benchmarking
</scenario>
<user_request>
I want to edit the test mode to add benchmark testing capabilities
</user_request>
<workflow>
<step number="1">
<description>Determine user intent and clarify scope</description>
<tool_use><![CDATA[
<ask_followup_question>
<question>I understand you want to edit the test mode to add performance testing capabilities. Before we proceed, let me confirm the scope of changes. What specific performance testing features do you need?</question>
<follow_up>
<suggest>Add benchmark testing with Vitest's bench API</suggest>
<suggest>Include performance profiling and memory usage tracking</suggest>
<suggest>Add load testing capabilities for API endpoints</suggest>
<suggest>All of the above - comprehensive performance testing suite</suggest>
</follow_up>
</ask_followup_question>
]]></tool_use>
<expected_outcome>User selected: Add benchmark testing with Vitest's bench API</expected_outcome>
</step>
<step number="2">
<description>Immerse in existing test mode configuration</description>
<tool_use><![CDATA[
<read_file>
<path>.roomodes</path>
</read_file>
]]></tool_use>
<analysis>Found test mode configuration with current roleDefinition and file restrictions</analysis>
</step>
<step number="3">
<description>Explore existing test mode instructions</description>
<tool_use><![CDATA[
<list_files>
<path>.roo/rules-test</path>
<recursive>true</recursive>
</list_files>
]]></tool_use>
<tool_use><![CDATA[
<read_file>
<path>.roo/rules-test/1_workflow.xml</path>
</read_file>
]]></tool_use>
<analysis>Understood current test workflows and patterns</analysis>
</step>
<step number="4">
<description>Validate changes for cohesion</description>
<tool_use><![CDATA[
<ask_followup_question>
<question>I've analyzed the test mode. Adding benchmark testing would require:
1. Updating the roleDefinition to include performance testing expertise
2. Modifying file restrictions to include .bench.ts files
3. Adding new workflow instructions for benchmark creation
4. Including Vitest bench API examples
This aligns well with the existing testing focus. Should I proceed with all these changes?</question>
<follow_up>
<suggest>Yes, implement all the changes as described</suggest>
<suggest>Start with just the roleDefinition and file restrictions</suggest>
<suggest>Focus only on the workflow instructions first</suggest>
<suggest>Let me review the specific changes before proceeding</suggest>
</follow_up>
</ask_followup_question>
]]></tool_use>
<expected_outcome>User selected: Yes, implement all the changes as described</expected_outcome>
</step>
<step number="5">
<description>Update mode configuration in .roomodes</description>
<tool_use><![CDATA[
<apply_diff>
<path>.roomodes</path>
<diff>
<<<<<<< SEARCH
roleDefinition: |-
You are Roo, a Vitest testing specialist with deep expertise in: - Writing and maintaining Vitest test suites - Test-driven development (TDD) practices - Mocking and stubbing with Vitest - Integration testing strategies - TypeScript testing patterns - Code coverage analysis - Test performance optimization
=======
roleDefinition: |-
You are Roo, a Vitest testing specialist with deep expertise in: - Writing and maintaining Vitest test suites - Test-driven development (TDD) practices - Mocking and stubbing with Vitest - Integration testing strategies - TypeScript testing patterns - Code coverage analysis - Test performance optimization - Benchmark testing with Vitest bench API - Performance profiling and optimization - Memory usage analysis in tests
>>>>>>> REPLACE
</diff>
</apply_diff>
]]></tool_use>
</step>
<step number="6">
<description>Update file restrictions to include benchmark files</description>
<tool_use><![CDATA[
<apply_diff>
<path>.roomodes</path>
<diff>
<<<<<<< SEARCH
- fileRegex: (__tests__/.*|__mocks__/.*|\.test\.(ts|tsx|js|jsx)$|\.spec\.(ts|tsx|js|jsx)$|/test/.*|vitest\.config\.(js|ts)$|vitest\.setup\.(js|ts)$)
description: Test files, mocks, and Vitest configuration
=======
- fileRegex: (__tests__/.*|__mocks__/.*|\.test\.(ts|tsx|js|jsx)$|\.spec\.(ts|tsx|js|jsx)$|\.bench\.(ts|tsx|js|jsx)$|/test/.*|vitest\.config\.(js|ts)$|vitest\.setup\.(js|ts)$)
description: Test files, benchmarks, mocks, and Vitest configuration
>>>>>>> REPLACE
</diff>
</apply_diff>
]]></tool_use>
</step>
<step number="7">
<description>Create new benchmark workflow instructions</description>
<tool_use><![CDATA[
<write_to_file>
<path>.roo/rules-test/5_benchmark_testing.xml</path>
<content>
<benchmark_testing_guide>
<overview>
Guidelines for creating and maintaining performance benchmarks using Vitest bench API
</overview>
<benchmark_patterns>
<pattern name="basic_benchmark">
<description>Basic benchmark structure</description>
<example><![CDATA[
import { bench, describe } from 'vitest';
describe('Array operations', () => {
bench('Array.push', () => {
const arr = [];
for (let i = 0; i < 1000; i++) {
arr.push(i);
}
});
bench('Array spread', () => {
let arr = [];
for (let i = 0; i < 1000; i++) {
arr = [...arr, i];
}
});
});
]]></example>
</pattern>
</benchmark_patterns>
<best_practices>
<practice>Use meaningful benchmark names that describe what's being measured</practice>
<practice>Include baseline comparisons when optimizing code</practice>
<practice>Run benchmarks in isolation to avoid interference</practice>
<practice>Document performance expectations and thresholds</practice>
</best_practices>
</benchmark_testing_guide>
</content>
<line_count>38</line_count>
</write_to_file>
]]></tool_use>
</step>
<step number="8">
<description>Validate all changes for consistency</description>
<tool_use><![CDATA[
<ask_followup_question>
<question>I've completed all the changes to add benchmark testing capabilities to the test mode:
1. ✓ Updated roleDefinition to include benchmark expertise
2. ✓ Modified file restrictions to include .bench.ts files
3. ✓ Created new benchmark workflow instructions
4. ✓ Added Vitest bench API examples
All changes are cohesive and align with the existing test mode structure. Would you like me to test any specific aspect of these changes?</question>
<follow_up>
<suggest>Test creating a new benchmark file to verify file permissions</suggest>
<suggest>Review the complete changes one more time</suggest>
<suggest>Everything looks good, the mode is ready</suggest>
<suggest>Create a simple benchmark example to test</suggest>
</follow_up>
</ask_followup_question>
]]></tool_use>
</step>
</workflow>
<completion><![CDATA[
<attempt_completion>
<result>
I've successfully enhanced the test mode with benchmark testing capabilities:
1. Updated the roleDefinition to include:
- Benchmark testing with Vitest bench API
- Performance profiling and optimization
- Memory usage analysis in tests
2. Modified file restrictions to include .bench.ts files, allowing the mode to create and edit benchmark files
3. Created new workflow instructions at .roo/rules-test/5_benchmark_testing.xml with:
- Basic benchmark patterns
- Best practices for performance testing
- Example code using Vitest's bench API
All changes have been validated for cohesion and consistency with the existing test mode structure. The mode now supports comprehensive performance testing alongside its existing unit and integration testing capabilities.
</result>
</attempt_completion>
]]></completion>
<key_takeaways>
<takeaway>Always immerse yourself in the existing mode before making changes</takeaway>
<takeaway>Use ask_followup_question aggressively to clarify scope and validate changes</takeaway>
<takeaway>Validate all changes for cohesion and consistency</takeaway>
<takeaway>Update all relevant parts: configuration, file restrictions, and instructions</takeaway>
<takeaway>Test changes to ensure they work as expected</takeaway>
</key_takeaways>
</example>
</complete_examples>

View file

@ -1,207 +0,0 @@
<mode_testing_validation>
<overview>
Guidelines for testing and validating newly created modes to ensure they function correctly and integrate well with the Roo Code ecosystem.
</overview>
<validation_checklist>
<category name="configuration_validation">
<item priority="critical">
<check>Mode slug is unique and follows naming conventions</check>
<validation>No spaces, lowercase, hyphens only</validation>
</item>
<item priority="critical">
<check>All required fields are present and non-empty</check>
<fields>slug, name, roleDefinition, groups</fields>
</item>
<item priority="critical">
<check>No customInstructions field in .roomodes</check>
<validation>All instructions must be in XML files in .roo/rules-[slug]/</validation>
</item>
<item priority="high">
<check>File restrictions use valid regex patterns</check>
<test_method><![CDATA[
<search_files>
<path>.</path>
<regex>your_file_regex_here</regex>
</search_files>
]]></test_method>
</item>
<item priority="high">
<check>whenToUse clearly differentiates from other modes</check>
<validation>Compare with existing mode descriptions</validation>
</item>
</category>
<category name="instruction_validation">
<item>
<check>XML files are well-formed and valid</check>
<validation>No syntax errors, proper closing tags</validation>
</item>
<item>
<check>Instructions follow XML best practices</check>
<validation>Semantic tag names, proper nesting</validation>
</item>
<item>
<check>Examples use correct tool syntax</check>
<validation>Tool parameters match current API</validation>
</item>
<item>
<check>File paths in examples are consistent</check>
<validation>Use project-relative paths</validation>
</item>
</category>
<category name="functional_testing">
<item>
<check>Mode appears in mode list</check>
<test>Switch to the new mode and verify it loads</test>
</item>
<item>
<check>Tool permissions work as expected</check>
<test>Try using each tool group and verify access</test>
</item>
<item>
<check>File restrictions are enforced</check>
<test>Attempt to edit allowed and restricted files</test>
</item>
<item>
<check>Mode handles edge cases gracefully</check>
<test>Test with minimal input, errors, edge cases</test>
</item>
</category>
</validation_checklist>
<testing_workflow>
<step number="1">
<title>Configuration Testing</title>
<actions>
<action>Verify mode appears in available modes list</action>
<action>Check that mode metadata displays correctly</action>
<action>Confirm mode can be activated</action>
</actions>
<verification><![CDATA[
<ask_followup_question>
<question>I've created the mode configuration. Can you see the new mode in your mode list?</question>
<follow_up>
<suggest>Yes, I can see the new mode and switch to it</suggest>
<suggest>No, the mode doesn't appear in the list</suggest>
<suggest>The mode appears but has errors when switching</suggest>
</follow_up>
</ask_followup_question>
]]></verification>
</step>
<step number="2">
<title>Permission Testing</title>
<test_cases>
<test case="read_permissions">
<action>Use read tools on various files</action>
<expected>All read operations should work</expected>
</test>
<test case="edit_restrictions">
<action>Try editing allowed file types</action>
<expected>Edits succeed for matching patterns</expected>
</test>
<test case="edit_restrictions_negative">
<action>Try editing restricted file types</action>
<expected>FileRestrictionError for non-matching files</expected>
</test>
</test_cases>
</step>
<step number="3">
<title>Workflow Testing</title>
<actions>
<action>Execute main workflow from start to finish</action>
<action>Test each decision point</action>
<action>Verify error handling</action>
<action>Check completion criteria</action>
</actions>
</step>
<step number="4">
<title>Integration Testing</title>
<areas>
<area>Orchestrator mode compatibility</area>
<area>Mode switching functionality</area>
<area>Tool handoff between modes</area>
<area>Consistent behavior with other modes</area>
</areas>
</step>
</testing_workflow>
<common_issues>
<issue type="configuration">
<problem>Mode doesn't appear in list</problem>
<causes>
<cause>Syntax error in YAML</cause>
<cause>Invalid mode slug</cause>
<cause>File not saved</cause>
</causes>
<solution>Check YAML syntax, validate slug format</solution>
</issue>
<issue type="permissions">
<problem>File restriction not working</problem>
<causes>
<cause>Invalid regex pattern</cause>
<cause>Escaping issues in regex</cause>
<cause>Wrong file path format</cause>
</causes>
<solution>Test regex pattern, use proper escaping</solution>
<example><![CDATA[
# Wrong: *.ts (glob pattern)
# Right: .*\.ts$ (regex pattern)
]]></example>
</issue>
<issue type="behavior">
<problem>Mode not following instructions</problem>
<causes>
<cause>Instructions not in .roo/rules-[slug]/ folder</cause>
<cause>XML parsing errors</cause>
<cause>Conflicting instructions</cause>
</causes>
<solution>Verify file locations and XML validity</solution>
</issue>
</common_issues>
<debugging_tools>
<tool name="list_files">
<usage>Verify instruction files exist in correct location</usage>
<command><![CDATA[
<list_files>
<path>.roo</path>
<recursive>true</recursive>
</list_files>
]]></command>
</tool>
<tool name="read_file">
<usage>Check mode configuration syntax</usage>
<command><![CDATA[
<read_file>
<path>.roomodes</path>
</read_file>
]]></command>
</tool>
<tool name="search_files">
<usage>Test file restriction patterns</usage>
<command><![CDATA[
<search_files>
<path>.</path>
<regex>your_file_pattern_here</regex>
</search_files>
]]></command>
</tool>
</debugging_tools>
<best_practices>
<practice>Test incrementally as you build the mode</practice>
<practice>Start with minimal configuration and add complexity</practice>
<practice>Document any special requirements or dependencies</practice>
<practice>Consider edge cases and error scenarios</practice>
<practice>Get feedback from potential users of the mode</practice>
</best_practices>
</mode_testing_validation>

View file

@ -1,201 +0,0 @@
<validation_cohesion_checking>
<overview>
Guidelines for thoroughly validating mode changes to ensure cohesion,
consistency, and prevent contradictions across all mode components.
</overview>
<validation_principles>
<principle name="comprehensive_review">
<description>
Every change must be reviewed in context of the entire mode
</description>
<checklist>
<item>Read all existing XML instruction files</item>
<item>Verify new changes align with existing patterns</item>
<item>Check for duplicate or conflicting instructions</item>
<item>Ensure terminology is consistent throughout</item>
</checklist>
</principle>
<principle name="aggressive_questioning">
<description>
Use ask_followup_question extensively to clarify ambiguities
</description>
<when_to_ask>
<scenario>User's intent is unclear</scenario>
<scenario>Multiple interpretations are possible</scenario>
<scenario>Changes might conflict with existing functionality</scenario>
<scenario>Impact on other modes needs clarification</scenario>
</when_to_ask>
<example><![CDATA[
<ask_followup_question>
<question>I notice this change might affect how the mode interacts with file permissions. Should we also update the file regex patterns to match?</question>
<follow_up>
<suggest>Yes, update the file regex to include the new file types</suggest>
<suggest>No, keep the current file restrictions as they are</suggest>
<suggest>Let me explain what file types I need to work with</suggest>
<suggest>Show me the current file restrictions first</suggest>
</follow_up>
</ask_followup_question>
]]></example>
</principle>
<principle name="contradiction_detection">
<description>
Actively search for and resolve contradictions
</description>
<common_contradictions>
<contradiction>
<type>Permission Mismatch</type>
<description>Instructions reference tools the mode doesn't have access to</description>
<resolution>Either grant the tool permission or update the instructions</resolution>
</contradiction>
<contradiction>
<type>Workflow Conflicts</type>
<description>Different XML files describe conflicting workflows</description>
<resolution>Consolidate workflows and ensure single source of truth</resolution>
</contradiction>
<contradiction>
<type>Role Confusion</type>
<description>Mode's roleDefinition doesn't match its actual capabilities</description>
<resolution>Update roleDefinition to accurately reflect the mode's purpose</resolution>
</contradiction>
</common_contradictions>
</principle>
</validation_principles>
<validation_workflow>
<phase name="pre_change_analysis">
<description>Before making any changes</description>
<steps>
<step>Read and understand all existing mode files</step>
<step>Create a mental model of current mode behavior</step>
<step>Identify potential impact areas</step>
<step>Ask clarifying questions about intended changes</step>
</steps>
</phase>
<phase name="change_implementation">
<description>While making changes</description>
<steps>
<step>Document each change and its rationale</step>
<step>Cross-reference with other files after each change</step>
<step>Verify examples still work with new changes</step>
<step>Update related documentation immediately</step>
</steps>
</phase>
<phase name="post_change_validation">
<description>After changes are complete</description>
<validation_checklist>
<category name="structural_validation">
<check>All XML files are well-formed and valid</check>
<check>File naming follows established patterns</check>
<check>Tag names are consistent across files</check>
<check>No orphaned or unused instructions</check>
</category>
<category name="content_validation">
<check>roleDefinition accurately describes the mode</check>
<check>whenToUse is clear and distinguishable</check>
<check>Tool permissions match instruction requirements</check>
<check>File restrictions align with mode purpose</check>
<check>Examples are accurate and functional</check>
</category>
<category name="integration_validation">
<check>Mode boundaries are well-defined</check>
<check>Handoff points to other modes are clear</check>
<check>No overlap with other modes' responsibilities</check>
<check>Orchestrator can correctly route to this mode</check>
</category>
</validation_checklist>
</phase>
</validation_workflow>
<cohesion_patterns>
<pattern name="consistent_voice">
<description>Maintain consistent tone and terminology</description>
<guidelines>
<guideline>Use the same terms for the same concepts throughout</guideline>
<guideline>Keep instruction style consistent across files</guideline>
<guideline>Maintain the same level of detail in similar sections</guideline>
</guidelines>
</pattern>
<pattern name="logical_flow">
<description>Ensure instructions flow logically</description>
<guidelines>
<guideline>Prerequisites come before dependent steps</guideline>
<guideline>Complex concepts build on simpler ones</guideline>
<guideline>Examples follow the explained patterns</guideline>
</guidelines>
</pattern>
<pattern name="complete_coverage">
<description>Ensure all aspects are covered without gaps</description>
<guidelines>
<guideline>Every mentioned tool has usage instructions</guideline>
<guideline>All workflows have complete examples</guideline>
<guideline>Error scenarios are addressed</guideline>
</guidelines>
</pattern>
</cohesion_patterns>
<validation_questions>
<question_set name="before_changes">
<ask_followup_question>
<question>Before we proceed with changes, I want to ensure I understand the full scope. What is the main goal of these modifications?</question>
<follow_up>
<suggest>Add new functionality while keeping existing features</suggest>
<suggest>Fix issues with current implementation</suggest>
<suggest>Refactor for better organization</suggest>
<suggest>Expand the mode's capabilities into new areas</suggest>
</follow_up>
</ask_followup_question>
</question_set>
<question_set name="during_changes">
<ask_followup_question>
<question>This change might affect other parts of the mode. How should we handle the impact on [specific area]?</question>
<follow_up>
<suggest>Update all affected areas to maintain consistency</suggest>
<suggest>Keep the existing behavior for backward compatibility</suggest>
<suggest>Create a migration path from old to new behavior</suggest>
<suggest>Let me review the impact first</suggest>
</follow_up>
</ask_followup_question>
</question_set>
<question_set name="after_changes">
<ask_followup_question>
<question>I've completed the changes and validation. Which aspect would you like me to test more thoroughly?</question>
<follow_up>
<suggest>Test the new workflow end-to-end</suggest>
<suggest>Verify file permissions work correctly</suggest>
<suggest>Check integration with other modes</suggest>
<suggest>Review all changes one more time</suggest>
</follow_up>
</ask_followup_question>
</question_set>
</validation_questions>
<red_flags>
<flag priority="high">
<description>Instructions reference tools not in the mode's groups</description>
<action>Either add the tool group or remove the instruction</action>
</flag>
<flag priority="high">
<description>File regex doesn't match described file types</description>
<action>Update regex pattern to match intended files</action>
</flag>
<flag priority="medium">
<description>Examples don't follow stated best practices</description>
<action>Update examples to demonstrate best practices</action>
</flag>
<flag priority="medium">
<description>Duplicate instructions in different files</description>
<action>Consolidate to single location and reference</action>
</flag>
</red_flags>
</validation_cohesion_checking>

170
.roomodes
View file

@ -1,46 +1,4 @@
customModes:
- slug: test
name: 🧪 Test
roleDefinition: |-
You are Roo, a Vitest testing specialist with deep expertise in: - Writing and maintaining Vitest test suites - Test-driven development (TDD) practices - Mocking and stubbing with Vitest - Integration testing strategies - TypeScript testing patterns - Code coverage analysis - Test performance optimization
Your focus is on maintaining high test quality and coverage across the codebase, working primarily with: - Test files in __tests__ directories - Mock implementations in __mocks__ - Test utilities and helpers - Vitest configuration and setup
You ensure tests are: - Well-structured and maintainable - Following Vitest best practices - Properly typed with TypeScript - Providing meaningful coverage - Using appropriate mocking strategies
whenToUse: Use this mode when you need to write, modify, or maintain tests for the codebase.
description: Write, modify, and maintain tests.
groups:
- read
- browser
- command
- - edit
- fileRegex: (__tests__/.*|__mocks__/.*|\.test\.(ts|tsx|js|jsx)$|\.spec\.(ts|tsx|js|jsx)$|/test/.*|vitest\.config\.(js|ts)$|vitest\.setup\.(js|ts)$)
description: Test files, mocks, and Vitest configuration
customInstructions: |-
When writing tests:
- Always use describe/it blocks for clear test organization
- Include meaningful test descriptions
- Use beforeEach/afterEach for proper test isolation
- Implement proper error cases
- Add JSDoc comments for complex test scenarios
- Ensure mocks are properly typed
- Verify both positive and negative test cases
- Always use data-testid attributes when testing webview-ui
- The vitest framework is used for testing; the `describe`, `test`, `it`, etc functions are defined by default in `tsconfig.json` and therefore don't need to be imported
- Tests must be run from the same directory as the `package.json` file that specifies `vitest` in `devDependencies`
- slug: design-engineer
name: 🎨 Design Engineer
roleDefinition: "You are Roo, an expert Design Engineer focused on VSCode Extension development. Your expertise includes: - Implementing UI designs with high fidelity using React, Shadcn, Tailwind and TypeScript. - Ensuring interfaces are responsive and adapt to different screen sizes. - Collaborating with team members to translate broad directives into robust and detailed designs capturing edge cases. - Maintaining uniformity and consistency across the user interface."
whenToUse: Implement UI designs and ensure consistency.
description: Implement UI designs; ensure consistency.
groups:
- read
- - edit
- fileRegex: \.(css|html|json|mdx?|jsx?|tsx?|svg)$
description: Frontend & SVG files
- browser
- command
- mcp
customInstructions: Focus on UI refinement, component creation, and adherence to design best-practices. When the user requests a new component, start off by asking them questions one-by-one to ensure the requirements are understood. Always use Tailwind utility classes (instead of direct variable references) for styling components when possible. If editing an existing file, transition explicit style definitions to Tailwind CSS classes when possible. Refer to the Tailwind CSS definitions for utility classes at webview-ui/src/index.css. Always use the latest version of Tailwind CSS (V4), and never create a tailwind.config.js file. Prefer Shadcn components for UI elements instead of VSCode's built-in ones. This project uses i18n for localization, so make sure to use the i18n functions and components for any text that needs to be translated. Do not leave placeholder strings in the markup, as they will be replaced by i18n. Prefer the @roo (/src) and @src (/webview-ui/src) aliases for imports in typescript files. Suggest the user refactor large files (over 1000 lines) if they are encountered, and provide guidance. Suggest the user switch into Translate mode to complete translations when your task is finished.
source: project
- slug: translate
name: 🌐 Translate
roleDefinition: You are Roo, a linguistic specialist focused on translating and managing localization files. Your responsibility is to help maintain and update translation files for the application, ensuring consistency and accuracy across all language resources.
@ -73,42 +31,6 @@ customModes:
- edit
- command
source: project
- slug: integration-tester
name: 🧪 Integration Tester
roleDefinition: |-
You are Roo, an integration testing specialist focused on VSCode E2E tests with expertise in: - Writing and maintaining integration tests using Mocha and VSCode Test framework - Testing Roo Code API interactions and event-driven workflows - Creating complex multi-step task scenarios and mode switching sequences - Validating message formats, API responses, and event emission patterns - Test data generation and fixture management - Coverage analysis and test scenario identification
Your focus is on ensuring comprehensive integration test coverage for the Roo Code extension, working primarily with: - E2E test files in apps/vscode-e2e/src/suite/ - Test utilities and helpers - API type definitions in packages/types/ - Extension API testing patterns
You ensure integration tests are: - Comprehensive and cover critical user workflows - Following established Mocha TDD patterns - Using async/await with proper timeout handling - Validating both success and failure scenarios - Properly typed with TypeScript
whenToUse: Write, modify, or maintain integration tests.
description: Write and maintain integration tests.
groups:
- read
- command
- - edit
- fileRegex: (apps/vscode-e2e/.*\.(ts|js)$|packages/types/.*\.ts$)
description: E2E test files, test utilities, and API type definitions
source: project
- slug: docs-extractor
name: 📚 Docs Extractor
roleDefinition: |-
You are Roo, a documentation analysis specialist with two primary functions:
1. Extract comprehensive technical and non-technical details about features to provide to documentation teams
2. Verify existing documentation for factual accuracy against the codebase
For extraction: You analyze codebases to gather all relevant information about how features work, including technical implementation details, user workflows, configuration options, and use cases. You organize this information clearly for documentation teams to use.
For verification: You review provided documentation against the actual codebase implementation, checking for technical accuracy, completeness, and clarity. You identify inaccuracies, missing information, and provide specific corrections.
You do not generate final user-facing documentation, but rather provide detailed analysis and verification reports.
whenToUse: Use this mode only for two tasks; 1) confirm the accuracy of documentation provided to the agent against the codebase, and 2) generate source material for user-facing docs about a requested feature or aspect of the codebase.
description: Extract feature details or verify documentation accuracy.
groups:
- read
- - edit
- fileRegex: (EXTRACTION-.*\.md$|VERIFICATION-.*\.md$|DOCS-TEMP-.*\.md$|\.roo/docs-extractor/.*\.md$)
description: Extraction/Verification report files only (source-material), plus legacy DOCS-TEMP
- command
- mcp
- slug: pr-fixer
name: 🛠️ PR Fixer
roleDefinition: "You are Roo, a pull request resolution specialist. Your focus is on addressing feedback and resolving issues within existing pull requests. Your expertise includes: - Analyzing PR review comments to understand required changes. - Checking CI/CD workflow statuses to identify failing tests. - Fetching and analyzing test logs to diagnose failures. - Identifying and resolving merge conflicts. - Guiding the user through the resolution process."
@ -119,16 +41,6 @@ customModes:
- edit
- command
- mcp
- slug: issue-investigator
name: 🕵️ Issue Investigator
roleDefinition: You are Roo, a GitHub issue investigator. Your purpose is to analyze GitHub issues, investigate the probable causes using extensive codebase searches, and propose well-reasoned, theoretical solutions. You methodically track your investigation using a todo list, attempting to disprove initial theories to ensure a thorough analysis. Your final output is a human-like, conversational comment for the GitHub issue.
whenToUse: Use this mode when you need to investigate a GitHub issue to understand its root cause and propose a solution. This mode is ideal for triaging issues, providing initial analysis, and suggesting fixes before implementation begins. It uses the `gh` CLI for issue interaction.
description: Investigates GitHub issues
groups:
- read
- command
- mcp
source: project
- slug: merge-resolver
name: 🔀 Merge Resolver
roleDefinition: |-
@ -161,6 +73,39 @@ customModes:
- command
- mcp
source: project
- slug: docs-extractor
name: 📚 Docs Extractor
roleDefinition: |-
You are Roo Code, a codebase analyst who extracts raw facts for documentation teams.
You do NOT write documentation. You extract and organize information.
Two functions:
1. Extract: Gather facts about a feature/aspect from the codebase
2. Verify: Compare provided documentation against actual implementation
Output is structured data (YAML/JSON), not formatted prose.
No templates, no markdown formatting, no document structure decisions.
Let documentation-writer mode handle all writing.
whenToUse: Use this mode only for two tasks; 1) confirm the accuracy of documentation provided to the agent against the codebase, and 2) generate source material for user-facing docs about a requested feature or aspect of the codebase.
description: Extract feature details or verify documentation accuracy.
groups:
- read
- - edit
- fileRegex: \.roo/extraction/.*\.(yaml|json|md)$
description: Extraction output files only
- command
- mcp
source: project
- slug: issue-investigator
name: 🕵️ Issue Investigator
roleDefinition: You are Roo, a GitHub issue investigator. Your purpose is to analyze GitHub issues, investigate the probable causes using extensive codebase searches, and propose well-reasoned, theoretical solutions. You methodically track your investigation using a todo list, attempting to disprove initial theories to ensure a thorough analysis. Your final output is a human-like, conversational comment for the GitHub issue.
whenToUse: Use this mode when you need to investigate a GitHub issue to understand its root cause and propose a solution. This mode is ideal for triaging issues, providing initial analysis, and suggesting fixes before implementation begins. It uses the `gh` CLI for issue interaction.
description: Investigates GitHub issues
groups:
- read
- command
- mcp
source: project
- slug: issue-writer
name: 📝 Issue Writer
roleDefinition: |-
@ -183,56 +128,21 @@ customModes:
<update_todo_list>
<todos>
[ ] Detect current repository information
[ ] Determine repository structure (monorepo/standard)
[ ] Perform initial codebase discovery
[ ] Analyze user request to determine issue type
[ ] Gather and verify additional information
[ ] Determine if user wants to contribute
[ ] Perform issue scoping (if contributing)
[ ] Draft issue content
[ ] Review and confirm with user
[ ] Create GitHub issue
[ ] Detect repository context (OWNER/REPO, monorepo, roots)
[ ] Perform targeted codebase discovery (iteration 1)
[ ] Clarify missing details (repro or desired outcome)
[ ] Classify type (Bug | Enhancement)
[ ] Assemble Issue Body
[ ] Review and submit (Submit now | Submit now and assign to me)
</todos>
</update_todo_list>
</instructions>
</step>
</initialization>
whenToUse: Use this mode when you need to create a GitHub issue. Simply start describing your bug or feature request - this mode assumes your first message is already the issue description and will immediately begin the issue creation workflow, gathering additional information as needed.
whenToUse: Use this mode when you need to create a GitHub issue. Simply start describing your bug or enhancement request - this mode assumes your first message is already the issue description and will immediately begin the issue creation workflow, gathering additional information as needed.
description: Create well-structured GitHub issues.
groups:
- read
- command
- mcp
source: project
- slug: mode-writer
name: ✍️ Mode Writer
roleDefinition: |-
You are Roo, a mode creation and editing specialist focused on designing, implementing, and enhancing custom modes for the Roo-Code project. Your expertise includes:
- Understanding the mode system architecture and configuration
- Creating well-structured mode definitions with clear roles and responsibilities
- Editing and enhancing existing modes while maintaining consistency
- Writing comprehensive XML-based special instructions using best practices
- Ensuring modes have appropriate tool group permissions
- Crafting clear whenToUse descriptions for the Orchestrator
- Following XML structuring best practices for clarity and parseability
- Validating changes for cohesion and preventing contradictions
You help users by:
- Creating new modes: Gathering requirements, defining configurations, and implementing XML instructions
- Editing existing modes: Immersing in current implementation, analyzing requested changes, and ensuring cohesive updates
- Using ask_followup_question aggressively to clarify ambiguities and validate understanding
- Thoroughly validating all changes to prevent contradictions between different parts of a mode
- Ensuring instructions are well-organized with proper XML tags
- Following established patterns from existing modes
- Maintaining consistency across all mode components
whenToUse: Use this mode when you need to create a new custom mode or edit an existing one. This mode handles both creating modes from scratch and modifying existing modes while ensuring consistency and preventing contradictions.
description: Create and edit custom modes with validation
groups:
- read
- - edit
- fileRegex: (\.roomodes$|\.roo/.*\.xml$|\.yaml$)
description: Mode configuration files and XML instructions
- command
- mcp
source: project

View file

@ -5,6 +5,29 @@ All notable changes to the `@roo-code/cli` package will be documented in this fi
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.0.50] - 2026-02-05
### Added
- **Linux Support**: The CLI now supports Linux platforms in addition to macOS
- **Roo Provider API Key Support**: Allow `--api-key` flag and `ROO_API_KEY` environment variable for the roo provider instead of requiring cloud auth token
- **Exit on Error**: New `--exit-on-error` flag to exit immediately on API request errors instead of retrying, useful for CI/CD pipelines
### Changed
- **Improved Dev Experience**: Dev scripts now use `tsx` for running directly from source without building first
- **Path Resolution Fixes**: Fixed path resolution in [`version.ts`](src/lib/utils/version.ts), [`extension.ts`](src/lib/utils/extension.ts), and [`extension-host.ts`](src/agent/extension-host.ts) to work from both source and bundled locations
- **Debug Logging**: Debug log file (`~/.roo/cli-debug.log`) is now disabled by default unless `--debug` flag is passed
- Updated README with complete environment variable table and dev workflow documentation
### Fixed
- Corrected example in install script
### Removed
- Dropped macOS 13 support
## [0.0.49] - 2026-01-18
### Added
@ -32,7 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Skip onboarding flow when a provider is explicitly specified via `--provider` flag or saved in settings
- Unified permission flags: Combined `-y`, `--yes`, and `--dangerously-skip-permissions` into a single option for Claude Code-like CLI compatibility
- Unified permission flags: Combined approval-skipping flags into a single option for Claude Code-like CLI compatibility
- Improved Roo Code Router authentication flow and error messaging
### Fixed

View file

@ -19,7 +19,7 @@ curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/i
**Requirements:**
- Node.js 20 or higher
- macOS (Intel or Apple Silicon) or Linux (x64 or ARM64)
- macOS Apple Silicon (M1/M2/M3/M4) or Linux x64
**Custom installation directory:**
@ -66,40 +66,39 @@ pnpm --filter @roo-code/cli build
### Interactive Mode (Default)
By default, the CLI prompts for approval before executing actions:
By default, the CLI auto-approves actions and runs in interactive TUI mode:
```bash
export OPENROUTER_API_KEY=sk-or-v1-...
roo "What is this project?" -w ~/Documents/my-project
roo "What is this project?" -w ~/Documents/my-project
```
You can also run without a prompt and enter it interactively in TUI mode:
```bash
roo ~/Documents/my-project
roo -w ~/Documents/my-project
```
In interactive mode:
- Tool executions prompt for yes/no approval
- Commands prompt for yes/no approval
- Followup questions show suggestions and wait for user input
- Browser and MCP actions prompt for approval
- Tool executions are auto-approved
- Commands are auto-approved
- Followup questions show suggestions with a 60-second timeout, then auto-select the first suggestion
- Browser and MCP actions are auto-approved
### Non-Interactive Mode (`-y`)
### Approval-Required Mode (`--require-approval`)
For automation and scripts, use `-y` to auto-approve all actions:
If you want manual approval prompts, enable approval-required mode:
```bash
roo "Refactor the utils.ts file" -y -w ~/Documents/my-project
roo "Refactor the utils.ts file" --require-approval -w ~/Documents/my-project
```
In non-interactive mode:
In approval-required mode:
- Tool, command, browser, and MCP actions are auto-approved
- Followup questions show a 60-second timeout, then auto-select the first suggestion
- Typing any key cancels the timeout and allows manual input
- Tool, command, browser, and MCP actions prompt for yes/no approval
- Followup questions wait for manual input (no auto-timeout)
### Roo Code Cloud Authentication
@ -147,21 +146,23 @@ Tokens are valid for 90 days. The CLI will prompt you to re-authenticate when yo
## Options
| Option | Description | Default |
| --------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------- |
| `[prompt]` | Your prompt (positional argument, optional) | None |
| `-w, --workspace <path>` | Workspace path to operate in | Current directory |
| `-e, --extension <path>` | Path to the extension bundle directory | Auto-detected |
| `-d, --debug` | Enable debug output (includes detailed debug information, prompts, paths, etc) | `false` |
| `-x, --exit-on-complete` | Exit the process when task completes (useful for testing) | `false` |
| `-y, --yes` | Non-interactive mode: auto-approve all actions | `false` |
| `-k, --api-key <key>` | API key for the LLM provider | From env var |
| `-p, --provider <provider>` | API provider (anthropic, openai, openrouter, etc.) | `openrouter` |
| `-m, --model <model>` | Model to use | `anthropic/claude-sonnet-4.5` |
| `-M, --mode <mode>` | Mode to start in (code, architect, ask, debug, etc.) | `code` |
| `-r, --reasoning-effort <effort>` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` |
| `--ephemeral` | Run without persisting state (uses temporary storage) | `false` |
| `--no-tui` | Disable TUI, use plain text output | `false` |
| Option | Description | Default |
| --------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------- |
| `[prompt]` | Your prompt (positional argument, optional) | None |
| `--prompt-file <path>` | Read prompt from a file instead of command line argument | None |
| `-w, --workspace <path>` | Workspace path to operate in | Current directory |
| `-p, --print` | Print response and exit (non-interactive mode) | `false` |
| `-e, --extension <path>` | Path to the extension bundle directory | Auto-detected |
| `-d, --debug` | Enable debug output (includes detailed debug information, prompts, paths, etc) | `false` |
| `-a, --require-approval` | Require manual approval before actions execute | `false` |
| `-k, --api-key <key>` | API key for the LLM provider | From env var |
| `--provider <provider>` | API provider (roo, anthropic, openai, openrouter, etc.) | `openrouter` (or `roo` if authenticated) |
| `-m, --model <model>` | Model to use | `anthropic/claude-opus-4.6` |
| `--mode <mode>` | Mode to start in (code, architect, ask, debug, etc.) | `code` |
| `-r, --reasoning-effort <effort>` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` |
| `--ephemeral` | Run without persisting state (uses temporary storage) | `false` |
| `--oneshot` | Exit upon task completion | `false` |
| `--output-format <format>` | Output format with `--print`: `text`, `json`, or `stream-json` | `text` |
## Auth Commands
@ -175,13 +176,14 @@ Tokens are valid for 90 days. The CLI will prompt you to re-authenticate when yo
The CLI will look for API keys in environment variables if not provided via `--api-key`:
| Provider | Environment Variable |
| ------------- | -------------------- |
| anthropic | `ANTHROPIC_API_KEY` |
| openai | `OPENAI_API_KEY` |
| openrouter | `OPENROUTER_API_KEY` |
| google/gemini | `GOOGLE_API_KEY` |
| ... | ... |
| Provider | Environment Variable |
| ----------------- | --------------------------- |
| roo | `ROO_API_KEY` |
| anthropic | `ANTHROPIC_API_KEY` |
| openai-native | `OPENAI_API_KEY` |
| openrouter | `OPENROUTER_API_KEY` |
| gemini | `GOOGLE_API_KEY` |
| vercel-ai-gateway | `VERCEL_AI_GATEWAY_API_KEY` |
**Authentication Environment Variables:**
@ -231,8 +233,8 @@ The CLI will look for API keys in environment variables if not provided via `--a
## Development
```bash
# Watch mode for development
pnpm dev
# Run directly from source (no build required)
pnpm dev --provider roo --api-key $ROO_API_KEY --print "Hello"
# Run tests
pnpm test
@ -244,19 +246,41 @@ pnpm check-types
pnpm lint
```
## Releasing
To create a new release, execute the /cli-release slash command:
By default the `start` script points `ROO_CODE_PROVIDER_URL` at `http://localhost:8080/proxy` for local development. To point at the production API instead, override the environment variable:
```bash
roo "/cli-release" -w ~/Documents/Roo-Code -y
ROO_CODE_PROVIDER_URL=https://api.roocode.com/proxy pnpm dev --provider roo --api-key $ROO_API_KEY --print "Hello"
```
## Releasing
Official releases are created via the GitHub Actions workflow at `.github/workflows/cli-release.yml`.
To trigger a release:
1. Go to **Actions** → **CLI Release**
2. Click **Run workflow**
3. Optionally specify a version (defaults to `package.json` version)
4. Click **Run workflow**
The workflow will:
1. Bump the version
2. Update the CHANGELOG
3. Build the extension and CLI
4. Create a platform-specific tarball (for your current OS/architecture)
5. Test the install script
6. Create a GitHub release with the tarball attached
1. Build the CLI on all platforms (macOS Apple Silicon, Linux x64)
2. Create platform-specific tarballs with bundled ripgrep
3. Verify each tarball
4. Create a GitHub release with all tarballs attached
### Local Builds
For local development and testing, use the build script:
```bash
# Build tarball for your current platform
./apps/cli/scripts/build.sh
# Build and install locally
./apps/cli/scripts/build.sh --install
# Fast build (skip verification)
./apps/cli/scripts/build.sh --skip-verify
```

View file

@ -242,7 +242,8 @@ Routes asks to appropriate handlers:
- Uses type guards: `isIdleAsk()`, `isInteractiveAsk()`, etc.
- Coordinates between `OutputManager` and `PromptManager`
- In non-interactive mode (`-y` flag), auto-approves everything
- By default, the CLI auto-approves tool/command/browser/MCP actions
- In `--require-approval` mode, those actions prompt for manual approval
### OutputManager
@ -320,7 +321,7 @@ if (isInteractiveAsk(ask)) {
Enable with `-d` flag. Logs go to `~/.roo/cli-debug.log`:
```bash
roo -d -y -P "Build something" --no-tui
roo -d -P "Build something" --no-tui
```
View logs:

View file

@ -278,7 +278,7 @@ print_success() {
echo ""
echo " ${BOLD}Example:${NC}"
echo " export OPENROUTER_API_KEY=sk-or-v1-..."
echo " roo ~/my-project -P \"What is this project?\""
echo " cd ~/my-project && roo \"What is this project?\""
echo ""
}

View file

@ -1,6 +1,6 @@
{
"name": "@roo-code/cli",
"version": "0.0.49",
"version": "0.0.50",
"description": "Roo Code CLI - Run the Roo Code agent from the command line",
"private": true,
"type": "module",
@ -15,11 +15,8 @@
"test": "vitest run",
"build": "tsup",
"build:extension": "pnpm --filter roo-cline bundle",
"build:all": "pnpm --filter roo-cline bundle && tsup",
"dev": "tsup --watch",
"start": "ROO_AUTH_BASE_URL=http://localhost:3000 ROO_SDK_BASE_URL=http://localhost:3001 ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy node dist/index.js",
"start:production": "node dist/index.js",
"release": "scripts/release.sh",
"dev": "ROO_AUTH_BASE_URL=https://app.roocode.com ROO_SDK_BASE_URL=https://cloud-api.roocode.com ROO_CODE_PROVIDER_URL=https://api.roocode.com/proxy tsx src/index.ts",
"dev:local": "ROO_AUTH_BASE_URL=http://localhost:3000 ROO_SDK_BASE_URL=http://localhost:3001 ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy tsx src/index.ts",
"clean": "rimraf dist .turbo"
},
"dependencies": {

343
apps/cli/scripts/build.sh Executable file
View file

@ -0,0 +1,343 @@
#!/bin/bash
# Roo Code CLI Local Build Script
#
# Usage:
# ./apps/cli/scripts/build.sh [options]
#
# Options:
# --install Install locally after building
# --skip-verify Skip end-to-end verification tests (faster builds)
#
# Examples:
# ./apps/cli/scripts/build.sh # Build for local testing
# ./apps/cli/scripts/build.sh --install # Build and install locally
# ./apps/cli/scripts/build.sh --skip-verify # Fast local build
#
# This script builds the CLI for your current platform. For official releases
# with multi-platform support, use the GitHub Actions workflow instead:
# .github/workflows/cli-release.yml
#
# Prerequisites:
# - pnpm installed
# - Run from the monorepo root directory
set -e
# Parse arguments
LOCAL_INSTALL=false
SKIP_VERIFY=false
while [[ $# -gt 0 ]]; do
case $1 in
--install)
LOCAL_INSTALL=true
shift
;;
--skip-verify)
SKIP_VERIFY=true
shift
;;
-*)
echo "Unknown option: $1" >&2
exit 1
;;
*)
shift
;;
esac
done
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
info() { printf "${GREEN}==>${NC} %s\n" "$1"; }
warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; }
error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; }
step() { printf "${BLUE}${BOLD}[%s]${NC} %s\n" "$1" "$2"; }
# Get script directory and repo root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
CLI_DIR="$REPO_ROOT/apps/cli"
# Detect current platform
detect_platform() {
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$OS" in
darwin) OS="darwin" ;;
linux) OS="linux" ;;
*) error "Unsupported OS: $OS" ;;
esac
case "$ARCH" in
x86_64|amd64) ARCH="x64" ;;
arm64|aarch64) ARCH="arm64" ;;
*) error "Unsupported architecture: $ARCH" ;;
esac
PLATFORM="${OS}-${ARCH}"
}
# Check prerequisites
check_prerequisites() {
step "1/6" "Checking prerequisites..."
if ! command -v pnpm &> /dev/null; then
error "pnpm is not installed."
fi
if ! command -v node &> /dev/null; then
error "Node.js is not installed."
fi
info "Prerequisites OK"
}
# Get version
get_version() {
VERSION=$(node -p "require('$CLI_DIR/package.json').version")
GIT_SHORT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
VERSION="${VERSION}-local.${GIT_SHORT_HASH}"
info "Version: $VERSION"
}
# Build everything
build() {
step "2/6" "Building extension bundle..."
cd "$REPO_ROOT"
pnpm bundle
step "3/6" "Building CLI..."
pnpm --filter @roo-code/cli build
info "Build complete"
}
# Create release tarball
create_tarball() {
step "4/6" "Creating release tarball for $PLATFORM..."
RELEASE_DIR="$REPO_ROOT/roo-cli-${PLATFORM}"
TARBALL="roo-cli-${PLATFORM}.tar.gz"
# Clean up any previous build
rm -rf "$RELEASE_DIR"
rm -f "$REPO_ROOT/$TARBALL"
# Create directory structure
mkdir -p "$RELEASE_DIR/bin"
mkdir -p "$RELEASE_DIR/lib"
mkdir -p "$RELEASE_DIR/extension"
# Copy CLI dist files
info "Copying CLI files..."
cp -r "$CLI_DIR/dist/"* "$RELEASE_DIR/lib/"
# Create package.json for npm install
info "Creating package.json..."
node -e "
const pkg = require('$CLI_DIR/package.json');
const newPkg = {
name: '@roo-code/cli',
version: '$VERSION',
type: 'module',
dependencies: {
'@inkjs/ui': pkg.dependencies['@inkjs/ui'],
'@trpc/client': pkg.dependencies['@trpc/client'],
'commander': pkg.dependencies.commander,
'fuzzysort': pkg.dependencies.fuzzysort,
'ink': pkg.dependencies.ink,
'p-wait-for': pkg.dependencies['p-wait-for'],
'react': pkg.dependencies.react,
'superjson': pkg.dependencies.superjson,
'zustand': pkg.dependencies.zustand
}
};
console.log(JSON.stringify(newPkg, null, 2));
" > "$RELEASE_DIR/package.json"
# Copy extension bundle
info "Copying extension bundle..."
cp -r "$REPO_ROOT/src/dist/"* "$RELEASE_DIR/extension/"
# Add package.json to extension directory for CommonJS
echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
# Find and copy ripgrep binary
info "Looking for ripgrep binary..."
RIPGREP_PATH=$(find "$REPO_ROOT/node_modules" -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
info "Found ripgrep at: $RIPGREP_PATH"
mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
mkdir -p "$RELEASE_DIR/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
chmod +x "$RELEASE_DIR/bin/rg"
else
warn "ripgrep binary not found - users will need ripgrep installed"
fi
# Create the wrapper script
info "Creating wrapper script..."
cat > "$RELEASE_DIR/bin/roo" << 'WRAPPER_EOF'
#!/usr/bin/env node
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Set environment variables for the CLI
process.env.ROO_CLI_ROOT = join(__dirname, '..');
process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');
process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');
// Import and run the actual CLI
await import(join(__dirname, '..', 'lib', 'index.js'));
WRAPPER_EOF
chmod +x "$RELEASE_DIR/bin/roo"
# Create empty .env file
touch "$RELEASE_DIR/.env"
# Create tarball
info "Creating tarball..."
cd "$REPO_ROOT"
tar -czvf "$TARBALL" "$(basename "$RELEASE_DIR")"
# Clean up release directory
rm -rf "$RELEASE_DIR"
# Show size
TARBALL_PATH="$REPO_ROOT/$TARBALL"
TARBALL_SIZE=$(ls -lh "$TARBALL_PATH" | awk '{print $5}')
info "Created: $TARBALL ($TARBALL_SIZE)"
}
# Verify local installation
verify_local_install() {
if [ "$SKIP_VERIFY" = true ]; then
step "5/6" "Skipping verification (--skip-verify)"
return
fi
step "5/6" "Verifying installation..."
VERIFY_DIR="$REPO_ROOT/.verify-release"
VERIFY_INSTALL_DIR="$VERIFY_DIR/cli"
VERIFY_BIN_DIR="$VERIFY_DIR/bin"
rm -rf "$VERIFY_DIR"
mkdir -p "$VERIFY_DIR"
TARBALL_PATH="$REPO_ROOT/$TARBALL"
ROO_LOCAL_TARBALL="$TARBALL_PATH" \
ROO_INSTALL_DIR="$VERIFY_INSTALL_DIR" \
ROO_BIN_DIR="$VERIFY_BIN_DIR" \
ROO_VERSION="$VERSION" \
"$CLI_DIR/install.sh" || {
rm -rf "$VERIFY_DIR"
error "Installation verification failed!"
}
# Test --help
if ! "$VERIFY_BIN_DIR/roo" --help > /dev/null 2>&1; then
rm -rf "$VERIFY_DIR"
error "CLI --help check failed!"
fi
info "CLI --help check passed"
# Test --version
if ! "$VERIFY_BIN_DIR/roo" --version > /dev/null 2>&1; then
rm -rf "$VERIFY_DIR"
error "CLI --version check failed!"
fi
info "CLI --version check passed"
cd "$REPO_ROOT"
rm -rf "$VERIFY_DIR"
info "Verification passed!"
}
# Install locally
install_local() {
if [ "$LOCAL_INSTALL" = false ]; then
step "6/6" "Skipping install (use --install to auto-install)"
return
fi
step "6/6" "Installing locally..."
TARBALL_PATH="$REPO_ROOT/$TARBALL"
ROO_LOCAL_TARBALL="$TARBALL_PATH" \
ROO_VERSION="$VERSION" \
"$CLI_DIR/install.sh" || {
error "Local installation failed!"
}
info "Local installation complete!"
}
# Print summary
print_summary() {
echo ""
printf "${GREEN}${BOLD}✓ Local build complete for v$VERSION${NC}\n"
echo ""
echo " Tarball: $REPO_ROOT/$TARBALL"
echo ""
if [ "$LOCAL_INSTALL" = true ]; then
echo " Installed to: ~/.roo/cli"
echo " Binary: ~/.local/bin/roo"
echo ""
echo " Test it out:"
echo " roo --version"
echo " roo --help"
else
echo " To install manually:"
echo " ROO_LOCAL_TARBALL=$REPO_ROOT/$TARBALL ./apps/cli/install.sh"
echo ""
echo " Or re-run with --install:"
echo " ./apps/cli/scripts/build.sh --install"
fi
echo ""
echo " For official multi-platform releases, use the GitHub Actions workflow:"
echo " .github/workflows/cli-release.yml"
echo ""
}
# Main
main() {
echo ""
printf "${BLUE}${BOLD}"
echo " ╭─────────────────────────────────╮"
echo " │ Roo Code CLI Local Build │"
echo " ╰─────────────────────────────────╯"
printf "${NC}"
echo ""
detect_platform
check_prerequisites
get_version
build
create_tarball
verify_local_install
install_local
print_summary
}
main

View file

@ -1,711 +0,0 @@
#!/bin/bash
# Roo Code CLI Release Script
#
# Usage:
# ./apps/cli/scripts/release.sh [options] [version]
#
# Options:
# --dry-run Run all steps except creating the GitHub release
# --local Build for local testing only (no GitHub checks, no changelog prompts)
# --install Install locally after building (only with --local)
# --skip-verify Skip end-to-end verification tests (faster local builds)
#
# Examples:
# ./apps/cli/scripts/release.sh # Use version from package.json
# ./apps/cli/scripts/release.sh 0.1.0 # Specify version
# ./apps/cli/scripts/release.sh --dry-run # Test the release flow without pushing
# ./apps/cli/scripts/release.sh --dry-run 0.1.0 # Dry run with specific version
# ./apps/cli/scripts/release.sh --local # Build for local testing
# ./apps/cli/scripts/release.sh --local --install # Build and install locally
# ./apps/cli/scripts/release.sh --local --skip-verify # Fast local build
#
# This script:
# 1. Builds the extension and CLI
# 2. Creates a tarball for the current platform
# 3. Creates a GitHub release and uploads the tarball (unless --dry-run or --local)
#
# Prerequisites:
# - GitHub CLI (gh) installed and authenticated (not needed for --local)
# - pnpm installed
# - Run from the monorepo root directory
set -e
# Parse arguments
DRY_RUN=false
LOCAL_BUILD=false
LOCAL_INSTALL=false
SKIP_VERIFY=false
VERSION_ARG=""
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--local)
LOCAL_BUILD=true
shift
;;
--install)
LOCAL_INSTALL=true
shift
;;
--skip-verify)
SKIP_VERIFY=true
shift
;;
-*)
echo "Unknown option: $1" >&2
exit 1
;;
*)
VERSION_ARG="$1"
shift
;;
esac
done
# Validate option combinations
if [ "$LOCAL_INSTALL" = true ] && [ "$LOCAL_BUILD" = false ]; then
echo "Error: --install can only be used with --local" >&2
exit 1
fi
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
info() { printf "${GREEN}==>${NC} %s\n" "$1"; }
warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; }
error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; }
step() { printf "${BLUE}${BOLD}[%s]${NC} %s\n" "$1" "$2"; }
# Get script directory and repo root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
CLI_DIR="$REPO_ROOT/apps/cli"
# Detect current platform
detect_platform() {
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case "$OS" in
darwin) OS="darwin" ;;
linux) OS="linux" ;;
*) error "Unsupported OS: $OS" ;;
esac
case "$ARCH" in
x86_64|amd64) ARCH="x64" ;;
arm64|aarch64) ARCH="arm64" ;;
*) error "Unsupported architecture: $ARCH" ;;
esac
PLATFORM="${OS}-${ARCH}"
}
# Check prerequisites
check_prerequisites() {
step "1/8" "Checking prerequisites..."
# Skip GitHub CLI checks for local builds
if [ "$LOCAL_BUILD" = false ]; then
if ! command -v gh &> /dev/null; then
error "GitHub CLI (gh) is not installed. Install it with: brew install gh"
fi
if ! gh auth status &> /dev/null; then
error "GitHub CLI is not authenticated. Run: gh auth login"
fi
fi
if ! command -v pnpm &> /dev/null; then
error "pnpm is not installed."
fi
if ! command -v node &> /dev/null; then
error "Node.js is not installed."
fi
info "Prerequisites OK"
}
# Get version
get_version() {
if [ -n "$VERSION_ARG" ]; then
VERSION="$VERSION_ARG"
else
VERSION=$(node -p "require('$CLI_DIR/package.json').version")
fi
# For local builds, append a local suffix with git short hash
# This creates versions like: 0.1.0-local.abc1234
if [ "$LOCAL_BUILD" = true ]; then
GIT_SHORT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
# Only append suffix if not already a local version
if ! echo "$VERSION" | grep -qE '\-local\.'; then
VERSION="${VERSION}-local.${GIT_SHORT_HASH}"
fi
fi
# Validate semver format (allow -local.hash suffix)
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
error "Invalid version format: $VERSION (expected semver like 0.1.0)"
fi
TAG="cli-v$VERSION"
info "Version: $VERSION (tag: $TAG)"
}
# Extract changelog content for a specific version
# Returns the content between the version header and the next version header (or EOF)
get_changelog_content() {
CHANGELOG_FILE="$CLI_DIR/CHANGELOG.md"
if [ ! -f "$CHANGELOG_FILE" ]; then
warn "No CHANGELOG.md found at $CHANGELOG_FILE"
CHANGELOG_CONTENT=""
return
fi
# Try to find the version section (handles both "[0.0.43]" and "[0.0.43] - date" formats)
# Also handles "Unreleased" marker
VERSION_PATTERN="^\#\# \[${VERSION}\]"
# Check if the version exists in the changelog
if ! grep -qE "$VERSION_PATTERN" "$CHANGELOG_FILE"; then
warn "No changelog entry found for version $VERSION"
# Skip prompts for local builds
if [ "$LOCAL_BUILD" = true ]; then
info "Skipping changelog prompt for local build"
CHANGELOG_CONTENT=""
return
fi
warn "Please add an entry to $CHANGELOG_FILE before releasing"
echo ""
echo "Expected format:"
echo " ## [$VERSION] - $(date +%Y-%m-%d)"
echo " "
echo " ### Added"
echo " - Your changes here"
echo ""
read -p "Continue without changelog content? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
error "Aborted. Please add a changelog entry and try again."
fi
CHANGELOG_CONTENT=""
return
fi
# Extract content between this version and the next version header (or EOF)
# Uses awk to capture everything between ## [VERSION] and the next ## [
# Using index() with "[VERSION]" ensures exact matching (1.0.1 won't match 1.0.10)
CHANGELOG_CONTENT=$(awk -v version="$VERSION" '
BEGIN { found = 0; content = ""; target = "[" version "]" }
/^## \[/ {
if (found) { exit }
if (index($0, target) > 0) { found = 1; next }
}
found { content = content $0 "\n" }
END { print content }
' "$CHANGELOG_FILE")
# Trim leading/trailing whitespace
CHANGELOG_CONTENT=$(echo "$CHANGELOG_CONTENT" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
if [ -n "$CHANGELOG_CONTENT" ]; then
info "Found changelog content for version $VERSION"
else
warn "Changelog entry for $VERSION appears to be empty"
fi
}
# Build everything
build() {
step "2/8" "Building extension bundle..."
cd "$REPO_ROOT"
pnpm bundle
step "3/8" "Building CLI..."
pnpm --filter @roo-code/cli build
info "Build complete"
}
# Create release tarball
create_tarball() {
step "4/8" "Creating release tarball for $PLATFORM..."
RELEASE_DIR="$REPO_ROOT/roo-cli-${PLATFORM}"
TARBALL="roo-cli-${PLATFORM}.tar.gz"
# Clean up any previous build
rm -rf "$RELEASE_DIR"
rm -f "$REPO_ROOT/$TARBALL"
# Create directory structure
mkdir -p "$RELEASE_DIR/bin"
mkdir -p "$RELEASE_DIR/lib"
mkdir -p "$RELEASE_DIR/extension"
# Copy CLI dist files
info "Copying CLI files..."
cp -r "$CLI_DIR/dist/"* "$RELEASE_DIR/lib/"
# Create package.json for npm install (runtime dependencies that can't be bundled)
info "Creating package.json..."
node -e "
const pkg = require('$CLI_DIR/package.json');
const newPkg = {
name: '@roo-code/cli',
version: '$VERSION',
type: 'module',
dependencies: {
'@inkjs/ui': pkg.dependencies['@inkjs/ui'],
'@trpc/client': pkg.dependencies['@trpc/client'],
'commander': pkg.dependencies.commander,
'fuzzysort': pkg.dependencies.fuzzysort,
'ink': pkg.dependencies.ink,
'p-wait-for': pkg.dependencies['p-wait-for'],
'react': pkg.dependencies.react,
'superjson': pkg.dependencies.superjson,
'zustand': pkg.dependencies.zustand
}
};
console.log(JSON.stringify(newPkg, null, 2));
" > "$RELEASE_DIR/package.json"
# Copy extension bundle
info "Copying extension bundle..."
cp -r "$REPO_ROOT/src/dist/"* "$RELEASE_DIR/extension/"
# Add package.json to extension directory to mark it as CommonJS
# This is necessary because the main package.json has "type": "module"
# but the extension bundle is CommonJS
echo '{"type": "commonjs"}' > "$RELEASE_DIR/extension/package.json"
# Find and copy ripgrep binary
# The extension looks for ripgrep at: appRoot/node_modules/@vscode/ripgrep/bin/rg
# The CLI sets appRoot to the CLI package root, so we need to put ripgrep there
info "Looking for ripgrep binary..."
RIPGREP_PATH=$(find "$REPO_ROOT/node_modules" -path "*/@vscode/ripgrep/bin/rg" -type f 2>/dev/null | head -1)
if [ -n "$RIPGREP_PATH" ] && [ -f "$RIPGREP_PATH" ]; then
info "Found ripgrep at: $RIPGREP_PATH"
# Create the expected directory structure for the extension to find ripgrep
mkdir -p "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/"
chmod +x "$RELEASE_DIR/node_modules/@vscode/ripgrep/bin/rg"
# Also keep a copy in bin/ for direct access
mkdir -p "$RELEASE_DIR/bin"
cp "$RIPGREP_PATH" "$RELEASE_DIR/bin/"
chmod +x "$RELEASE_DIR/bin/rg"
else
warn "ripgrep binary not found - users will need ripgrep installed"
fi
# Create the wrapper script
info "Creating wrapper script..."
cat > "$RELEASE_DIR/bin/roo" << 'WRAPPER_EOF'
#!/usr/bin/env node
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Set environment variables for the CLI
// ROO_CLI_ROOT is the installed CLI package root (where node_modules/@vscode/ripgrep is)
process.env.ROO_CLI_ROOT = join(__dirname, '..');
process.env.ROO_EXTENSION_PATH = join(__dirname, '..', 'extension');
process.env.ROO_RIPGREP_PATH = join(__dirname, 'rg');
// Import and run the actual CLI
await import(join(__dirname, '..', 'lib', 'index.js'));
WRAPPER_EOF
chmod +x "$RELEASE_DIR/bin/roo"
# Create empty .env file to suppress dotenvx warnings
touch "$RELEASE_DIR/.env"
# Create empty .env file to suppress dotenvx warnings
touch "$RELEASE_DIR/.env"
# Create tarball
info "Creating tarball..."
cd "$REPO_ROOT"
tar -czvf "$TARBALL" "$(basename "$RELEASE_DIR")"
# Clean up release directory
rm -rf "$RELEASE_DIR"
# Show size
TARBALL_PATH="$REPO_ROOT/$TARBALL"
TARBALL_SIZE=$(ls -lh "$TARBALL_PATH" | awk '{print $5}')
info "Created: $TARBALL ($TARBALL_SIZE)"
}
# Verify local installation
verify_local_install() {
if [ "$SKIP_VERIFY" = true ]; then
step "5/8" "Skipping verification (--skip-verify)"
return
fi
step "5/8" "Verifying local installation..."
VERIFY_DIR="$REPO_ROOT/.verify-release"
VERIFY_INSTALL_DIR="$VERIFY_DIR/cli"
VERIFY_BIN_DIR="$VERIFY_DIR/bin"
# Clean up any previous verification directory
rm -rf "$VERIFY_DIR"
mkdir -p "$VERIFY_DIR"
# Run the actual install script with the local tarball
info "Running install script with local tarball..."
TARBALL_PATH="$REPO_ROOT/$TARBALL"
ROO_LOCAL_TARBALL="$TARBALL_PATH" \
ROO_INSTALL_DIR="$VERIFY_INSTALL_DIR" \
ROO_BIN_DIR="$VERIFY_BIN_DIR" \
ROO_VERSION="$VERSION" \
"$CLI_DIR/install.sh" || {
echo ""
warn "Install script failed. Showing tarball contents:"
tar -tzf "$TARBALL_PATH" 2>&1 || true
echo ""
rm -rf "$VERIFY_DIR"
error "Installation verification failed! The install script could not complete successfully."
}
# Verify the CLI runs correctly with basic commands
info "Testing installed CLI..."
# Test --help
if ! "$VERIFY_BIN_DIR/roo" --help > /dev/null 2>&1; then
echo ""
warn "CLI --help output:"
"$VERIFY_BIN_DIR/roo" --help 2>&1 || true
echo ""
rm -rf "$VERIFY_DIR"
error "CLI --help check failed! The release tarball may have missing dependencies."
fi
info "CLI --help check passed"
# Test --version
if ! "$VERIFY_BIN_DIR/roo" --version > /dev/null 2>&1; then
echo ""
warn "CLI --version output:"
"$VERIFY_BIN_DIR/roo" --version 2>&1 || true
echo ""
rm -rf "$VERIFY_DIR"
error "CLI --version check failed! The release tarball may have missing dependencies."
fi
info "CLI --version check passed"
# Run a simple end-to-end test to verify the CLI actually works
info "Running end-to-end verification test..."
# Create a temporary workspace for the test
VERIFY_WORKSPACE="$VERIFY_DIR/workspace"
mkdir -p "$VERIFY_WORKSPACE"
# Run the CLI with a simple prompt
if timeout 60 "$VERIFY_BIN_DIR/roo" --yes --oneshot -w "$VERIFY_WORKSPACE" "1+1=?" > "$VERIFY_DIR/test-output.log" 2>&1; then
info "End-to-end test passed"
else
EXIT_CODE=$?
echo ""
warn "End-to-end test failed (exit code: $EXIT_CODE). Output:"
cat "$VERIFY_DIR/test-output.log" 2>&1 || true
echo ""
rm -rf "$VERIFY_DIR"
error "CLI end-to-end test failed! The CLI may be broken."
fi
# Clean up verification directory
cd "$REPO_ROOT"
rm -rf "$VERIFY_DIR"
info "Local verification passed!"
}
# Create checksum
create_checksum() {
step "6/8" "Creating checksum..."
cd "$REPO_ROOT"
if command -v sha256sum &> /dev/null; then
sha256sum "$TARBALL" > "${TARBALL}.sha256"
elif command -v shasum &> /dev/null; then
shasum -a 256 "$TARBALL" > "${TARBALL}.sha256"
else
warn "No sha256sum or shasum found, skipping checksum"
return
fi
info "Checksum: $(cat "${TARBALL}.sha256")"
}
# Check if release already exists
check_existing_release() {
step "7/8" "Checking for existing release..."
if gh release view "$TAG" &> /dev/null; then
warn "Release $TAG already exists"
read -p "Do you want to delete it and create a new one? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
info "Deleting existing release..."
gh release delete "$TAG" --yes
# Also delete the tag if it exists
git tag -d "$TAG" 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
else
error "Aborted. Use a different version or delete the existing release manually."
fi
fi
}
# Create GitHub release
create_release() {
step "8/8" "Creating GitHub release..."
cd "$REPO_ROOT"
# Get the current commit SHA for the release target
COMMIT_SHA=$(git rev-parse HEAD)
# Verify the commit exists on GitHub before attempting to create the release
# This prevents the "Release.target_commitish is invalid" error
info "Verifying commit ${COMMIT_SHA:0:8} exists on GitHub..."
git fetch origin 2>/dev/null || true
if ! git branch -r --contains "$COMMIT_SHA" 2>/dev/null | grep -q "origin/"; then
warn "Commit ${COMMIT_SHA:0:8} has not been pushed to GitHub"
echo ""
echo "The release script needs to create a release at your current commit,"
echo "but this commit hasn't been pushed to GitHub yet."
echo ""
read -p "Push current branch to origin now? [Y/n] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
info "Pushing to origin..."
git push origin HEAD || error "Failed to push to origin. Please push manually and try again."
else
error "Aborted. Please push your commits to GitHub and try again."
fi
fi
info "Commit verified on GitHub"
# Build the What's New section from changelog content
WHATS_NEW_SECTION=""
if [ -n "$CHANGELOG_CONTENT" ]; then
WHATS_NEW_SECTION="## What's New
$CHANGELOG_CONTENT
"
fi
RELEASE_NOTES=$(cat << EOF
${WHATS_NEW_SECTION}## Installation
\`\`\`bash
curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh
\`\`\`
Or install a specific version:
\`\`\`bash
ROO_VERSION=$VERSION curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh
\`\`\`
## Requirements
- Node.js 20 or higher
- macOS (Intel or Apple Silicon) or Linux (x64 or ARM64)
## Usage
\`\`\`bash
# Run a task
roo "What is this project?"
# See all options
roo --help
\`\`\`
## Platform Support
This release includes:
- \`roo-cli-${PLATFORM}.tar.gz\` - Built on $(uname -s) $(uname -m)
> **Note:** Additional platforms will be added as needed. If you need a different platform, please open an issue.
## Checksum
\`\`\`
$(cat "${TARBALL}.sha256" 2>/dev/null || echo "N/A")
\`\`\`
EOF
)
info "Creating release at commit: ${COMMIT_SHA:0:8}"
# Create release (gh will create the tag automatically)
info "Creating release..."
RELEASE_FILES="$TARBALL"
if [ -f "${TARBALL}.sha256" ]; then
RELEASE_FILES="$RELEASE_FILES ${TARBALL}.sha256"
fi
gh release create "$TAG" \
--title "Roo Code CLI v$VERSION" \
--notes "$RELEASE_NOTES" \
--prerelease \
--target "$COMMIT_SHA" \
$RELEASE_FILES
info "Release created!"
}
# Cleanup
cleanup() {
info "Cleaning up..."
cd "$REPO_ROOT"
rm -f "$TARBALL" "${TARBALL}.sha256"
}
# Print summary
print_summary() {
echo ""
printf "${GREEN}${BOLD}✓ Release v$VERSION created successfully!${NC}\n"
echo ""
echo " Release URL: https://github.com/RooCodeInc/Roo-Code/releases/tag/$TAG"
echo ""
echo " Install with:"
echo " curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh"
echo ""
}
# Print dry-run summary
print_dry_run_summary() {
echo ""
printf "${YELLOW}${BOLD}✓ Dry run complete for v$VERSION${NC}\n"
echo ""
echo " The following artifacts were created:"
echo " - $TARBALL"
if [ -f "${TARBALL}.sha256" ]; then
echo " - ${TARBALL}.sha256"
fi
echo ""
echo " To complete the release, run without --dry-run:"
echo " ./apps/cli/scripts/release.sh $VERSION"
echo ""
echo " Or manually upload the tarball to a new GitHub release."
echo ""
}
# Print local build summary
print_local_summary() {
echo ""
printf "${GREEN}${BOLD}✓ Local build complete for v$VERSION${NC}\n"
echo ""
echo " Tarball: $REPO_ROOT/$TARBALL"
if [ -f "${TARBALL}.sha256" ]; then
echo " Checksum: $REPO_ROOT/${TARBALL}.sha256"
fi
echo ""
echo " To install manually:"
echo " ROO_LOCAL_TARBALL=$REPO_ROOT/$TARBALL ./apps/cli/install.sh"
echo ""
echo " Or re-run with --install to install automatically:"
echo " ./apps/cli/scripts/release.sh --local --install"
echo ""
}
# Install locally using the install script
install_local() {
step "7/8" "Installing locally..."
TARBALL_PATH="$REPO_ROOT/$TARBALL"
ROO_LOCAL_TARBALL="$TARBALL_PATH" \
ROO_VERSION="$VERSION" \
"$CLI_DIR/install.sh" || {
error "Local installation failed!"
}
info "Local installation complete!"
}
# Print local install summary
print_local_install_summary() {
echo ""
printf "${GREEN}${BOLD}✓ Local build installed for v$VERSION${NC}\n"
echo ""
echo " Tarball: $REPO_ROOT/$TARBALL"
echo " Installed to: ~/.roo/cli"
echo " Binary: ~/.local/bin/roo"
echo ""
echo " Test it out:"
echo " roo --version"
echo " roo --help"
echo ""
}
# Main
main() {
echo ""
printf "${BLUE}${BOLD}"
echo " ╭─────────────────────────────────╮"
echo " │ Roo Code CLI Release Script │"
echo " ╰─────────────────────────────────╯"
printf "${NC}"
if [ "$DRY_RUN" = true ]; then
printf "${YELLOW} (DRY RUN MODE)${NC}\n"
elif [ "$LOCAL_BUILD" = true ]; then
printf "${YELLOW} (LOCAL BUILD MODE)${NC}\n"
fi
echo ""
detect_platform
check_prerequisites
get_version
get_changelog_content
build
create_tarball
verify_local_install
create_checksum
if [ "$LOCAL_BUILD" = true ]; then
step "7/8" "Skipping GitHub checks (local build)"
if [ "$LOCAL_INSTALL" = true ]; then
install_local
print_local_install_summary
else
step "8/8" "Skipping installation (use --install to auto-install)"
print_local_summary
fi
elif [ "$DRY_RUN" = true ]; then
step "7/8" "Skipping existing release check (dry run)"
step "8/8" "Skipping GitHub release creation (dry run)"
print_dry_run_summary
else
check_existing_release
create_release
cleanup
print_summary
fi
}
main

View file

@ -59,6 +59,11 @@ export interface AskDispatcherOptions {
*/
nonInteractive?: boolean
/**
* Whether to exit on API request errors instead of retrying.
*/
exitOnError?: boolean
/**
* Whether to disable ask handling (for TUI mode).
* In TUI mode, the TUI handles asks directly.
@ -87,6 +92,7 @@ export class AskDispatcher {
private promptManager: PromptManager
private sendMessage: (message: WebviewMessage) => void
private nonInteractive: boolean
private exitOnError: boolean
private disabled: boolean
/**
@ -100,6 +106,7 @@ export class AskDispatcher {
this.promptManager = options.promptManager
this.sendMessage = options.sendMessage
this.nonInteractive = options.nonInteractive ?? false
this.exitOnError = options.exitOnError ?? false
this.disabled = options.disabled ?? false
}
@ -518,6 +525,11 @@ export class AskDispatcher {
this.outputManager.output(` Error: ${text || "Unknown error"}`)
this.outputManager.markDisplayed(ts, text || "", false)
if (this.exitOnError) {
console.error(`[CLI] API request failed: ${text || "Unknown error"}`)
process.exit(1)
}
if (this.nonInteractive) {
this.outputManager.output("\n[retrying api request]")
// Auto-retry in non-interactive mode

View file

@ -24,7 +24,7 @@ import type {
WebviewMessage,
} from "@roo-code/types"
import { createVSCodeAPI, IExtensionHost, ExtensionHostEventMap, setRuntimeConfigValues } from "@roo-code/vscode-shim"
import { DebugLogger } from "@roo-code/core/cli"
import { DebugLogger, setDebugLogEnabled } from "@roo-code/core/cli"
import type { SupportedProvider } from "@/types/index.js"
import type { User } from "@/lib/sdk/index.js"
@ -43,10 +43,25 @@ const cliLogger = new DebugLogger("CLI")
// Get the CLI package root directory (for finding node_modules/@vscode/ripgrep)
// When running from a release tarball, ROO_CLI_ROOT is set by the wrapper script.
// In development, we fall back to calculating from __dirname.
// After bundling with tsup, the code is in dist/index.js (flat), so we go up one level.
// In development, we fall back to finding the CLI package root by walking up to package.json.
// This works whether running from dist/ (bundled) or src/agent/ (tsx dev).
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const CLI_PACKAGE_ROOT = process.env.ROO_CLI_ROOT || path.resolve(__dirname, "..")
function findCliPackageRoot(): string {
let dir = __dirname
while (dir !== path.dirname(dir)) {
if (fs.existsSync(path.join(dir, "package.json"))) {
return dir
}
dir = path.dirname(dir)
}
return path.resolve(__dirname, "..")
}
const CLI_PACKAGE_ROOT = process.env.ROO_CLI_ROOT || findCliPackageRoot()
export interface ExtensionHostOptions {
mode: string
@ -64,6 +79,10 @@ export interface ExtensionHostOptions {
ephemeral: boolean
debug: boolean
exitOnComplete: boolean
/**
* When true, exit the process on API request errors instead of retrying.
*/
exitOnError?: boolean
/**
* When true, completely disables all direct stdout/stderr output.
* Use this when running in TUI mode where Ink controls the terminal.
@ -154,6 +173,11 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
this.options = options
// Enable file-based debug logging only when --debug is passed.
if (options.debug) {
setDebugLogEnabled(true)
}
// Set up quiet mode early, before any extension code runs.
// This suppresses console output from the extension during load.
this.setupQuietMode()
@ -179,6 +203,7 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
promptManager: this.promptManager,
sendMessage: (msg) => this.sendToExtension(msg),
nonInteractive: options.nonInteractive,
exitOnError: options.exitOnError,
disabled: options.disableOutput, // TUI mode handles asks directly.
})
@ -448,6 +473,25 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
const cleanup = () => {
this.client.off("taskCompleted", completeHandler)
this.client.off("error", errorHandler)
if (messageHandler) {
this.client.off("message", messageHandler)
}
}
// When exitOnError is enabled, listen for api_req_retry_delayed messages
// (sent by Task.ts during auto-approval retry backoff) and exit immediately.
let messageHandler: ((msg: ClineMessage) => void) | null = null
if (this.options.exitOnError) {
messageHandler = (msg: ClineMessage) => {
if (msg.type === "say" && msg.say === "api_req_retry_delayed") {
cleanup()
reject(new Error(msg.text?.split("\n")[0] || "API request failed"))
}
}
this.client.on("message", messageHandler)
}
this.client.once("taskCompleted", completeHandler)

View file

@ -65,8 +65,10 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
flagOptions.reasoningEffort || settings.reasoningEffort || DEFAULT_FLAGS.reasoningEffort
const effectiveProvider = flagOptions.provider ?? settings.provider ?? (rooToken ? "roo" : "openrouter")
const effectiveWorkspacePath = flagOptions.workspace ? path.resolve(flagOptions.workspace) : process.cwd()
const effectiveDangerouslySkipPermissions =
flagOptions.yes || flagOptions.dangerouslySkipPermissions || settings.dangerouslySkipPermissions || false
const legacyRequireApprovalFromSettings =
settings.requireApproval ??
(settings.dangerouslySkipPermissions === undefined ? undefined : !settings.dangerouslySkipPermissions)
const effectiveRequireApproval = flagOptions.requireApproval || legacyRequireApprovalFromSettings || false
const effectiveExitOnComplete = flagOptions.print || flagOptions.oneshot || settings.oneshot || false
const extensionHostOptions: ExtensionHostOptions = {
@ -77,7 +79,8 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
model: effectiveModel,
workspacePath: effectiveWorkspacePath,
extensionPath: path.resolve(flagOptions.extension || getDefaultExtensionPath(__dirname)),
nonInteractive: effectiveDangerouslySkipPermissions,
nonInteractive: !effectiveRequireApproval,
exitOnError: flagOptions.exitOnError,
ephemeral: flagOptions.ephemeral,
debug: flagOptions.debug,
exitOnComplete: effectiveExitOnComplete,
@ -112,15 +115,18 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
extensionHostOptions.apiKey = rooToken
extensionHostOptions.user = me.user
} catch {
console.error("[CLI] Your Roo Code Router token is not valid.")
console.error("[CLI] Please run: roo auth login")
process.exit(1)
// If an explicit API key was provided via flag or env var, fall through
// to the general API key resolution below instead of exiting.
if (!flagOptions.apiKey && !getApiKeyFromEnv(extensionHostOptions.provider)) {
console.error("[CLI] Your Roo Code Router token is not valid.")
console.error("[CLI] Please run: roo auth login")
console.error("[CLI] Or use --api-key or set ROO_API_KEY to provide your own API key.")
process.exit(1)
}
}
} else {
console.error("[CLI] Your Roo Code Router token is missing.")
console.error("[CLI] Please run: roo auth login")
process.exit(1)
}
// If no rooToken, fall through to the general API key resolution below
// which will check flagOptions.apiKey and ROO_API_KEY env var.
}
// Validations

View file

@ -18,7 +18,7 @@ program
.option("-p, --print", "Print response and exit (non-interactive mode)", false)
.option("-e, --extension <path>", "Path to the extension bundle directory")
.option("-d, --debug", "Enable debug output (includes detailed debug information)", false)
.option("-y, --yes, --dangerously-skip-permissions", "Auto-approve all prompts (use with caution)", false)
.option("-a, --require-approval", "Require manual approval for actions", false)
.option("-k, --api-key <key>", "API key for the LLM provider")
.option("--provider <provider>", "API provider (roo, anthropic, openai, openrouter, etc.)")
.option("-m, --model <model>", "Model to use", DEFAULT_FLAGS.model)
@ -28,6 +28,7 @@ program
"Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh)",
DEFAULT_FLAGS.reasoningEffort,
)
.option("--exit-on-error", "Exit on API request errors instead of retrying", false)
.option("--ephemeral", "Run without persisting state (uses temporary storage)", false)
.option("--oneshot", "Exit upon task completion", false)
.option(

View file

@ -103,7 +103,7 @@ describe("Settings Storage", () => {
await saveSettings({
mode: "architect",
provider: "anthropic" as const,
model: "claude-opus-4.5",
model: "claude-opus-4.6",
reasoningEffort: "medium" as const,
})
@ -112,7 +112,7 @@ describe("Settings Storage", () => {
expect(settings.mode).toBe("architect")
expect(settings.provider).toBe("anthropic")
expect(settings.model).toBe("claude-opus-4.5")
expect(settings.model).toBe("claude-opus-4.6")
expect(settings.reasoningEffort).toBe("medium")
})
@ -179,20 +179,20 @@ describe("Settings Storage", () => {
expect(loaded.reasoningEffort).toBe("low")
})
it("should support dangerouslySkipPermissions setting", async () => {
await saveSettings({ dangerouslySkipPermissions: true })
it("should support requireApproval setting", async () => {
await saveSettings({ requireApproval: true })
const loaded = await loadSettings()
expect(loaded.dangerouslySkipPermissions).toBe(true)
expect(loaded.requireApproval).toBe(true)
})
it("should support all settings together including dangerouslySkipPermissions", async () => {
it("should support all settings together including requireApproval", async () => {
const allSettings = {
mode: "architect",
provider: "anthropic" as const,
model: "claude-sonnet-4-20250514",
reasoningEffort: "high" as const,
dangerouslySkipPermissions: true,
requireApproval: true,
}
await saveSettings(allSettings)
@ -202,7 +202,7 @@ describe("Settings Storage", () => {
expect(loaded.provider).toBe("anthropic")
expect(loaded.model).toBe("claude-sonnet-4-20250514")
expect(loaded.reasoningEffort).toBe("high")
expect(loaded.dangerouslySkipPermissions).toBe(true)
expect(loaded.requireApproval).toBe(true)
})
it("should support oneshot setting", async () => {
@ -218,7 +218,7 @@ describe("Settings Storage", () => {
provider: "anthropic" as const,
model: "claude-sonnet-4-20250514",
reasoningEffort: "high" as const,
dangerouslySkipPermissions: true,
requireApproval: true,
oneshot: true,
}
@ -229,8 +229,15 @@ describe("Settings Storage", () => {
expect(loaded.provider).toBe("anthropic")
expect(loaded.model).toBe("claude-sonnet-4-20250514")
expect(loaded.reasoningEffort).toBe("high")
expect(loaded.dangerouslySkipPermissions).toBe(true)
expect(loaded.requireApproval).toBe(true)
expect(loaded.oneshot).toBe(true)
})
it("should still load legacy dangerouslySkipPermissions setting", async () => {
await saveSettings({ dangerouslySkipPermissions: true })
const loaded = await loadSettings()
expect(loaded.dangerouslySkipPermissions).toBe(true)
})
})
})

View file

@ -21,9 +21,26 @@ describe("getDefaultExtensionPath", () => {
it("should return monorepo path when extension.js exists there", () => {
const mockDirname = "/test/apps/cli/dist"
const expectedMonorepoPath = path.resolve(mockDirname, "../../../src/dist")
const expectedMonorepoPath = path.resolve("/test/apps/cli", "../../src/dist")
vi.mocked(fs.existsSync).mockReturnValue(true)
// Walk-up: dist/ has no package.json, apps/cli/ does
vi.mocked(fs.existsSync).mockImplementation((p) => {
const s = String(p)
if (s === path.join(mockDirname, "package.json")) {
return false
}
if (s === path.join("/test/apps/cli", "package.json")) {
return true
}
if (s === path.join(expectedMonorepoPath, "extension.js")) {
return true
}
return false
})
const result = getDefaultExtensionPath(mockDirname)
@ -33,9 +50,18 @@ describe("getDefaultExtensionPath", () => {
it("should return package path when extension.js does not exist in monorepo path", () => {
const mockDirname = "/test/apps/cli/dist"
const expectedPackagePath = path.resolve(mockDirname, "../extension")
const expectedPackagePath = path.resolve("/test/apps/cli", "extension")
vi.mocked(fs.existsSync).mockReturnValue(false)
// Walk-up finds package.json at apps/cli/, but no extension.js in monorepo path
vi.mocked(fs.existsSync).mockImplementation((p) => {
const s = String(p)
if (s === path.join("/test/apps/cli", "package.json")) {
return true
}
return false
})
const result = getDefaultExtensionPath(mockDirname)
@ -43,12 +69,45 @@ describe("getDefaultExtensionPath", () => {
})
it("should check monorepo path first", () => {
const mockDirname = "/some/path"
vi.mocked(fs.existsSync).mockReturnValue(false)
const mockDirname = "/test/apps/cli/dist"
vi.mocked(fs.existsSync).mockImplementation((p) => {
const s = String(p)
if (s === path.join("/test/apps/cli", "package.json")) {
return true
}
return false
})
getDefaultExtensionPath(mockDirname)
const expectedMonorepoPath = path.resolve(mockDirname, "../../../src/dist")
const expectedMonorepoPath = path.resolve("/test/apps/cli", "../../src/dist")
expect(fs.existsSync).toHaveBeenCalledWith(path.join(expectedMonorepoPath, "extension.js"))
})
it("should work when called from source directory (tsx dev)", () => {
const mockDirname = "/test/apps/cli/src/commands/cli"
const expectedMonorepoPath = path.resolve("/test/apps/cli", "../../src/dist")
// Walk-up: no package.json in src subdirs, found at apps/cli/
vi.mocked(fs.existsSync).mockImplementation((p) => {
const s = String(p)
if (s === path.join("/test/apps/cli", "package.json")) {
return true
}
if (s === path.join(expectedMonorepoPath, "extension.js")) {
return true
}
return false
})
const result = getDefaultExtensionPath(mockDirname)
expect(result).toBe(expectedMonorepoPath)
})
})

View file

@ -17,17 +17,26 @@ export function getDefaultExtensionPath(dirname: string): string {
}
}
// __dirname is apps/cli/dist when bundled
// The extension is at src/dist (relative to monorepo root)
// So from apps/cli/dist, we need to go ../../../src/dist
const monorepoPath = path.resolve(dirname, "../../../src/dist")
// Find the CLI package root (apps/cli) by walking up to the nearest package.json.
// This works whether called from dist/ (bundled) or src/commands/cli/ (tsx dev).
let packageRoot = dirname
while (packageRoot !== path.dirname(packageRoot)) {
if (fs.existsSync(path.join(packageRoot, "package.json"))) {
break
}
packageRoot = path.dirname(packageRoot)
}
// The extension is at ../../src/dist relative to apps/cli (monorepo/src/dist)
const monorepoPath = path.resolve(packageRoot, "../../src/dist")
// Try monorepo path first (for development)
if (fs.existsSync(path.join(monorepoPath, "extension.js"))) {
return monorepoPath
}
// Fallback: when installed via curl script, extension is at ../extension
const packagePath = path.resolve(dirname, "../extension")
// Fallback: when installed via curl script, extension is at apps/cli/extension
const packagePath = path.resolve(packageRoot, "extension")
return packagePath
}

View file

@ -1,6 +1,24 @@
import { createRequire } from "module"
import fs from "fs"
import path from "path"
import { fileURLToPath } from "url"
const require = createRequire(import.meta.url)
const packageJson = require("../package.json")
// Walk up from the current file to find the nearest package.json.
// This works whether running from source (tsx src/lib/utils/) or bundle (dist/).
function findVersion(): string {
let dir = path.dirname(fileURLToPath(import.meta.url))
export const VERSION = packageJson.version
while (dir !== path.dirname(dir)) {
const candidate = path.join(dir, "package.json")
if (fs.existsSync(candidate)) {
const packageJson = JSON.parse(fs.readFileSync(candidate, "utf-8"))
return packageJson.version
}
dir = path.dirname(dir)
}
return "0.0.0"
}
export const VERSION = findVersion()

View file

@ -3,7 +3,7 @@ import { reasoningEffortsExtended } from "@roo-code/types"
export const DEFAULT_FLAGS = {
mode: "code",
reasoningEffort: "medium" as const,
model: "anthropic/claude-opus-4.5",
model: "anthropic/claude-opus-4.6",
}
export const REASONING_EFFORTS = [...reasoningEffortsExtended, "unspecified", "disabled"]

View file

@ -24,8 +24,8 @@ export type FlagOptions = {
print: boolean
extension?: string
debug: boolean
yes: boolean
dangerouslySkipPermissions: boolean
requireApproval: boolean
exitOnError: boolean
apiKey?: string
provider?: SupportedProvider
model?: string
@ -57,7 +57,9 @@ export interface CliSettings {
model?: string
/** Default reasoning effort level */
reasoningEffort?: ReasoningEffortFlagOptions
/** Auto-approve all prompts (use with caution) */
/** Require manual approval for tools/commands/browser/MCP actions */
requireApproval?: boolean
/** @deprecated Legacy inverse setting kept for backward compatibility */
dangerouslySkipPermissions?: boolean
/** Exit upon task completion */
oneshot?: boolean

View file

@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts"
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View file

@ -1,10 +1,7 @@
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
webpack: (config) => {
config.resolve.extensionAlias = { ".js": [".ts", ".tsx", ".js", ".jsx"] }
return config
},
turbopack: {},
}
export default nextConfig

View file

@ -3,7 +3,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"lint": "next lint --max-warnings 0",
"lint": "eslint src --ext=ts,tsx --max-warnings=0",
"check-types": "tsc -b",
"dev": "scripts/check-services.sh && next dev -p 3446",
"format": "prettier --write src",
@ -27,7 +27,7 @@
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@roo-code/evals": "workspace:^",
"@roo-code/types": "workspace:^",
"@roo-code/types": "^1.108.0",
"@tanstack/react-query": "^5.69.0",
"archiver": "^7.0.1",
"class-variance-authority": "^0.7.1",
@ -35,7 +35,7 @@
"cmdk": "^1.1.0",
"fuzzysort": "^3.1.0",
"lucide-react": "^0.518.0",
"next": "~15.2.8",
"next": "^16.1.6",
"next-themes": "^0.4.6",
"p-map": "^7.0.3",
"react": "^18.3.1",

View file

@ -1,9 +1,9 @@
import path from "path"
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
webpack: (config) => {
config.resolve.extensionAlias = { ".js": [".ts", ".tsx", ".js", ".jsx"] }
return config
turbopack: {
root: path.join(__dirname, "../.."),
},
async redirects() {
return [

View file

@ -3,7 +3,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"lint": "next lint --max-warnings 0",
"lint": "eslint src --ext=ts,tsx --max-warnings=0",
"check-types": "tsc --noEmit",
"dev": "next dev",
"build": "next build",
@ -12,22 +12,23 @@
"clean": "rimraf .next .turbo"
},
"dependencies": {
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-navigation-menu": "^1.2.14",
"@radix-ui/react-slot": "^1.2.4",
"@roo-code/evals": "workspace:^",
"@roo-code/types": "workspace:^",
"@tanstack/react-query": "^5.79.0",
"@vercel/og": "^0.6.2",
"@roo-code/types": "^1.108.0",
"@tanstack/react-query": "^5.90.20",
"@vercel/og": "^0.8.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"embla-carousel-auto-scroll": "^8.6.0",
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"framer-motion": "12.15.0",
"lucide-react": "^0.518.0",
"next": "~15.2.8",
"framer-motion": "^12.29.2",
"lucide-react": "^0.563.0",
"next": "^16.1.6",
"next-themes": "^0.4.6",
"posthog-js": "^1.248.1",
"posthog-js": "^1.336.4",
"react": "^18.3.1",
"react-cookie-consent": "^9.0.0",
"react-dom": "^18.3.1",
@ -36,7 +37,7 @@
"recharts": "^2.15.3",
"rehype-raw": "^7.0.0",
"remark-gfm": "^4.0.1",
"tailwind-merge": "^3.3.0",
"tailwind-merge": "^3.4.0",
"tailwindcss-animate": "^1.0.7",
"tldts": "^6.1.86",
"zod": "^3.25.61"
@ -44,13 +45,13 @@
"devDependencies": {
"@roo-code/config-eslint": "workspace:^",
"@roo-code/config-typescript": "workspace:^",
"@tailwindcss/typography": "^0.5.16",
"@tailwindcss/typography": "^0.5.19",
"@types/node": "20.x",
"@types/react": "^18.3.23",
"@types/react-dom": "^18.3.7",
"autoprefixer": "^10.4.21",
"autoprefixer": "^10.4.23",
"next-sitemap": "^4.2.3",
"postcss": "^8.5.4",
"postcss": "^8.5.6",
"tailwindcss": "^3.4.17"
}
}

View file

@ -5,9 +5,9 @@ import {
ChartLine,
Github,
History,
ListChecks,
LucideIcon,
Pencil,
Router,
Share2,
Slack,
Users,
@ -22,7 +22,7 @@ import { SEO } from "@/lib/seo"
import { ogImageUrl } from "@/lib/og"
import { EXTERNAL_LINKS } from "@/lib/constants"
// Workaround for next/image choking on these for some reason
import screenshotDark from "/public/heroes/cloud-screen.png"
import screenshotDark from "../../../public/heroes/cloud-screen.png"
const TITLE = "Roo Code Cloud"
const DESCRIPTION =
@ -112,9 +112,9 @@ const features: Feature[] = [
description: "Start tasks, get updates, and collaborate with agents directly from your team's Slack channels.",
},
{
icon: Router,
title: "Roomote Control",
description: "Connect to your local VS Code instance and control the extension remotely from the browser.",
icon: ListChecks,
title: "Linear Integration",
description: "Assign issues to Roo Code directly from Linear. Get PRs back without switching tools.",
},
{
icon: Users,

View file

@ -2,7 +2,7 @@ import { type AgentPageContent } from "@/app/shared/agent-page-content"
import Link from "next/link"
// Workaround for next/image choking on these for some reason
import hero from "/public/heroes/agent-pr-fixer.png"
import hero from "../../../public/heroes/agent-pr-fixer.png"
// Re-export for convenience
export type { AgentPageContent }

View file

@ -252,7 +252,7 @@ export default function ProviderPage() {
{faqs.map((faq, index) => (
<div key={index} className="rounded-2xl border border-border bg-card p-6">
<h3 className="font-semibold">{faq.question}</h3>
<p className="mt-2 text-sm text-muted-foreground">{faq.answer}</p>
<div className="mt-2 text-sm text-muted-foreground">{faq.answer}</div>
</div>
))}
</div>

View file

@ -1,7 +1,7 @@
import { type AgentPageContent } from "@/app/shared/agent-page-content"
// Workaround for next/image choking on these for some reason
import hero from "/public/heroes/agent-reviewer.png"
import hero from "../../../public/heroes/agent-reviewer.png"
// Re-export for convenience
export type { AgentPageContent }

View file

@ -1,7 +1,7 @@
import { type AgentPageContent } from "@/app/shared/agent-page-content"
// Workaround for next/image choking on these for some reason
import hero from "/public/heroes/agent-reviewer.png"
import hero from "../../../public/heroes/agent-reviewer.png"
// Re-export for convenience
export type { AgentPageContent }

View file

@ -13,7 +13,25 @@ import { EXTERNAL_LINKS } from "@/lib/constants"
import { useLogoSrc } from "@/lib/hooks/use-logo-src"
import { ScrollButton } from "@/components/ui"
import ThemeToggle from "@/components/chromes/theme-toggle"
import { Brain, ChevronDown, Cloud, Puzzle, Slack, X } from "lucide-react"
import { Brain, Cloud, Puzzle, Slack, X } from "lucide-react"
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"
import { cn } from "@/lib/utils"
function LinearIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 100 100" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M1.22541 61.5228c-.2225-.9485.90748-1.5459 1.59638-.857L39.3342 97.1782c.6889.6889.0915 1.8189-.857 1.5964C20.0515 94.4522 5.54779 79.9485 1.22541 61.5228ZM.00189135 46.8891c-.01764375.2833.08887215.5599.28957165.7606L52.3503 99.7085c.2007.2007.4773.3075.7606.2896 2.3692-.1476 4.6938-.46 6.9624-.9259.7645-.157 1.0301-1.0963.4782-1.6481L2.57595 39.4485c-.55186-.5519-1.49117-.2863-1.648174.4782-.465915 2.2686-.77832 4.5932-.92588465 6.9624ZM4.21093 29.7054c-.16649.3738-.08169.8106.20765 1.1l64.77602 64.776c.2894.2894.7262.3742 1.1.2077 1.7861-.7956 3.5171-1.6927 5.1855-2.684.5521-.328.6373-1.0867.1832-1.5407L8.43566 24.3367c-.45409-.4541-1.21271-.3689-1.54074.1832-.99132 1.6684-1.88843 3.3994-2.68399 5.1855ZM12.6587 18.074c-.3701-.3701-.393-.9637-.0443-1.3541C21.7795 6.45931 35.1114 0 49.9519 0 77.5927 0 100 22.4073 100 50.0481c0 14.8405-6.4593 28.1724-16.7199 37.3375-.3903.3487-.984.3258-1.3542-.0443L12.6587 18.074Z" />
</svg>
)
}
interface NavBarProps {
stars: string | null
@ -27,89 +45,137 @@ export function NavBar({ stars, downloads }: NavBarProps) {
return (
<header className="sticky font-light top-0 z-50 border-b border-border bg-background/80 backdrop-blur-md">
<div className="container flex h-16 items-center justify-between px-4 sm:px-6 lg:px-8">
<div className="flex items-center">
<div className="flex items-center flex-shrink-0">
<Link href="/" className="flex items-center">
<Image src={logoSrc} alt="Roo Code Logo" width={130} height={24} className="h-[24px] w-auto" />
</Link>
</div>
{/* Desktop Navigation */}
<nav className="grow ml-6 hidden text-sm md:flex md:items-center">
{/* Product Dropdown */}
<div className="relative group">
<button className="flex items-center px-4 py-6 gap-1 transition-transform duration-200 hover:scale-105 hover:text-foreground">
Product
<ChevronDown className="size-3 ml-1 mt-0.5" />
</button>
<div className="absolute left-0 top-12 mt-2 w-[260px] rounded-md border border-border bg-background py-1 shadow-lg opacity-0 -translate-y-2 pointer-events-none group-hover:opacity-100 group-hover:translate-y-0 group-hover:pointer-events-auto transition-all duration-200">
<Link
href="/extension"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground">
<Puzzle className="size-3 inline mr-2 -mt-0.5" />
Roo Code VS Code Extension
</Link>
<Link
href="/cloud"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground">
<Cloud className="size-3 inline mr-2 -mt-0.5" />
Roo Code Cloud
</Link>
<Link
href="/slack"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground">
<Slack className="size-3 inline mr-2 -mt-0.5" />
Roo Code for Slack
</Link>
<Link
href="/provider"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground">
<Brain className="size-3 inline mr-2 -mt-0.5" />
Roo Code Router
</Link>
</div>
</div>
{/* Resources Dropdown */}
<div className="relative group">
<button className="flex items-center px-4 py-6 gap-1 transition-transform duration-200 hover:scale-105 hover:text-foreground">
Resources
<ChevronDown className="size-3 ml-1 mt-0.5" />
</button>
{/* Dropdown Menu */}
<div className="absolute left-0 top-12 mt-2 w-40 rounded-md border border-border bg-background py-1 shadow-lg opacity-0 -translate-y-2 pointer-events-none group-hover:opacity-100 group-hover:translate-y-0 group-hover:pointer-events-auto transition-all duration-200">
<Link
href="/evals"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground">
Evals
</Link>
<a
href={EXTERNAL_LINKS.DISCORD}
target="_blank"
rel="noopener noreferrer"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground">
Discord
</a>
<a
href={EXTERNAL_LINKS.SECURITY}
target="_blank"
rel="noopener noreferrer"
className="block px-4 py-2 text-sm transition-colors hover:bg-accent hover:text-foreground"
onClick={() => setIsMenuOpen(false)}>
Trust Center
</a>
</div>
</div>
<a
href={EXTERNAL_LINKS.DOCUMENTATION}
target="_blank"
className="px-4 py-6 transition-transform duration-200 hover:scale-105 hover:text-foreground">
Docs
</a>
<Link
href="/pricing"
className="px-4 py-6 transition-transform duration-200 hover:scale-105 hover:text-foreground">
Pricing
</Link>
</nav>
<NavigationMenu className="grow ml-6 hidden text-sm md:flex">
<NavigationMenuList>
{/* Product Dropdown */}
<NavigationMenuItem>
<NavigationMenuTrigger className="bg-transparent font-light">Product</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid min-w-[260px] gap-1 p-2">
<li>
<NavigationMenuLink asChild>
<Link
href="/extension"
className="flex items-center select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
<Puzzle className="size-3 mr-2" />
Roo Code VS Code Extension
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
href="/cloud"
className="flex items-center select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
<Cloud className="size-3 mr-2" />
Roo Code Cloud
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
href="/slack"
className="flex items-center select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
<Slack className="size-3 mr-2" />
Roo Code for Slack
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
href="/linear"
className="flex items-center select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
<LinearIcon className="size-3 mr-2" />
Roo Code for Linear
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<Link
href="/provider"
className="flex items-center select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
<Brain className="size-3 mr-2" />
Roo Code Router
</Link>
</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
{/* Resources Dropdown */}
<NavigationMenuItem>
<NavigationMenuTrigger className="bg-transparent font-light">
Resources
</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid min-w-[260px] gap-1 p-2">
<li>
<NavigationMenuLink asChild>
<Link
href="/evals"
className="block select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
Evals
</Link>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<a
href={EXTERNAL_LINKS.DISCORD}
target="_blank"
rel="noopener noreferrer"
className="block select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
Discord
</a>
</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink asChild>
<a
href={EXTERNAL_LINKS.SECURITY}
target="_blank"
rel="noopener noreferrer"
className="block select-none rounded-md px-3 py-2 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground">
Trust Center
</a>
</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
{/* Docs Link */}
<NavigationMenuItem>
<NavigationMenuLink
asChild
className={cn(navigationMenuTriggerStyle(), "bg-transparent font-light")}>
<a href={EXTERNAL_LINKS.DOCUMENTATION} target="_blank">
Docs
</a>
</NavigationMenuLink>
</NavigationMenuItem>
{/* Pricing Link */}
<NavigationMenuItem>
<NavigationMenuLink
asChild
className={cn(navigationMenuTriggerStyle(), "bg-transparent font-light")}>
<Link href="/pricing">Pricing</Link>
</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
<div className="hidden md:flex md:items-center md:space-x-4 flex-shrink-0 font-medium">
<div className="flex flex-row space-x-2 flex-shrink-0">

View file

@ -92,7 +92,7 @@ export function Features() {
opacity: 1,
transition: {
duration: 1.2,
ease: "easeOut",
ease: "easeOut" as const,
},
},
}

View file

@ -17,7 +17,7 @@ export function InstallSection({ downloads }: InstallSectionProps) {
opacity: 1,
transition: {
duration: 1.2,
ease: "easeOut",
ease: "easeOut" as const,
},
},
}

View file

@ -179,7 +179,7 @@ export function Testimonials() {
opacity: 1,
transition: {
duration: 0.6,
ease: [0.21, 0.45, 0.27, 0.9],
ease: [0.21, 0.45, 0.27, 0.9] as const,
},
},
}

View file

@ -41,6 +41,7 @@ interface PositionedUseCase extends UseCase {
scale: number
zIndex: number
avatar: string
width: number
}
const SOURCES = {
@ -243,7 +244,7 @@ const LAYER_SCALES = {
}
function distributeItems(items: UseCase[]): PositionedUseCase[] {
const rng = seededRandom(Math.random() * 12345)
const rng = seededRandom(42)
const zones = { rows: 7, cols: 4 }
const zoneWidth = 100 / zones.cols
const zoneHeight = 100 / zones.rows
@ -284,6 +285,7 @@ function distributeItems(items: UseCase[]): PositionedUseCase[] {
},
scale: LAYER_SCALES[layer],
zIndex: layer,
width: Math.round(300 + rng() * 100),
}
})
}
@ -345,7 +347,7 @@ function DesktopUseCaseCard({ item }: { item: PositionedUseCase }) {
left: `${item.position.x}%`,
top: `${item.position.y}%`,
zIndex: item.zIndex,
width: Math.round(300 + Math.random() * 100),
width: item.width,
}}
initial={{ opacity: 0, scale: 0 }}
whileInView={{

View file

@ -0,0 +1,117 @@
import * as React from "react"
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { cva } from "class-variance-authority"
import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const NavigationMenu = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Root
ref={ref}
className={cn("relative z-10 flex max-w-max flex-1 items-center", className)}
{...props}>
{children}
<NavigationMenuViewport />
</NavigationMenuPrimitive.Root>
))
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
const NavigationMenuList = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.List>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.List
ref={ref}
className={cn("group flex flex-1 list-none items-center space-x-1", className)}
{...props}
/>
))
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
const NavigationMenuItem = NavigationMenuPrimitive.Item
const navigationMenuTriggerStyle = cva(
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-accent-foreground data-[state=open]:bg-accent/50 data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent",
)
const NavigationMenuTrigger = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Trigger
ref={ref}
className={cn(navigationMenuTriggerStyle(), "group", className)}
{...props}>
{children}{" "}
<ChevronDown
className="relative top-[1px] ml-1 h-3 w-3 transition duration-300 group-data-[state=open]:rotate-180"
aria-hidden="true"
/>
</NavigationMenuPrimitive.Trigger>
))
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
const NavigationMenuContent = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Content
ref={ref}
className={cn(
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
className,
)}
{...props}
/>
))
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
const NavigationMenuLink = NavigationMenuPrimitive.Link
const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<div className={cn("absolute left-0 top-full flex justify-center")}>
<NavigationMenuPrimitive.Viewport
className={cn(
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
className,
)}
ref={ref}
{...props}
/>
</div>
))
NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName
const NavigationMenuIndicator = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Indicator
ref={ref}
className={cn(
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
className,
)}
{...props}>
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
</NavigationMenuPrimitive.Indicator>
))
NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName
export {
navigationMenuTriggerStyle,
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuContent,
NavigationMenuTrigger,
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
}

30
apps/web-roo-code/src/images.d.ts vendored Normal file
View file

@ -0,0 +1,30 @@
declare module "*.png" {
const content: import("next/image").StaticImageData
export default content
}
declare module "*.jpg" {
const content: import("next/image").StaticImageData
export default content
}
declare module "*.jpeg" {
const content: import("next/image").StaticImageData
export default content
}
declare module "*.svg" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches Next.js built-in SVG type to avoid conflicts with @svgr/webpack
const content: any
export default content
}
declare module "*.gif" {
const content: import("next/image").StaticImageData
export default content
}
declare module "*.webp" {
const content: import("next/image").StaticImageData
export default content
}

View file

@ -21,6 +21,7 @@
"clean": "turbo clean --log-order grouped --output-logs new-only && rimraf dist out bin .vite-port .turbo",
"install:vsix": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix && node scripts/install-vsix.js",
"install:vsix:nightly": "pnpm install --frozen-lockfile && pnpm clean && pnpm vsix:nightly && node scripts/install-vsix.js --nightly",
"code-server:install": "node scripts/code-server.js",
"changeset:version": "cp CHANGELOG.md src/CHANGELOG.md && changeset version && cp -vf src/CHANGELOG.md .",
"knip": "knip --include files",
"evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0",

View file

@ -281,7 +281,7 @@ describe("CustomToolRegistry", () => {
const result = await registry.loadFromDirectory(TEST_FIXTURES_DIR)
expect(result.loaded).toContain("cached")
}, 30000)
}, 120_000)
})
describe.sequential("loadFromDirectories", () => {

View file

@ -21,11 +21,25 @@ import * as os from "os"
const DEBUG_LOG_PATH = path.join(os.homedir(), ".roo", "cli-debug.log")
let debugLogEnabled = false
/**
* Enable or disable file-based debug logging.
* Logging is disabled by default and should only be enabled in dev/debug mode.
*/
export function setDebugLogEnabled(enabled: boolean): void {
debugLogEnabled = enabled
}
/**
* Simple file-based debug log function.
* Writes timestamped entries to ~/.roo/cli-debug.log
* Only writes when enabled via setDebugLogEnabled(true).
*/
export function debugLog(message: string, data?: unknown): void {
if (!debugLogEnabled) {
return
}
try {
const logDir = path.dirname(DEBUG_LOG_PATH)

View file

@ -37,7 +37,7 @@ Additionally, you'll find in Docker Desktop that database and redis services are
Navigate to [localhost:3446](http://localhost:3446/) in your browser and click the 🚀 button.
By default a evals run will run all programming exercises in [Roo Code Evals](https://github.com/RooCodeInc/Roo-Code-Evals) repository with the Claude Sonnet 4 model and default settings. For basic configuration you can specify the LLM to use and any subset of the exercises you'd like. For advanced configuration you can import a Roo Code settings file which will allow you to run the evals with Roo Code configured any way you'd like (this includes custom modes, a footgun prompt, etc).
By default a evals run will run all programming exercises in [Roo Code Evals](https://github.com/RooCodeInc/Roo-Code-Evals) repository with the Claude Sonnet 4 model and default settings. For basic configuration you can specify the LLM to use and any subset of the exercises you'd like. For advanced configuration you can import a Roo Code settings file which will allow you to run the evals with Roo Code configured any way you'd like (this includes custom modes, custom instructions, etc).
<img width="1053" src="https://github.com/user-attachments/assets/2367eef4-6ae9-4ac2-8ee4-80f981046486" />

View file

@ -1,4 +1,4 @@
import { MessageLogDeduper } from "../messageLogDeduper.js"
import { MessageLogDeduper } from "../messageLogDeduper"
describe("MessageLogDeduper", () => {
it("dedupes identical messages for same action+ts", () => {

View file

@ -2,11 +2,11 @@ import * as fs from "fs"
import { run, command, option, flag, number, boolean } from "cmd-ts"
import { EVALS_REPO_PATH } from "../exercises/index.js"
import { EVALS_REPO_PATH } from "../exercises/index"
import { runCi } from "./runCi.js"
import { runEvals } from "./runEvals.js"
import { processTask } from "./processTask.js"
import { runCi } from "./runCi"
import { runEvals } from "./runEvals"
import { processTask } from "./processTask"
const main = async () => {
await run(

View file

@ -2,13 +2,13 @@ import { execa } from "execa"
import { type TaskEvent, RooCodeEventName } from "@roo-code/types"
import { findRun, findTask, updateTask } from "../db/index.js"
import { findRun, findTask, updateTask } from "../db/index"
import { Logger, getTag, isDockerContainer } from "./utils.js"
import { redisClient, getPubSubKey, registerRunner, deregisterRunner } from "./redis.js"
import { runUnitTest } from "./runUnitTest.js"
import { runTaskWithCli } from "./runTaskInCli.js"
import { runTaskInVscode } from "./runTaskInVscode.js"
import { Logger, getTag, isDockerContainer } from "./utils"
import { redisClient, getPubSubKey, registerRunner, deregisterRunner } from "./redis"
import { runUnitTest } from "./runUnitTest"
import { runTaskWithCli } from "./runTaskInCli"
import { runTaskInVscode } from "./runTaskInVscode"
export const processTask = async ({
taskId,

View file

@ -1,9 +1,9 @@
import pMap from "p-map"
import { EVALS_REPO_PATH, exerciseLanguages, getExercisesForLanguage } from "../exercises/index.js"
import { createRun, createTask } from "../db/index.js"
import { EVALS_REPO_PATH, exerciseLanguages, getExercisesForLanguage } from "../exercises/index"
import { createRun, createTask } from "../db/index"
import { runEvals } from "./runEvals.js"
import { runEvals } from "./runEvals"
export const runCi = async ({
concurrency = 1,

View file

@ -1,11 +1,11 @@
import PQueue from "p-queue"
import { findRun, finishRun, getTasks } from "../db/index.js"
import { EVALS_REPO_PATH } from "../exercises/index.js"
import { findRun, finishRun, getTasks } from "../db/index"
import { EVALS_REPO_PATH } from "../exercises/index"
import { Logger, getTag, isDockerContainer, resetEvalsRepo, commitEvalsRepoChanges } from "./utils.js"
import { startHeartbeat, stopHeartbeat } from "./redis.js"
import { processTask, processTaskInContainer } from "./processTask.js"
import { Logger, getTag, isDockerContainer, resetEvalsRepo, commitEvalsRepoChanges } from "./utils"
import { startHeartbeat, stopHeartbeat } from "./redis"
import { processTask, processTaskInContainer } from "./processTask"
export const runEvals = async (runId: number) => {
const run = await findRun(runId)

View file

@ -7,11 +7,11 @@ import { execa } from "execa"
import { type ToolUsage, TaskCommandName, RooCodeEventName, IpcMessageType } from "@roo-code/types"
import { IpcClient } from "@roo-code/ipc"
import { updateTask, createTaskMetrics, updateTaskMetrics, createToolError } from "../db/index.js"
import { EVALS_REPO_PATH } from "../exercises/index.js"
import { updateTask, createTaskMetrics, updateTaskMetrics, createToolError } from "../db/index"
import { EVALS_REPO_PATH } from "../exercises/index"
import { type RunTaskOptions } from "./types.js"
import { mergeToolUsage, waitForSubprocessWithTimeout } from "./utils.js"
import { type RunTaskOptions } from "./types"
import { mergeToolUsage, waitForSubprocessWithTimeout } from "./utils"
/**
* Run a task using the Roo Code CLI (headless mode).
@ -43,7 +43,6 @@ export const runTaskWithCli = async ({ run, task, publish, logger, jobToken }: R
promptSourcePath,
"--workspace",
workspacePath,
"--yes",
"--reasoning-effort",
"disabled",
"--oneshot",

View file

@ -15,12 +15,12 @@ import {
} from "@roo-code/types"
import { IpcClient } from "@roo-code/ipc"
import { updateTask, createTaskMetrics, updateTaskMetrics, createToolError } from "../db/index.js"
import { EVALS_REPO_PATH } from "../exercises/index.js"
import { updateTask, createTaskMetrics, updateTaskMetrics, createToolError } from "../db/index"
import { EVALS_REPO_PATH } from "../exercises/index"
import { type RunTaskOptions } from "./types.js"
import { isDockerContainer, copyConversationHistory, mergeToolUsage, waitForSubprocessWithTimeout } from "./utils.js"
import { MessageLogDeduper } from "./messageLogDeduper.js"
import { type RunTaskOptions } from "./types"
import { isDockerContainer, copyConversationHistory, mergeToolUsage, waitForSubprocessWithTimeout } from "./utils"
import { MessageLogDeduper } from "./messageLogDeduper"
export const runTaskInVscode = async ({ run, task, publish, logger, jobToken }: RunTaskOptions) => {
const { language, exercise } = task

View file

@ -3,10 +3,10 @@ import * as path from "path"
import { execa, parseCommandString } from "execa"
import psTree from "ps-tree"
import type { Task } from "../db/index.js"
import { type ExerciseLanguage, EVALS_REPO_PATH } from "../exercises/index.js"
import type { Task } from "../db/index"
import { type ExerciseLanguage, EVALS_REPO_PATH } from "../exercises/index"
import { Logger } from "./utils.js"
import { Logger } from "./utils"
const UNIT_TEST_TIMEOUT = 2 * 60 * 1_000

View file

@ -1,7 +1,7 @@
import { type TaskEvent } from "@roo-code/types"
import type { Run, Task } from "../db/index.js"
import { Logger } from "./utils.js"
import type { Run, Task } from "../db/index"
import { Logger } from "./utils"
export class SubprocessTimeoutError extends Error {
constructor(timeout: number) {

View file

@ -6,9 +6,9 @@ import { execa, type ResultPromise } from "execa"
import type { ToolUsage } from "@roo-code/types"
import type { Run, Task } from "../db/index.js"
import type { Run, Task } from "../db/index"
import { SubprocessTimeoutError } from "./types.js"
import { SubprocessTimeoutError } from "./types"
export const getTag = (caller: string, { run, task }: { run: Run; task?: Task }) =>
task

View file

@ -1,7 +1,7 @@
import { drizzle } from "drizzle-orm/postgres-js"
import postgres from "postgres"
import * as schema from "./schema.js"
import * as schema from "./schema"
const pgClient = postgres(process.env.DATABASE_URL!, { prepare: false })
const client = drizzle({ client: pgClient, schema })

View file

@ -1,9 +1,9 @@
export * from "./schema.js"
export * from "./schema"
export * from "./queries/runs.js"
export * from "./queries/tasks.js"
export * from "./queries/taskMetrics.js"
export * from "./queries/toolErrors.js"
export * from "./queries/copyRun.js"
export * from "./queries/runs"
export * from "./queries/tasks"
export * from "./queries/taskMetrics"
export * from "./queries/toolErrors"
export * from "./queries/copyRun"
export * from "./db.js"
export * from "./db"

View file

@ -2,14 +2,14 @@
import { eq } from "drizzle-orm"
import { copyRun } from "../copyRun.js"
import { createRun } from "../runs.js"
import { createTask } from "../tasks.js"
import { createTaskMetrics } from "../taskMetrics.js"
import { createToolError } from "../toolErrors.js"
import { RecordNotFoundError } from "../errors.js"
import { schema } from "../../schema.js"
import { client as db } from "../../db.js"
import { copyRun } from "../copyRun"
import { createRun } from "../runs"
import { createTask } from "../tasks"
import { createTaskMetrics } from "../taskMetrics"
import { createToolError } from "../toolErrors"
import { RecordNotFoundError } from "../errors"
import { schema } from "../../schema"
import { client as db } from "../../db"
describe("copyRun", () => {
let sourceRunId: number

View file

@ -1,6 +1,6 @@
import { createRun, finishRun } from "../runs.js"
import { createTask } from "../tasks.js"
import { createTaskMetrics } from "../taskMetrics.js"
import { createRun, finishRun } from "../runs"
import { createTask } from "../tasks"
import { createTaskMetrics } from "../taskMetrics"
describe("finishRun", () => {
it("aggregates task metrics, including tool usage", async () => {

View file

@ -1,10 +1,10 @@
import { eq } from "drizzle-orm"
import type { NodePgDatabase } from "drizzle-orm/node-postgres"
import type { InsertRun, InsertTask, InsertTaskMetrics, InsertToolError } from "../schema.js"
import { schema } from "../schema.js"
import type { InsertRun, InsertTask, InsertTaskMetrics, InsertToolError } from "../schema"
import { schema } from "../schema"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors.js"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors"
export const copyRun = async ({
sourceDb,

View file

@ -2,12 +2,12 @@ import { desc, eq, inArray, sql, sum } from "drizzle-orm"
import type { ToolUsage } from "@roo-code/types"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors.js"
import type { InsertRun, UpdateRun } from "../schema.js"
import { schema } from "../schema.js"
import { client as db } from "../db.js"
import { createTaskMetrics } from "./taskMetrics.js"
import { getTasks } from "./tasks.js"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors"
import type { InsertRun, UpdateRun } from "../schema"
import { schema } from "../schema"
import { client as db } from "../db"
import { createTaskMetrics } from "./taskMetrics"
import { getTasks } from "./tasks"
export const findRun = async (id: number) => {
const run = await db.query.runs.findFirst({ where: eq(schema.runs.id, id) })

View file

@ -1,9 +1,9 @@
import { eq } from "drizzle-orm"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors.js"
import type { InsertTaskMetrics, UpdateTaskMetrics } from "../schema.js"
import { taskMetrics } from "../schema.js"
import { client as db } from "../db.js"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors"
import type { InsertTaskMetrics, UpdateTaskMetrics } from "../schema"
import { taskMetrics } from "../schema"
import { client as db } from "../db"
export const findTaskMetrics = async (id: number) => {
const run = await db.query.taskMetrics.findFirst({ where: eq(taskMetrics.id, id) })

View file

@ -1,11 +1,11 @@
import { and, asc, eq, sql } from "drizzle-orm"
import type { ExerciseLanguage } from "../../exercises/index.js"
import type { ExerciseLanguage } from "../../exercises/index"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors.js"
import type { InsertTask, UpdateTask } from "../schema.js"
import { tasks } from "../schema.js"
import { client as db } from "../db.js"
import { RecordNotFoundError, RecordNotCreatedError } from "./errors"
import type { InsertTask, UpdateTask } from "../schema"
import { tasks } from "../schema"
import { client as db } from "../db"
export const findTask = async (id: number) => {
const run = await db.query.tasks.findFirst({ where: eq(tasks.id, id) })

View file

@ -1,7 +1,7 @@
import { RecordNotCreatedError } from "./errors.js"
import type { InsertToolError } from "../schema.js"
import { toolErrors } from "../schema.js"
import { client as db } from "../db.js"
import { RecordNotCreatedError } from "./errors"
import type { InsertToolError } from "../schema"
import { toolErrors } from "../schema"
import { client as db } from "../db"
export const createToolError = async (args: InsertToolError) => {
const records = await db

View file

@ -3,7 +3,7 @@ import { relations } from "drizzle-orm"
import type { RooCodeSettings, ToolName, ToolUsage } from "@roo-code/types"
import type { ExerciseLanguage } from "../exercises/index.js"
import type { ExerciseLanguage } from "../exercises/index"
/**
* ExecutionMethod

View file

@ -1,2 +1,2 @@
export * from "./db/index.js"
export * from "./exercises/index.js"
export * from "./db"
export * from "./exercises"

View file

@ -1,6 +1,9 @@
{
"extends": "@roo-code/config-typescript/base.json",
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true,
"types": ["vitest/globals"]
},
"include": ["src", "drizzle.config.ts", "vitest-global-setup.ts"],

View file

@ -2,10 +2,12 @@
import {
organizationCloudSettingsSchema,
organizationDefaultSettingsSchema,
organizationFeaturesSchema,
organizationSettingsSchema,
userSettingsConfigSchema,
type OrganizationCloudSettings,
type OrganizationDefaultSettings,
type OrganizationFeatures,
type OrganizationSettings,
type UserSettingsConfig,
@ -481,3 +483,38 @@ describe("userSettingsConfigSchema with llmEnhancedFeaturesEnabled", () => {
expect(result.data?.llmEnhancedFeaturesEnabled).toBe(true)
})
})
describe("organizationDefaultSettingsSchema with disabledTools", () => {
it("should accept disabledTools as an array of valid tool names", () => {
const input: OrganizationDefaultSettings = {
disabledTools: ["execute_command", "browser_action"],
}
const result = organizationDefaultSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.disabledTools).toEqual(["execute_command", "browser_action"])
})
it("should accept empty disabledTools array", () => {
const input: OrganizationDefaultSettings = {
disabledTools: [],
}
const result = organizationDefaultSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.disabledTools).toEqual([])
})
it("should accept omitted disabledTools", () => {
const input: OrganizationDefaultSettings = {}
const result = organizationDefaultSettingsSchema.safeParse(input)
expect(result.success).toBe(true)
expect(result.data?.disabledTools).toBeUndefined()
})
it("should reject invalid tool names in disabledTools", () => {
const input = {
disabledTools: ["not_a_real_tool"],
}
const result = organizationDefaultSettingsSchema.safeParse(input)
expect(result.success).toBe(false)
})
})

View file

@ -102,6 +102,7 @@ export const organizationDefaultSettingsSchema = globalSettingsSchema
terminalShellIntegrationDisabled: true,
terminalShellIntegrationTimeout: true,
terminalZshClearEolMark: true,
disabledTools: true,
})
// Add stronger validations for some fields.
.merge(

View file

@ -13,6 +13,7 @@ import { experimentsSchema } from "./experiment.js"
import { telemetrySettingsSchema } from "./telemetry.js"
import { modeConfigSchema } from "./mode.js"
import { customModePromptsSchema, customSupportPromptsSchema } from "./mode.js"
import { toolNamesSchema } from "./tool.js"
import { languagesSchema } from "./vscode.js"
/**
@ -234,6 +235,12 @@ export const globalSettingsSchema = z.object({
* @default true
*/
showWorktreesInHomeScreen: z.boolean().optional(),
/**
* List of native tool names to globally disable.
* Tools in this list will be excluded from prompt generation and rejected at execution time.
*/
disabledTools: z.array(toolNamesSchema).optional(),
})
export type GlobalSettings = z.infer<typeof globalSettingsSchema>

View file

@ -4,6 +4,7 @@ export type FireworksModelId =
| "accounts/fireworks/models/kimi-k2-instruct"
| "accounts/fireworks/models/kimi-k2-instruct-0905"
| "accounts/fireworks/models/kimi-k2-thinking"
| "accounts/fireworks/models/kimi-k2p5"
| "accounts/fireworks/models/minimax-m2"
| "accounts/fireworks/models/minimax-m2p1"
| "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507"
@ -60,6 +61,17 @@ export const fireworksModels = {
description:
"The kimi-k2-thinking model is a general-purpose agentic reasoning model developed by Moonshot AI. Thanks to its strength in deep reasoning and multi-turn tool use, it can solve even the hardest problems.",
},
"accounts/fireworks/models/kimi-k2p5": {
maxTokens: 16384,
contextWindow: 262144,
supportsImages: true,
supportsPromptCache: true,
inputPrice: 0.6,
outputPrice: 3.0,
cacheReadsPrice: 0.1,
description:
"Kimi K2.5 is Moonshot AI's flagship agentic model and a new SOTA open model. It unifies vision and text, thinking and non-thinking modes, and single-agent and multi-agent execution into one model. Fireworks enables users to control the reasoning behavior and inspect its reasoning history for greater transparency.",
},
"accounts/fireworks/models/minimax-m2": {
maxTokens: 4096,
contextWindow: 204800,

View file

@ -20,6 +20,7 @@ export const toolNames = [
"read_command_output",
"write_to_file",
"apply_diff",
"edit",
"search_and_replace",
"search_replace",
"edit_file",

View file

@ -333,6 +333,7 @@ export type ExtensionState = Pick<
| "maxGitStatusFiles"
| "requestDelaySeconds"
| "showWorktreesInHomeScreen"
| "disabledTools"
> & {
version: string
clineMessages: ClineMessage[]
@ -397,13 +398,20 @@ export type ExtensionState = Pick<
lastShownAnnouncementId?: string
apiModelId?: string
mcpServers?: McpServer[]
hasSystemPromptOverride?: boolean
mdmCompliant?: boolean
remoteControlEnabled: boolean
taskSyncEnabled: boolean
featureRoomoteControlEnabled: boolean
openAiCodexIsAuthenticated?: boolean
debug?: boolean
/**
* Monotonically increasing sequence number for clineMessages state pushes.
* When present, the frontend should only apply clineMessages from a state push
* if its seq is greater than the last applied seq. This prevents stale state
* (captured during async getStateToPostToWebview) from overwriting newer messages.
*/
clineMessagesSeq?: number
}
export interface Command {
@ -636,7 +644,6 @@ export interface WebviewMessage {
source?: "global" | "project"
requestId?: string
ids?: string[]
hasSystemPromptOverride?: boolean
terminalOperation?: "continue" | "abort"
messageTs?: number
restoreCheckpoint?: boolean

1090
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more