Compare commits

...

64 commits

Author SHA1 Message Date
Matt Rubens
b867ec9145
Remove roocode.com web app (#12375)
Some checks failed
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
Code QA Roo Code / check-translations (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy docs to GitHub Pages / build (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
Deploy docs to GitHub Pages / deploy (push) Has been cancelled
2026-05-15 14:04:45 -04:00
Matt Rubens
8b94decaef
Redirect roocode.com to roomote.dev (#12374) 2026-05-15 13:55:24 -04:00
Hannes Rudolph
f49f0ce56a
Release v3.54.0 (#12369) 2026-05-15 11:42:49 -06:00
Matt Rubens
d82583c91b
Update README.md 2026-05-15 13:30:03 -04:00
Matt Rubens
6ae816f244
Remove stale roocode.github.io docs references (#12372) 2026-05-15 13:29:02 -04:00
Matt Rubens
f5cad409a1
Update package.json 2026-05-15 13:22:06 -04:00
Matt Rubens
15542fcbbf
Update docs links to GitHub Pages (#12371) 2026-05-15 13:20:20 -04:00
Matt Rubens
d229002cdd
Update README.md 2026-05-15 13:07:01 -04:00
Matt Rubens
06777a513e
Update README.md 2026-05-15 13:06:24 -04:00
Matt Rubens
5641ccd58d
Fix docs GitHub Pages base URL (#12370) 2026-05-15 13:05:47 -04:00
Bruno Bergher
e921f9d21e
Remove contributor and community references (#12347)
Some checks failed
Code QA Roo Code / check-translations (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy docs to GitHub Pages / build (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
Deploy roocode.com / check-secrets (push) Has been cancelled
Deploy docs to GitHub Pages / deploy (push) Has been cancelled
Deploy roocode.com / deploy (push) Has been cancelled
* Remove contributor and community references

* shutdown notice

* Allow empty web app test suite
2026-05-12 16:33:09 +01:00
Bruno Bergher
28acb6acf2
Add docs app and GitHub Pages deploy (#12344)
* Add docs app and Pages deploy

* Configure knip for docs app
2026-05-12 14:23:21 +01:00
Bruno Bergher
2428199851
Remove corporate extension support links (#12341)
* Remove corporate extension support links

* Remove welcome provider left inset

* Update retired provider sunset message

* Scope Roo retired provider message

* Add final release upgrade announcement

* Localize final release announcement
2026-05-12 14:23:08 +01:00
Matt Rubens
8922418600
Remove Roo Code Cloud and evals (#12328)
Some checks are pending
Code QA Roo Code / check-translations (push) Waiting to run
Code QA Roo Code / knip (push) Waiting to run
Code QA Roo Code / compile (push) Waiting to run
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Waiting to run
Code QA Roo Code / platform-unit-test (windows-latest) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Nightly Publish / publish-nightly (push) Waiting to run
Deploy roocode.com / check-secrets (push) Waiting to run
Deploy roocode.com / deploy (push) Blocked by required conditions
* Remove Roo Code Cloud and evals

* Remove unused onboarding and web helper files

* Update ChatView welcome tests after cloud removal
2026-05-11 22:43:45 -04:00
Matt Rubens
22d845cecb
Remove the MCP marketplace (#12326)
* Remove the MCP marketplace

* Remove unused URL utility
2026-05-11 18:19:08 -04:00
Matt Rubens
ff16c9c297
Remove all telemetry (#12324)
* Remove all telemetry

* Fix webview tests after telemetry removal

* Fix embedder tests after telemetry removal

* Fix tests after telemetry removal
2026-05-11 17:34:58 -04:00
Matt Rubens
3d37e054dd
Remove MDM and organization membership enforcement (#12323) 2026-05-11 15:42:02 -04:00
Bruno Bergher
ad25634905
web: Simplifies the website to be almost strictly about the extension (#12180)
Some checks failed
Code QA Roo Code / check-translations (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
Deploy roocode.com / check-secrets (push) Has been cancelled
Deploy roocode.com / deploy (push) Has been cancelled
* Remove pricing/enterprise and Roo Code for pages

* Remove cloud team and router pages

* Refine homepage hero and CTA sections

* nav

* more footer

* Fix knip by removing orphaned web files
2026-04-24 14:56:42 +01:00
github-actions[bot]
96d6e43643
Changeset version bump (#12172)
Some checks are pending
Code QA Roo Code / platform-unit-test (windows-latest) (push) Waiting to run
Code QA Roo Code / check-translations (push) Waiting to run
Code QA Roo Code / knip (push) Waiting to run
Code QA Roo Code / compile (push) Waiting to run
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Nightly Publish / publish-nightly (push) Waiting to run
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-23 15:26:28 -06:00
Hannes Rudolph
14922f127e
Release v3.53.0 (#12171)
Co-authored-by: Roo Code <roomote@roocode.com>
2026-04-23 15:02:08 -06:00
Hannes Rudolph
142f3fb335
feat(openai-codex): add GPT-5.5 model (#12170) 2026-04-23 13:54:33 -06:00
roomote-v0[bot]
c4547d25c5
feat(web): redesign Roomote announcement banner with violet branding (#12161)
Some checks failed
Code QA Roo Code / check-translations (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
Deploy roocode.com / check-secrets (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
Deploy roocode.com / deploy (push) Has been cancelled
Co-authored-by: Roo Code <roomote@roocode.com>
2026-04-21 11:40:35 -06:00
roomote-v0[bot]
b4f2a242bc
feat(blog): add sunsetting roo code blog post (#12160)
Co-authored-by: Roo Code <roomote@roocode.com>
2026-04-21 11:40:27 -06:00
Chiranjeevisantosh Madugundi
2bb826039b
feat(chat): add previous checkpoint navigation controls and i18n (#12139)
Some checks are pending
Code QA Roo Code / check-translations (push) Waiting to run
Code QA Roo Code / knip (push) Waiting to run
Code QA Roo Code / compile (push) Waiting to run
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Waiting to run
Code QA Roo Code / platform-unit-test (windows-latest) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Nightly Publish / publish-nightly (push) Waiting to run
2026-04-20 16:12:10 -06:00
Chiranjeevisantosh Madugundi
3e202ebf5b
feat(vertex): add Claude Opus 4.7 support (#12135) 2026-04-20 11:42:10 -06:00
Bruno Bergher
cb83656718
Roomote banner (#12119)
Some checks failed
Code QA Roo Code / check-translations (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
Deploy roocode.com / check-secrets (push) Has been cancelled
Deploy roocode.com / deploy (push) Has been cancelled
* Roomote banner

* fix(web): use published @roo-code/types in web-roo-code

---------

Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
2026-04-14 18:48:08 -04:00
github-actions[bot]
8b12f21439
Changeset version bump (#12110)
Some checks are pending
Code QA Roo Code / check-translations (push) Waiting to run
Code QA Roo Code / knip (push) Waiting to run
Code QA Roo Code / compile (push) Waiting to run
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Waiting to run
Code QA Roo Code / platform-unit-test (windows-latest) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Nightly Publish / publish-nightly (push) Waiting to run
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-13 16:57:35 -06:00
Hannes Rudolph
9f251fde70
Release v3.52.1 (#12109) 2026-04-13 16:13:55 -06:00
roomote-v0[bot]
319b5576c7
chore: remove hiring announcement from VS Code extension (#12108)
Co-authored-by: Roo Code <roomote@roocode.com>
2026-04-13 15:57:28 -06:00
roomote-v0[bot]
7adbfec2a4
feat: add correct JSON schema for .roomodes configuration files (#11791)
Some checks failed
Code QA Roo Code / check-translations (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
Deploy roocode.com / check-secrets (push) Has been cancelled
Deploy roocode.com / deploy (push) Has been cancelled
Co-authored-by: Roo Code <roomote@roocode.com>
2026-04-08 16:37:14 -06:00
github-actions[bot]
9cfaf38d8a
Changeset version bump (#12085)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hannes Rudolph <hrudolph@gmail.com>
2026-04-08 15:16:12 -06:00
Ronald
92a1be40df
fix: Qwen Bad Request 400 (#12067) (#12083) 2026-04-08 14:34:45 -06:00
Hannes Rudolph
5b93bc7dc3
Release v3.52.0 (#12082) 2026-04-08 14:33:47 -06:00
Enrico Carlesso
5432fa2689
feat: migrate xAI provider to Responses API with reusable transform utils (#11962)
Co-authored-by: Enrico Carlesso <ecarlesso@twitter.com>
Co-authored-by: Roo Code <roomote@roocode.com>
2026-04-08 11:38:13 -06:00
Ksandr
eafed9705c
Fix/minimax context window and models (#12069) 2026-04-08 08:44:36 -06:00
Kamil Jopek
c3cae397a1
feat: add Poe as an AI provider (#12015)
Some checks failed
Code QA Roo Code / platform-unit-test (ubuntu-latest) (push) Has been cancelled
Code QA Roo Code / platform-unit-test (windows-latest) (push) Has been cancelled
Code QA Roo Code / knip (push) Has been cancelled
Code QA Roo Code / compile (push) Has been cancelled
Code QA Roo Code / check-translations (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Nightly Publish / publish-nightly (push) Has been cancelled
2026-04-05 23:37:29 -04:00
Peter Dave Hello
137d3f4fd8
Add OpenAI GPT-5.4 mini and nano models (#11946) 2026-03-18 22:27:26 -06:00
Enrico Carlesso
08f3a2bb39
feat: add xAI grok-4.20 models and update default (Fixes #11955) (#11956) 2026-03-18 22:25:20 -06:00
github-actions[bot]
44fd975b17
Changeset version bump
changeset version bump

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-07 19:36:55 -07:00
roomote-v0[bot]
4ab1d81f55
Release v3.51.1
chore: add changeset for v3.51.1

Co-authored-by: Roo Code <roomote@roocode.com>
2026-03-07 19:17:54 -07:00
roomote-v0[bot]
7ae9c4efd2
feat: add gpt-5.4 to ChatGPT Plus/Pro (Codex) model catalog (#11876) 2026-03-07 19:00:39 -07:00
cscvenkatmadurai
0892455db2
feat(bedrock): add Cohere Embed v4 model and improve credential handling (Fixes #11823) (#11824)
feat(bedrock): add Cohere Embed v4 model and improve credential handling

- Add cohere.embed-v4:0 (1536-dim) to Bedrock embedding model profiles
- Add v4-specific request format (embedding_types: ["float"]) and response
  parsing (embeddings.float[0]) in BedrockEmbedder
- Replace fromEnv() with fromNodeProviderChain() for default credential
  chain when no AWS profile is specified, supporting SSO, IMDS, ECS, and
  other credential sources with built-in memoization
- Add unit tests for Cohere v4 request/response handling, credential
  provider selection, and v3 regression coverage

Fixes #11823
2026-03-05 18:45:17 -07:00
Niklas Volcz
0e56afc764
Add Gemini 3.1 Pro customtools model to Vertex AI provider (#11857) 2026-03-05 15:21:12 -07:00
github-actions[bot]
5eec588653
Changeset version bump (#11731)
changeset version bump

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-05 15:18:22 -07:00
Hannes Rudolph
58c535319e
Release v3.51.0 (#11870)
chore: add changeset for v3.51.0
2026-03-05 14:58:45 -07:00
Peter Dave Hello
0612739ba1
Add OpenAI GPT-5.3 chat latest and GPT-5.4 model support (#11848) 2026-03-05 14:15:55 -07:00
AJ Juaire
52ce796e42
feat: add ROO_ACTIVE env variable to terminal env settings (#11862) 2026-03-04 17:23:52 -07:00
Chris Estreich
3e237e6061
chore(cli): prepare release v0.1.17 (#11860) 2026-03-04 12:27:57 -08:00
Chris Estreich
0b0b33e6a2
feat(cli): support --create-with-session-id and UUID session validation (#11859)
feat(cli): add create-with-session-id support

rename public task id flag to --create-with-session-id

validate session ids as UUIDs for create/resume and stdin start.taskId

add integration coverage for create+resume loading correct session
2026-03-04 10:32:16 -08:00
Chris Estreich
0db51d8bfa
chore(cli): prepare release v0.1.16 (#11852) 2026-03-03 23:37:56 -08:00
John Richmond
7dc83a522e
Allow selecting a specific shell (#11851)
* Allow selecting a specific shell

Add --terminal-shell CLI flag to specify which shell ExecaTerminalProcess
uses for inline command execution. The shell path is validated at the CLI
layer and passed through the standard settings mechanism (BaseTerminal
static getter/setter), matching how all other CLI terminal settings flow
through the system.

* test(cli): make shell path access test cross-platform
2026-03-03 23:31:34 -08:00
Chris Estreich
9a58f76299
Add CLI integration coverage for stdin stream routing/race invariants (#11846)
Add integration coverage for stdin stream routing and race invariants
2026-03-02 23:11:54 -08:00
Chris Estreich
f9da48f73a
chore(cli): prepare release v0.1.15 (#11845) 2026-03-02 23:05:05 -08:00
Chris Estreich
06afe4206b
Fix CLI follow-up routing after completion asks (#11844)
Fix stdin follow-up routing for completion asks in CLI stream mode
2026-03-02 22:52:39 -08:00
Chris Estreich
02598bc4a5
chore(cli): prepare release v0.1.14 (#11843) 2026-03-02 21:54:26 -08:00
Chris Estreich
d0480360cb
cli: ensure full command output is streamed before done (#11842) 2026-03-02 21:50:18 -08:00
Hannes Rudolph
459f27015d
fix: prevent redundant skill reloading in conversation (#11838) 2026-03-02 16:47:19 -07:00
Hannes Rudolph
d6611f8f69
chore(cli): prepare release v0.1.13 (#11837)
* chore(cli): prepare release v0.1.13

* Update CHANGELOG.md

---------

Co-authored-by: Chris Estreich <cestreich@gmail.com>
2026-03-02 14:50:33 -08:00
Hannes Rudolph
af1e12c76d
feat: expose skills as slash commands with skill fallback execution (#11834)
Co-authored-by: Roo Code <roomote@roocode.com>
2026-03-02 15:10:32 -07:00
Chris Estreich
ce73d05646
Release: v1.115.0 (#11833)
chore: bump version to v1.115.0
2026-03-02 13:35:52 -08:00
Chris Estreich
3c7544c104
chore(cli): prepare release v0.1.12 (#11836) 2026-03-02 13:34:19 -08:00
Chris Estreich
7ea91fa79e
fix(cli): ignore model-provided timeout in CLI runtime (#11835)
In CLI runtime, stdin harnesses expect command lifetime to be governed
solely by commandExecutionTimeout (user setting), not model-provided
background timeouts. Extract resolveAgentTimeoutMs() and return 0 when
ROO_CLI_RUNTIME=1.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:25:31 -08:00
Chris Estreich
941e6de743
chore(cli): prepare release v0.1.11 (#11832) 2026-03-02 12:59:23 -08:00
Chris Estreich
95ea01f9a5
feat(cli): support images in stdin stream commands (#11831)
feat(cli): support images in stdin stream start and message commands

Add optional `images` field (array of base64 data URIs) to the `start` and
`message` CLI stdin stream commands, allowing callers to attach images to
prompts. The images are validated, forwarded through the extension host, and
included in queued messages.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:57:21 -08:00
1888 changed files with 55695 additions and 86015 deletions

View file

@ -1,5 +0,0 @@
---
"roo-cline": patch
---
Add OpenAI's GPT-5.3-Codex model support

View file

@ -1,9 +0,0 @@
---
"roo-cline": patch
---
- Add OpenAI's GPT-5.3-Codex model support (PR #11728 by @PeterDaveHello)
- Warm Roo models on CLI startup for faster initial responses (PR #11722 by @cte)
- Fix spelling/grammar and casing inconsistencies (#11478 by @PeterDaveHello, PR #11485 by @PeterDaveHello)
- Fix: Restore Linear integration page (PR #11725 by @roomote)
- Chore: Prepare CLI release v0.1.1 (PR #11723 by @cte)

15
.changeset/v3.54.0.md Normal file
View file

@ -0,0 +1,15 @@
---
"roo-cline": minor
---
- Remove: Roo Code Cloud and eval infrastructure from the extension, CLI, workflows, and package surfaces so the release is focused on the standalone extension (PR #12328 by @mrubens)
- Remove: All telemetry collection and analytics plumbing across the extension, website, shared types, provider flows, and related tests (PR #12324 by @mrubens)
- Remove: MDM and organization membership enforcement, including host wiring, webview state, user-facing messages, and locale strings (PR #12323 by @mrubens)
- Remove: The MCP marketplace, marketplace services, webview marketplace UI, package contributions, and related localized copy (PR #12326 by @mrubens)
- Update: Extension-facing support, diagnostics, and announcement content for the final Roo Code release, including GitHub help paths and links to Roomote, ZooCode, and Cline (PR #12341 by @brunobergher)
- Add: A cleaned docs app with GitHub Pages deployment support (PR #12344 by @brunobergher)
- Fix: Configure the docs GitHub Pages base URL so deployed assets and canonical paths load correctly under the repository Pages path (PR #12370 by @mrubens)
- Update: Point docs links in the root README, localized READMEs, and web app copy to the current GitHub Pages docs URL (PR #12371 by @mrubens)
- Remove: Stale `roocode.github.io` docs references, including the old CNAME and outdated docs README and robots.txt URLs (PR #12372 by @mrubens)
- Update: The website to focus almost entirely on the Roo Code extension and remove cloud, team, enterprise, provider, pricing, Slack, and Linear product pages (PR #12180 by @brunobergher)
- Remove: Contributor, community, social channel, and tutorial references from README files, docs, website copy, issue templates, and workflows (PR #12347 by @brunobergher)

View file

@ -64,7 +64,7 @@ body:
attributes:
value: |
---
Optional (for contributors): You can stop here if you're just proposing the improvement.
Optional: You can stop here if you're just proposing the improvement.
- type: textarea
id: acceptance-criteria

View file

@ -1,75 +0,0 @@
<!--
Thank you for contributing to Roo Code!
Before submitting your PR, please ensure:
- It's linked to an approved GitHub Issue.
- You've reviewed our [Contributing Guidelines](../CONTRIBUTING.md).
-->
### Related GitHub Issue
<!-- Every PR MUST be linked to an approved issue. -->
Closes: # <!-- Replace with the issue number, e.g., Closes: #123 -->
### Roo Code Task Context (Optional)
<!--
If you used Roo Code to help create this PR, you can share public task links here.
This helps reviewers understand your development process and provides additional context.
Example: https://app.roocode.com/share/task-id
-->
### Description
<!--
Briefly summarize the changes in this PR and how they address the linked issue.
The issue should cover the "what" and "why"; this section should focus on:
- The "how": key implementation details, design choices, or trade-offs made.
- Anything specific reviewers should pay attention to in this PR.
-->
### Test Procedure
<!--
Detail the steps to test your changes. This helps reviewers verify your work.
- How did you test this specific implementation? (e.g., unit tests, manual testing steps)
- How can reviewers reproduce your tests or verify the fix/feature?
- Include relevant testing environment details if applicable.
-->
### Pre-Submission Checklist
<!-- Go through this checklist before marking your PR as ready for review. -->
- [ ] **Issue Linked**: This PR is linked to an approved GitHub Issue (see "Related GitHub Issue" above).
- [ ] **Scope**: My changes are focused on the linked issue (one major feature/fix per PR).
- [ ] **Self-Review**: I have performed a thorough self-review of my code.
- [ ] **Testing**: New and/or updated tests have been added to cover my changes (if applicable).
- [ ] **Documentation Impact**: I have considered if my changes require documentation updates (see "Documentation Updates" section below).
- [ ] **Contribution Guidelines**: I have read and agree to the [Contributor Guidelines](/CONTRIBUTING.md).
### Screenshots / Videos
<!--
For UI changes, please provide before-and-after screenshots or a short video of the *actual results*.
This greatly helps in understanding the visual impact of your changes.
-->
### Documentation Updates
<!--
Does this PR necessitate updates to user-facing documentation?
- [ ] No documentation updates are required.
- [ ] Yes, documentation updates are required. (Please describe what needs to be updated or link to a PR in the docs repository).
-->
### Additional Notes
<!-- Add any other context, questions, or information for reviewers here. -->
### Get in Touch
<!--
Please provide your Discord username for reviewers or maintainers to reach you if they have questions about your PR
-->

55
.github/workflows/docs-pages.yml vendored Normal file
View file

@ -0,0 +1,55 @@
name: Deploy docs to GitHub Pages
on:
push:
branches:
- main
paths:
- "apps/docs/**"
- ".github/workflows/docs-pages.yml"
- ".github/actions/setup-node-pnpm/**"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
workflow_dispatch:
concurrency:
group: docs-pages
cancel-in-progress: true
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
with:
install-args: "--frozen-lockfile"
- name: Run type check
run: pnpm --filter @roo-code/docs check-types
- name: Run lint
run: pnpm --filter @roo-code/docs lint
- name: Build docs
run: pnpm --filter @roo-code/docs build
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: apps/docs/build
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View file

@ -1,74 +0,0 @@
name: Evals
on:
pull_request:
types: [labeled]
workflow_dispatch:
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
jobs:
evals:
# Run if triggered manually or if PR has 'evals' label.
if: github.event_name == 'workflow_dispatch' || contains(github.event.label.name, 'evals')
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 45
defaults:
run:
working-directory: packages/evals
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create environment
run: |
cat > .env.local << EOF
OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY || 'test-key-for-build' }}
EOF
cat > .env.development << EOF
NODE_ENV=development
DATABASE_URL=postgresql://postgres:password@db:5432/evals_development
REDIS_URL=redis://redis:6379
HOST_EXECUTION_METHOD=docker
EOF
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
file: packages/evals/Dockerfile.runner
tags: evals-runner:latest
cache-from: type=gha
cache-to: type=gha,mode=max
push: false
load: true
- name: Tag image
run: docker tag evals-runner:latest evals-runner
- name: Start containers
run: |
docker compose up -d db redis
timeout 60 bash -c 'until docker compose exec -T db pg_isready -U postgres; do sleep 2; done'
timeout 60 bash -c 'until docker compose exec -T redis redis-cli ping | grep -q PONG; do sleep 2; done'
docker compose run --rm runner sh -c 'nc -z db 5432 && echo "✓ Runner -> Database connection successful"'
docker compose run --rm runner sh -c 'nc -z redis 6379 && echo "✓ Runner -> Redis connection successful"'
docker compose run --rm runner docker ps
- name: Run database migrations
run: docker compose run --rm runner pnpm --filter @roo-code/evals db:migrate
- name: Run evals
run: docker compose run --rm runner pnpm --filter @roo-code/evals cli --ci
- name: Cleanup
if: always()
run: docker compose down -v --remove-orphans

View file

@ -1,67 +0,0 @@
name: Update Contributors # Refresh contrib.rocks image cache
on:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
refresh-contrib-cache:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Bump cacheBust in all README files
run: |
set -euo pipefail
TS="$(date +%s)"
# Target only the root README.md and localized READMEs under locales/*/README.md
mapfile -t FILES < <(git ls-files README.md 'locales/*/README.md' || true)
if [ "${#FILES[@]}" -eq 0 ]; then
echo "No target README files found." >&2
exit 1
fi
UPDATED=0
for f in "${FILES[@]}"; do
if grep -q 'cacheBust=' "$f"; then
# Use portable sed in GNU environment of ubuntu-latest
sed -i -E "s/cacheBust=[0-9]+/cacheBust=${TS}/g" "$f"
echo "Updated cacheBust in $f"
UPDATED=1
else
echo "Warning: cacheBust parameter not found in $f" >&2
fi
done
if [ "$UPDATED" -eq 0 ]; then
echo "No files were updated. Ensure READMEs embed contrib.rocks with cacheBust param." >&2
exit 1
fi
- name: Detect changes
id: changes
run: |
if git diff --quiet; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
- name: Create Pull Request
if: steps.changes.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "docs: update contributors list [skip ci]"
committer: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
branch: refresh-contrib-cache
delete-branch: true
title: "Refresh contrib.rocks image cache (all READMEs)"
body: |
Automated refresh of the contrib.rocks image cache by bumping the cacheBust parameter in README.md and locales/*/README.md.
base: main

View file

@ -1,59 +0,0 @@
name: Deploy roocode.com
on:
push:
branches:
- main
paths:
- 'apps/web-roo-code/**'
workflow_dispatch:
concurrency:
group: deploy-roocode-com
cancel-in-progress: true
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
check-secrets:
runs-on: ubuntu-latest
outputs:
has-vercel-token: ${{ steps.check.outputs.has-vercel-token }}
steps:
- name: Check if VERCEL_TOKEN exists
id: check
run: |
if [ -n "${{ secrets.VERCEL_TOKEN }}" ]; then
echo "has-vercel-token=true" >> $GITHUB_OUTPUT
else
echo "has-vercel-token=false" >> $GITHUB_OUTPUT
fi
deploy:
runs-on: ubuntu-latest
needs: check-secrets
if: ${{ needs.check-secrets.outputs.has-vercel-token == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Run lint
run: pnpm lint
working-directory: apps/web-roo-code
- name: Run type check
run: pnpm check-types
working-directory: apps/web-roo-code
- name: Run build
run: pnpm build
working-directory: apps/web-roo-code
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment Information
run: npx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: npx vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
run: npx vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}

View file

@ -1,102 +0,0 @@
name: Preview roocode.com
on:
push:
branches-ignore:
- main
paths:
- "apps/web-roo-code/**"
pull_request:
paths:
- "apps/web-roo-code/**"
workflow_dispatch:
concurrency:
group: preview-roocode-com-${{ github.ref }}
cancel-in-progress: true
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
check-secrets:
runs-on: ubuntu-latest
outputs:
has-vercel-token: ${{ steps.check.outputs.has-vercel-token }}
steps:
- name: Check if VERCEL_TOKEN exists
id: check
run: |
if [ -n "${{ secrets.VERCEL_TOKEN }}" ]; then
echo "has-vercel-token=true" >> $GITHUB_OUTPUT
else
echo "has-vercel-token=false" >> $GITHUB_OUTPUT
fi
preview:
runs-on: ubuntu-latest
needs: check-secrets
if: ${{ needs.check-secrets.outputs.has-vercel-token == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Run lint
run: pnpm lint
working-directory: apps/web-roo-code
- name: Run type check
run: pnpm check-types
working-directory: apps/web-roo-code
- name: Run build
run: pnpm build
working-directory: apps/web-roo-code
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment Information
run: npx vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project Artifacts
run: npx vercel build --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
id: deploy
run: |
DEPLOYMENT_URL=$(npx vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
echo "deployment_url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT
echo "Preview deployed to: $DEPLOYMENT_URL"
- name: Comment PR with preview link
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const deploymentUrl = '${{ steps.deploy.outputs.deployment_url }}';
const commentIdentifier = '<!-- roo-preview-comment -->';
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existingComment = comments.find(comment =>
comment.body.includes(commentIdentifier)
);
const comment = commentIdentifier + '\n🚀 **Preview deployed!**\n\nYour changes have been deployed to Vercel:\n\n**Preview URL:** ' + deploymentUrl + '\n\nThis preview will be updated automatically when you push new commits to this PR.';
if (existingComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: comment
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}

View file

@ -1,5 +1,110 @@
# Roo Code Changelog
## 3.53.0
### Minor Changes
- **The Roo Code plugin is not going away.** You may have seen the [recent announcement](https://x.com/mattrubens/status/2046636598859559114) that Roo Code hit 3 million installs and the original team is going all-in on Roomote. We know that news was hard for a lot of you. This plugin means a lot to us and to you, and we hear you. The good news: a community team has stepped up to carry Roo Code forward, and we're working with them on an official handoff so the plugin you rely on keeps getting maintained and improved.
- Add GPT-5.5 support via the OpenAI Codex provider (PR #12170 by @hannesrudolph)
- Add Claude Opus 4.7 support on Vertex AI (#12134 by @saneroen, PR #12135 by @saneroen)
- Add previous checkpoint navigation controls and i18n in chat (#12138 by @saneroen, PR #12139 by @saneroen)
- Add Roomote banner (PR #12119 by @brunobergher)
- Redesign Roomote announcement banner with violet branding on the web (PR #12161 by @roomote-v0)
- Add sunsetting Roo Code blog post (PR #12160 by @roomote-v0)
## 3.52.1
### Patch Changes
- Add correct JSON schema for `.roomodes` configuration files (#11790 by @algorhythm85, PR #11791 by @app/roomote-v0)
- Remove the hiring announcement from the VS Code extension UI (PR #12108 by @app/roomote-v0)
## 3.52.0
### Minor Changes
- Add Poe as an AI provider so users can access Poe models directly in Roo Code (PR #12015 by @kamilio)
- Improve the xAI provider by migrating it to the Responses API with reusable transform utilities (#11961 by @carlesso, PR #11962 by @carlesso)
- Fix MiniMax model listings and context window handling for more reliable configuration (#11999 by @Rexarrior, PR #12069 by @Rexarrior)
- Add xAI Grok-4.20 models and update the default xAI model selection (#11955 by @carlesso, PR #11956 by @carlesso)
- Add OpenAI GPT-5.4 mini and nano models to expand the available OpenAI model lineup (PR #11946 by @PeterDaveHello)
- Chore: include the automated version bump PR from the previous release cycle for complete release accounting (PR #11892 by @app/github-actions)
### Patch Changes
- Add support for OpenAI `gpt-5.4-mini` and `gpt-5.4-nano` models.
## 3.51.1
### Patch Changes
- Feat: Add Cohere Embed v4 model support for Bedrock and improve credential handling (#11823 by @cscvenkatmadurai, PR #11824 by @cscvenkatmadurai)
- Feat: Add Gemini 3.1 Pro customtools model to Vertex AI provider (PR #11857 by @NVolcz)
- Feat: Add gpt-5.4 to ChatGPT Plus/Pro (Codex) model catalog (PR #11876 by @roomote-v0)
## 3.51.0
### Minor Changes
- Add OpenAI GPT-5.4 and GPT-5.3 Chat Latest model support so Roo Code can use the newest OpenAI chat models (PR #11848 by @PeterDaveHello)
- Add support for exposing skills as slash commands with skill fallback execution for faster workflows (PR #11834 by @hannesrudolph)
- Add CLI support for `--create-with-session-id` plus UUID session validation for more controlled session creation (PR #11859 by @cte)
- Add support for choosing a specific shell when running terminal commands (PR #11851 by @jr)
- Feature: Add the `ROO_ACTIVE` environment variable to terminal session settings for safer terminal guardrails (#11864 by @ajjuaire, PR #11862 by @ajjuaire)
- Improve cloud settings freshness by updating the refresh interval to one hour (PR #11749 by @roomote-v0)
- Add CLI session resume/history support plus an upgrade command for better long-running workflows (PR #11768 by @cte)
- Add support for images in CLI stdin stream commands (PR #11831 by @cte)
- Include `exitCode` in CLI command `tool_result` events for more reliable automation (PR #11820 by @cte)
- Add CLI types to improve development ergonomics and type safety (PR #11781 by @cte)
- Add CLI integration coverage for stdin stream routing and race-condition invariants (PR #11846 by @cte)
- Fix the CLI stdin-stream cancel race and add an integration test suite to prevent regressions (PR #11817 by @cte)
- Improve CLI stream recovery and add a configurable consecutive mistake limit (PR #11775 by @cte)
- Fix CLI streaming deltas, task ID propagation, cancel recovery, and other runtime edge cases (PR #11736 by @cte)
- Fix CLI task resumption so paused work can reliably continue (PR #11739 by @cte)
- Recover from unhandled exceptions in the CLI instead of failing hard (PR #11750 by @cte)
- Scope CLI session and resume flags to the current workspace to avoid cross-workspace confusion (PR #11774 by @cte)
- Fix stdin prompt streaming to forward task configuration correctly (PR #11778 by @daniel-lxs)
- Handle stdin-stream control-flow errors gracefully in the CLI runtime (PR #11811 by @cte)
- Fix stdin stream queued messages and command output streaming in the CLI (PR #11814 by @cte)
- Increase the CLI command execution timeout for long-running commands (PR #11815 by @cte)
- Fix knip checks to keep repository validation green (PR #11819 by @cte)
- Fix CLI upgrade version detection so upgrades resolve the correct target version (PR #11829 by @cte)
- Ignore model-provided timeout values in the CLI runtime to keep command handling consistent (PR #11835 by @cte)
- Fix redundant skill reloading during conversations to reduce duplicate work (PR #11838 by @hannesrudolph)
- Ensure full command output is streamed before the CLI reports completion (PR #11842 by @cte)
- Fix CLI follow-up routing after completion prompts so next actions land in the right place (PR #11844 by @cte)
- Remove the Netflix logo from the homepage (PR #11787 by @roomote-v0)
- Chore: Prepare CLI release v0.1.2 (PR #11737 by @cte)
- Chore: Prepare CLI release v0.1.3 (PR #11740 by @cte)
- Chore: Prepare CLI release v0.1.4 (PR #11751 by @cte)
- Chore: Prepare CLI release v0.1.5 (PR #11772 by @cte)
- Chore: Prepare CLI release v0.1.6 (PR #11780 by @cte)
- Release Roo Code v1.113.0 (PR #11782 by @cte)
- Chore: Prepare CLI release v0.1.7 (PR #11812 by @cte)
- Chore: Prepare CLI release v0.1.8 (PR #11816 by @cte)
- Chore: Prepare CLI release v0.1.9 (PR #11818 by @cte)
- Chore: Prepare CLI release v0.1.10 (PR #11821 by @cte)
- Release Roo Code v1.114.0 (PR #11822 by @cte)
- Chore: Prepare CLI release v0.1.11 (PR #11832 by @cte)
- Release Roo Code v1.115.0 (PR #11833 by @cte)
- Chore: Prepare CLI release v0.1.12 (PR #11836 by @cte)
- Chore: Prepare CLI release v0.1.13 (PR #11837 by @hannesrudolph)
- Chore: Prepare CLI release v0.1.14 (PR #11843 by @cte)
- Chore: Prepare CLI release v0.1.15 (PR #11845 by @cte)
- Chore: Prepare CLI release v0.1.16 (PR #11852 by @cte)
- Chore: Prepare CLI release v0.1.17 (PR #11860 by @cte)
### Patch Changes
- Add OpenAI's GPT-5.3-Chat-Latest model support
- Add OpenAI's GPT-5.3-Codex model support
- Add OpenAI's GPT-5.4 model support
- Add OpenAI's GPT-5.3-Codex model support (PR #11728 by @PeterDaveHello)
- Warm Roo models on CLI startup for faster initial responses (PR #11722 by @cte)
- Fix spelling/grammar and casing inconsistencies (#11478 by @PeterDaveHello, PR #11485 by @PeterDaveHello)
- Fix: Restore Linear integration page (PR #11725 by @roomote)
- Chore: Prepare CLI release v0.1.1 (PR #11723 by @cte)
## [3.50.4] - 2026-02-21
- Feat: Add MiniMax M2.5 model support (#11471 by @love8ko, PR #11458 by @roomote)
@ -1169,7 +1274,6 @@
- Reposition Add Image button inside ChatTextArea (thanks @roomote!)
- Bring back a way to temporarily and globally pause auto-approve without losing your toggle state (thanks @brunobergher!)
- Makes text area buttons appear only when there's text (thanks @brunobergher!)
- CONTRIBUTING.md tweaks and issue template rewrite (thanks @hannesrudolph!)
- Bump axios from 1.9.0 to 1.12.0 (thanks @dependabot!)
## [3.28.2] - 2025-09-14
@ -1629,7 +1733,6 @@
- Fix Claude model detection by name for API protocol selection (thanks @daniel-lxs!)
- Move marketplace icon from overflow menu to top navigation
- Optional setting to prevent completion with open todos
- Added YouTube to website footer (thanks @thill2323!)
## [3.23.14] - 2025-07-17
@ -2023,7 +2126,6 @@
- Fix bug with context condensing in Amazon Bedrock
- Fix UTF-8 encoding in ExecaTerminalProcess (thanks @mr-ryan-james!)
- Set sidebar name bugfix (thanks @chrarnoldus!)
- Fix link to CONTRIBUTING.md in feature request template (thanks @cannuri!)
- Add task metadata to Unbound and improve caching logic (thanks @pugazhendhi-m!)
## [3.19.0] - 2025-05-29
@ -2991,7 +3093,6 @@
- Ask and Architect modes can now edit markdown files
- Custom modes can now be restricted to specific file patterns (for example, a technical writer who can only edit markdown files 👋)
- Support for configuring the Bedrock provider with AWS Profiles
- New Roo Code community Discord at https://roocode.com/discord!
## [3.2.8]
@ -3031,8 +3132,6 @@
- Create specialized assistants for any workflow
- Just type "Create a new mode for <X>" or visit the Prompts tab in the top menu to get started
Join us at https://www.reddit.com/r/RooCode to share your custom modes and be part of our next chapter!
## [3.1.7]
- DeepSeek-R1 support (thanks @philipnext!)
@ -3080,12 +3179,8 @@ Join us at https://www.reddit.com/r/RooCode to share your custom modes and be pa
## [3.0.1]
- Fix the reddit link and a small visual glitch in the chat input
## [3.0.0]
- This release adds chat modes! Now you can ask Roo Code questions about system architecture or the codebase without immediately jumping into writing code. You can even assign different API configuration profiles to each mode if you prefer to use different models for thinking vs coding. Would love feedback in the new Roo Code Reddit! https://www.reddit.com/r/RooCode
## [2.2.46]
- Only parse @-mentions in user input (not in files)

View file

@ -1,90 +0,0 @@
<div align="center">
<sub>
<b>English</b> • [Català](locales/ca/CODE_OF_CONDUCT.md) • [Deutsch](locales/de/CODE_OF_CONDUCT.md) • [Español](locales/es/CODE_OF_CONDUCT.md) • [Français](locales/fr/CODE_OF_CONDUCT.md) • [हिंदी](locales/hi/CODE_OF_CONDUCT.md) • [Bahasa Indonesia](locales/id/CODE_OF_CONDUCT.md) • [Italiano](locales/it/CODE_OF_CONDUCT.md) • [日本語](locales/ja/CODE_OF_CONDUCT.md)
</sub>
<sub>
[한국어](locales/ko/CODE_OF_CONDUCT.md) • [Nederlands](locales/nl/CODE_OF_CONDUCT.md) • [Polski](locales/pl/CODE_OF_CONDUCT.md) • [Português (BR)](locales/pt-BR/CODE_OF_CONDUCT.md) • [Русский](locales/ru/CODE_OF_CONDUCT.md) • [Türkçe](locales/tr/CODE_OF_CONDUCT.md) • [Tiếng Việt](locales/vi/CODE_OF_CONDUCT.md) • [简体中文](locales/zh-CN/CODE_OF_CONDUCT.md) • [繁體中文](locales/zh-TW/CODE_OF_CONDUCT.md)
</sub>
</div>
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at support@roocode.com. All complaints
will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from [Cline's version][cline_coc] of the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[cline_coc]: https://github.com/cline/cline/blob/main/CODE_OF_CONDUCT.md
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View file

@ -1,141 +0,0 @@
<div align="center">
<sub>
<b>English</b> • [Català](locales/ca/CONTRIBUTING.md) • [Deutsch](locales/de/CONTRIBUTING.md) • [Español](locales/es/CONTRIBUTING.md) • [Français](locales/fr/CONTRIBUTING.md) • [हिंदी](locales/hi/CONTRIBUTING.md) • [Bahasa Indonesia](locales/id/CONTRIBUTING.md) • [Italiano](locales/it/CONTRIBUTING.md) • [日本語](locales/ja/CONTRIBUTING.md)
</sub>
<sub>
[한국어](locales/ko/CONTRIBUTING.md) • [Nederlands](locales/nl/CONTRIBUTING.md) • [Polski](locales/pl/CONTRIBUTING.md) • [Português (BR)](locales/pt-BR/CONTRIBUTING.md) • [Русский](locales/ru/CONTRIBUTING.md) • [Türkçe](locales/tr/CONTRIBUTING.md) • [Tiếng Việt](locales/vi/CONTRIBUTING.md) • [简体中文](locales/zh-CN/CONTRIBUTING.md) • [繁體中文](locales/zh-TW/CONTRIBUTING.md)
</sub>
</div>
# Contributing to Roo Code
Roo Code is a community-driven project, and we deeply value every contribution. To streamline collaboration, we operate on an [Issue-First](#issue-first-approach) basis, meaning all [Pull Requests (PRs)](#submitting-a-pull-request) must first be linked to a GitHub Issue. Please review this guide carefully.
## Table of Contents
- [Before You Contribute](#before-you-contribute)
- [Finding & Planning Your Contribution](#finding--planning-your-contribution)
- [Development & Submission Process](#development--submission-process)
- [Legal](#legal)
## Before You Contribute
### 1. Code of Conduct
All contributors must adhere to our [Code of Conduct](./CODE_OF_CONDUCT.md).
### 2. Project Roadmap
Our roadmap guides the project's direction. Align your contributions with these key goals:
### Reliability First
- Ensure diff editing and command execution are consistently reliable.
- Reduce friction points that deter regular usage.
- Guarantee smooth operation across all locales and platforms.
- Expand robust support for a wide variety of AI providers and models.
### Enhanced User Experience
- Streamline the UI/UX for clarity and intuitiveness.
- Continuously improve the workflow to meet the high expectations developers have for daily-use tools.
### Leading on Agent Performance
- Establish comprehensive evaluation benchmarks (evals) to measure real-world productivity.
- Make it easy for everyone to easily run and interpret these evals.
- Ship improvements that demonstrate clear increases in eval scores.
Mention alignment with these areas in your PRs.
### 3. Join the Roo Code Community
- **Primary:** Join our [Discord](https://discord.gg/roocode) and DM **Hannes Rudolph (`hrudolph`)**.
- **Alternative:** Experienced contributors can engage directly via [GitHub Projects](https://github.com/orgs/RooCodeInc/projects/1).
## Finding & Planning Your Contribution
### Types of Contributions
- **Bug Fixes:** Addressing code issues.
- **New Features:** Adding functionality.
- **Documentation:** Improving guides and clarity.
### Issue-First Approach
All contributions start with a GitHub Issue using our skinny templates.
- **Check existing issues**: Search [GitHub Issues](https://github.com/RooCodeInc/Roo-Code/issues).
- **Create an issue** using:
- **Enhancements:** "Enhancement Request" template (plain language focused on user benefit).
- **Bugs:** "Bug Report" template (minimal repro + expected vs actual + version).
- **Want to work on it?** Comment "Claiming" on the issue and DM **Hannes Rudolph (`hrudolph`)** on [Discord](https://discord.gg/roocode) to get assigned. Assignment will be confirmed in the thread.
- **PRs must link to the issue.** Unlinked PRs may be closed.
### Deciding What to Work On
- Check the [GitHub Project](https://github.com/orgs/RooCodeInc/projects/1) for "Issue [Unassigned]" issues.
- For docs, visit [Roo Code Docs](https://github.com/RooCodeInc/Roo-Code-Docs).
### Reporting Bugs
- Check for existing reports first.
- Create a new bug using the ["Bug Report" template](https://github.com/RooCodeInc/Roo-Code/issues/new/choose) with:
- Clear, numbered reproduction steps
- Expected vs actual result
- Roo Code version (required); API provider/model if relevant
- **Security issues**: Report privately via [security advisories](https://github.com/RooCodeInc/Roo-Code/security/advisories/new).
## Development & Submission Process
### Development Setup
1. **Fork & Clone:**
```
git clone https://github.com/YOUR_USERNAME/Roo-Code.git
```
2. **Install Dependencies:**
```
pnpm install
```
3. **Debugging:** Open with VS Code (`F5`).
### Writing Code Guidelines
- One focused PR per feature or fix.
- Follow ESLint and TypeScript best practices.
- Write clear, descriptive commits referencing issues (e.g., `Fixes #123`).
- Provide thorough testing (`npm test`).
- Rebase onto the latest `main` branch before submission.
### Submitting a Pull Request
- Begin as a **Draft PR** if seeking early feedback.
- Clearly describe your changes following the Pull Request Template.
- Link the issue in the PR description/title (e.g., "Fixes #123").
- Provide screenshots/videos for UI changes.
- Indicate if documentation updates are necessary.
### Pull Request Policy
- Must reference an assigned GitHub Issue. To get assigned: comment "Claiming" on the issue and DM **Hannes Rudolph (`hrudolph`)** on [Discord](https://discord.gg/roocode). Assignment will be confirmed in the thread.
- Unlinked PRs may be closed.
- PRs should pass CI tests, align with the roadmap, and have clear documentation.
### Review Process
- **Daily Triage:** Quick checks by maintainers.
- **Weekly In-depth Review:** Comprehensive assessment.
- **Iterate promptly** based on feedback.
## Legal
By contributing, you agree your contributions will be licensed under the Apache 2.0 License, consistent with Roo Code's licensing.

View file

@ -6,12 +6,11 @@ Roo Code respects your privacy and is committed to transparency about how we han
### **Where Your Data Goes (And Where It Doesnt)**
- **Code & Files**: Roo Code accesses files on your local machine when needed for AI-assisted features. When you send commands to Roo Code, relevant files may be transmitted to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. If you select Roo Code Cloud as the model provider (proxy mode), your code may transit Roo Code servers only to forward it to the upstream provider. We do not store your code; it is deleted immediately after forwarding. Otherwise, your code is sent directly to the provider. AI providers may store data per their privacy policies.
- **Code & Files**: Roo Code accesses files on your local machine when needed for AI-assisted features. When you send commands to Roo Code, relevant files may be transmitted to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. AI providers may store data per their privacy policies.
- **Commands**: Any commands executed through Roo Code happen on your local environment. However, when you use AI-powered features, the relevant code and context from your commands may be transmitted to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not have access to or store this data, but AI providers may process it per their privacy policies.
- **Prompts & AI Requests**: When you use AI-powered features, your prompts and relevant project context are sent to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not store or process this data. These AI providers have their own privacy policies and may store data per their terms of service. If you choose Roo Code Cloud as the provider (proxy mode), prompts may transit Roo Code servers only to forward them to the upstream model and are not stored.
- **Prompts & AI Requests**: When you use AI-powered features, your prompts and relevant project context are sent to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not store or process this data. These AI providers have their own privacy policies and may store data per their terms of service.
- **API Keys & Credentials**: If you enter an API key (e.g., to connect an AI model), it is stored locally on your device and never sent to us or any third party, except the provider you have chosen.
- **Telemetry (Usage Data)**: We collect anonymous feature usage and error data to help us improve Roo Code. This telemetry is powered by PostHog and includes your VS Code machine ID, feature usage patterns, and exception reports. This telemetry does **not** collect personally identifiable information, your code, or AI prompts. You can opt out of this telemetry at any time through the settings.
- **Marketplace Requests**: When you browse or search the Marketplace for Model Configuration Profiles (MCPs) or Custom Modes, Roo Code makes a secure API call to Roo Code's backend servers to retrieve listing information. These requests send only the query parameters (e.g., extension version, search term) necessary to fulfill the request and do not include your code, prompts, or personally identifiable information.
### **How We Use Your Data (If Collected)**

116
README.md
View file

@ -1,12 +1,5 @@
<p align="center">
<a href="https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline"><img src="https://img.shields.io/badge/VS_Code_Marketplace-007ACC?style=flat&logo=visualstudiocode&logoColor=white" alt="VS Code Marketplace"></a>
<a href="https://x.com/roocode"><img src="https://img.shields.io/badge/roocode-000000?style=flat&logo=x&logoColor=white" alt="X"></a>
<a href="https://youtube.com/@roocodeyt?feature=shared"><img src="https://img.shields.io/badge/YouTube-FF0000?style=flat&logo=youtube&logoColor=white" alt="YouTube"></a>
<a href="https://discord.gg/roocode"><img src="https://img.shields.io/badge/Join%20Discord-5865F2?style=flat&logo=discord&logoColor=white" alt="Join Discord"></a>
<a href="https://www.reddit.com/r/RooCode/"><img src="https://img.shields.io/badge/Join%20r%2FRooCode-FF4500?style=flat&logo=reddit&logoColor=white" alt="Join r/RooCode"></a>
</p>
<p align="center">
<em>Get help fast → <a href="https://discord.gg/roocode">Join Discord</a> • Prefer async? → <a href="https://www.reddit.com/r/RooCode/">Join r/RooCode</a></em>
<a href="https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline"><img src="https://img.shields.io/badge/VS_Code_Marketplace-007ACC?style=flat&logo=visualstudiocode&logoColor=white" alt="VS Code Marketplace"></a>
</p>
# Roo Code
@ -59,117 +52,26 @@ Roo Code adapts to how you work:
- Debug Mode: trace issues, add logs, isolate root causes
- Custom Modes: build specialized modes for your team or workflow
Learn more: [Using Modes](https://docs.roocode.com/basic-usage/using-modes) • [Custom Modes](https://docs.roocode.com/advanced-usage/custom-modes)
## Tutorial & Feature Videos
<div align="center">
| | | |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| <a href="https://www.youtube.com/watch?v=Mcq3r1EPZ-4"><img src="https://img.youtube.com/vi/Mcq3r1EPZ-4/maxresdefault.jpg" width="100%"></a><br><b>Installing Roo Code</b> | <a href="https://www.youtube.com/watch?v=ZBML8h5cCgo"><img src="https://img.youtube.com/vi/ZBML8h5cCgo/maxresdefault.jpg" width="100%"></a><br><b>Configuring Profiles</b> | <a href="https://www.youtube.com/watch?v=r1bpod1VWhg"><img src="https://img.youtube.com/vi/r1bpod1VWhg/maxresdefault.jpg" width="100%"></a><br><b>Codebase Indexing</b> |
| <a href="https://www.youtube.com/watch?v=iiAv1eKOaxk"><img src="https://img.youtube.com/vi/iiAv1eKOaxk/maxresdefault.jpg" width="100%"></a><br><b>Custom Modes</b> | <a href="https://www.youtube.com/watch?v=Ho30nyY332E"><img src="https://img.youtube.com/vi/Ho30nyY332E/maxresdefault.jpg" width="100%"></a><br><b>Checkpoints</b> | <a href="https://www.youtube.com/watch?v=HmnNSasv7T8"><img src="https://img.youtube.com/vi/HmnNSasv7T8/maxresdefault.jpg" width="100%"></a><br><b>Context Management</b> |
</div>
<p align="center">
<a href="https://docs.roocode.com/tutorial-videos">More quick tutorial and feature videos...</a>
</p>
Learn more: [Using Modes](https://roocodeinc.github.io/Roo-Code/basic-usage/using-modes) • [Custom Modes](https://roocodeinc.github.io/Roo-Code/advanced-usage/custom-modes)
## Resources
- **[Documentation](https://docs.roocode.com):** The official guide to installing, configuring, and mastering Roo Code.
- **[YouTube Channel](https://youtube.com/@roocodeyt?feature=shared):** Watch tutorials and see features in action.
- **[Discord Server](https://discord.gg/roocode):** Join the community for real-time help and discussion.
- **[Reddit Community](https://www.reddit.com/r/RooCode):** Share your experiences and see what others are building.
- **[Documentation](https://roocodeinc.github.io/Roo-Code/):** The official guide to installing, configuring, and mastering Roo Code.
- **[GitHub Issues](https://github.com/RooCodeInc/Roo-Code/issues):** Report bugs and track development.
- **[Feature Requests](https://github.com/RooCodeInc/Roo-Code/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop):** Have an idea? Share it with the developers.
---
## Local Setup & Development
1. **Clone** the repo:
```sh
git clone https://github.com/RooCodeInc/Roo-Code.git
```
2. **Install dependencies**:
```sh
pnpm install
```
3. **Run the extension**:
There are several ways to run the Roo Code extension:
### Development Mode (F5)
For active development, use VSCode's built-in debugging:
Press `F5` (or go to **Run****Start Debugging**) in VSCode. This will open a new VSCode window with the Roo Code extension running.
- Changes to the webview will appear immediately.
- Changes to the core extension will also hot reload automatically.
### Automated VSIX Installation
To build and install the extension as a VSIX package directly into VSCode:
```sh
pnpm install:vsix [-y] [--editor=<command>]
```
This command will:
- Ask which editor command to use (code/cursor/code-insiders) - defaults to 'code'
- Uninstall any existing version of the extension.
- Build the latest VSIX package.
- Install the newly built VSIX.
- Prompt you to restart VS Code for changes to take effect.
Options:
- `-y`: Skip all confirmation prompts and use defaults
- `--editor=<command>`: Specify the editor command (e.g., `--editor=cursor` or `--editor=code-insiders`)
### Manual VSIX Installation
If you prefer to install the VSIX package manually:
1. First, build the VSIX package:
```sh
pnpm vsix
```
2. A `.vsix` file will be generated in the `bin/` directory (e.g., `bin/roo-cline-<version>.vsix`).
3. Install it manually using the VSCode CLI:
```sh
code --install-extension bin/roo-cline-<version>.vsix
```
---
We use [changesets](https://github.com/changesets/changesets) for versioning and publishing. Check our `CHANGELOG.md` for release notes.
---
## Disclaimer
The Roo Code Extension was shut down on May 15th.
- If you're looking for an alternative, check out [ZooCode](https://github.com/Zoo-Code-Org/Zoo-Code/) (a fork started by the Roo Code community) and [Cline](https://cline.bot/) (from where Roo Code originated).
- If you were a paying user and have billing questions, please write [billing@roocode.com](mailto:billing@roocode.com).
**Please note** that Roo Code, Inc does **not** make any representations or warranties regarding any code, models, or other tools provided or made available in connection with Roo Code, any associated third-party tools, or any resulting outputs. You assume **all risks** associated with the use of any such tools or outputs; such tools are provided on an **"AS IS"** and **"AS AVAILABLE"** basis. Such risks may include, without limitation, intellectual property infringement, cyber vulnerabilities or attacks, bias, inaccuracies, errors, defects, viruses, downtime, property loss or damage, and/or personal injury. You are solely responsible for your use of any such tools or outputs (including, without limitation, the legality, appropriateness, and results thereof).
---
## Contributing
We love community contributions! Get started by reading our [CONTRIBUTING.md](CONTRIBUTING.md).
---
## License
[Apache 2.0 © 2025 Roo Code, Inc.](./LICENSE)
---
**Enjoy Roo Code!** Whether you keep it on a short leash or let it roam autonomously, we cant wait to see what you build. If you have questions or feature ideas, drop by our [Reddit community](https://www.reddit.com/r/RooCode/) or [Discord](https://discord.gg/roocode). Happy coding!
[Apache 2.0 © 2026 Roo Code, Inc.](./LICENSE)

View file

@ -5,6 +5,69 @@ 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.1.17] - 2026-03-04
### Added
- **Custom Session ID Support**: New `--create-with-session-id` flag allows specifying a custom UUID session ID when creating tasks. Session IDs are now validated as UUIDs for both create and resume operations, as well as for `start.taskId` in stdin-stream mode.
### Tests
- Added integration coverage for create+resume loading the correct session.
## [0.1.16] - 2026-03-04
### Added
- **Custom Shell Selection**: New `--terminal-shell` flag to specify which shell to use for inline command execution. The shell path is validated at the CLI layer and passed through the standard settings mechanism.
### Tests
- Added integration coverage for stdin stream routing and race invariants.
## [0.1.15] - 2026-03-03
### Fixed
- **Follow-up Routing for Completion Asks**: Fixed routing of follow-up messages when the agent asks for clarification (ask_followup_question) in stdin-stream mode. Messages sent after a completion ask are now correctly delivered to the agent instead of being queued.
## [0.1.14] - 2026-03-03
### Fixed
- **Command Output Streaming**: Ensure full command output is streamed before the done event is emitted, preventing truncated output in stdin-stream mode.
## [0.1.13] - 2026-03-02
### Added
- **Skills as Slash Commands**: Skills are now exposed as slash commands, so you can invoke skill workflows directly from command-style input.
- **Skill Fallback Execution**: When a slash command does not match a command file but matches a skill slug, the CLI can resolve and execute that skill path.
### Changed
- **Slash Command Resolution Priority**: Command precedence is preserved, with skill fallback only used when no matching slash command is found.
### Tests
- Added and updated tests for slash command + skill fallback behavior, including command precedence and duplicate skill-slug handling.
## [0.1.12] - 2026-03-02
### Fixed
- **Command Timeout Handling**: CLI runtime now correctly ignores model-provided background timeouts for commands, ensuring command lifetime is governed solely by the `--timeout` setting.
## [0.1.11] - 2026-03-02
### Added
- **Image Support in Stdin Stream**: The `start` and `message` commands in stdin-stream mode now support an optional `images` field (array of base64 data URIs) to attach images to prompts.
### Fixed
- **Upgrade Version Detection**: Fixed version detection in the `upgrade` command to correctly identify when updates are available.
## [0.1.10] - 2026-03-02
### Added

View file

@ -53,21 +53,6 @@ roo upgrade
rm -rf ~/.roo/cli ~/.local/bin/roo
```
### Development Installation
For contributing or development:
```bash
# From the monorepo root.
pnpm install
# Build the main extension first.
pnpm --filter roo-cline bundle
# Build the CLI.
pnpm --filter @roo-code/cli build
```
## Usage
### Interactive Mode (Default)
@ -113,90 +98,46 @@ Use `--print` for non-interactive execution and machine-readable output:
```bash
# Prompt is required
roo --print "Summarize this repository"
# Create a new task with a specific session ID (UUID)
roo --print --create-with-session-id 018f7fc8-7c96-7f7c-98aa-2ec4ff7f6d87 "Summarize this repository"
```
### Stdin Stream Mode (`--stdin-prompt-stream`)
For programmatic control (one process, multiple prompts), use `--stdin-prompt-stream` with `--print`.
Send one prompt per line via stdin:
Send NDJSON commands via stdin:
```bash
printf '1+1=?\n10!=?\n' | roo --print --stdin-prompt-stream --output-format stream-json
```
printf '{"command":"start","requestId":"1","prompt":"1+1=?"}\n' | roo --print --stdin-prompt-stream --output-format stream-json
### Roo Code Cloud Authentication
To use Roo Code Cloud features (like the provider proxy), you need to authenticate:
```bash
# Log in to Roo Code Cloud (opens browser)
roo auth login
# Check authentication status
roo auth status
# Log out
roo auth logout
```
The `auth login` command:
1. Opens your browser to authenticate with Roo Code Cloud
2. Receives a secure token via localhost callback
3. Stores the token in `~/.config/roo/credentials.json`
Tokens are valid for 90 days. The CLI will prompt you to re-authenticate when your token expires.
**Authentication Flow:**
```
┌──────┐ ┌─────────┐ ┌───────────────┐
│ CLI │ │ Browser │ │ Roo Code Cloud│
└──┬───┘ └────┬────┘ └───────┬───────┘
│ │ │
│ Open auth URL │ │
│─────────────────>│ │
│ │ │
│ │ Authenticate │
│ │─────────────────────>│
│ │ │
│ │<─────────────────────│
│ │ Token via callback │
<─────────────────│ │
│ │ │
│ Store token │ │
│ │ │
# Optional: provide taskId per start command
printf '{"command":"start","requestId":"1","taskId":"018f7fc8-7c96-7f7c-98aa-2ec4ff7f6d87","prompt":"1+1=?"}\n' | roo --print --stdin-prompt-stream --output-format stream-json
```
## Options
| 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` |
| `--stdin-prompt-stream` | Read prompts from stdin (one prompt per line, requires `--print`) | `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` |
| `--consecutive-mistake-limit <n>` | Consecutive error/repetition limit before guidance prompt (`0` disables the limit) | `10` |
| `--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
| Command | Description |
| ----------------- | ---------------------------------- |
| `roo auth login` | Authenticate with Roo Code Cloud |
| `roo auth logout` | Clear stored authentication token |
| `roo auth status` | Show current authentication status |
| Option | Description | Default |
| --------------------------------------- | --------------------------------------------------------------------------------------- | --------------------------- |
| `[prompt]` | Your prompt (positional argument, optional) | None |
| `--prompt-file <path>` | Read prompt from a file instead of command line argument | None |
| `--create-with-session-id <session-id>` | Create a new task using the provided session ID (UUID) | None |
| `-w, --workspace <path>` | Workspace path to operate in | Current directory |
| `-p, --print` | Print response and exit (non-interactive mode) | `false` |
| `--stdin-prompt-stream` | Read NDJSON control commands from stdin (requires `--print`) | `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 (anthropic, openai, openrouter, etc.) | `openrouter` |
| `-m, --model <model>` | Model to use | `anthropic/claude-opus-4.6` |
| `--mode <mode>` | Mode to start in (code, architect, ask, debug, etc.) | `code` |
| `--terminal-shell <path>` | Absolute shell path for inline terminal command execution | Auto-detected shell |
| `-r, --reasoning-effort <effort>` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` |
| `--consecutive-mistake-limit <n>` | Consecutive error/repetition limit before guidance prompt (`0` disables the limit) | `10` |
| `--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` |
## Environment Variables
@ -204,19 +145,12 @@ The CLI will look for API keys in environment variables if not provided via `--a
| 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:**
| Variable | Description |
| ----------------- | -------------------------------------------------------------------- |
| `ROO_WEB_APP_URL` | Override the Roo Code Cloud URL (default: `https://app.roocode.com`) |
## Architecture
```
@ -260,7 +194,7 @@ The CLI will look for API keys in environment variables if not provided via `--a
```bash
# Run directly from source (no build required)
pnpm dev --provider roo --api-key $ROO_API_KEY --print "Hello"
pnpm dev --provider openrouter --api-key $OPENROUTER_API_KEY --print "Hello"
# Run tests
pnpm test
@ -272,12 +206,6 @@ pnpm check-types
pnpm lint
```
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_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`.

View file

@ -1,6 +1,6 @@
{
"name": "@roo-code/cli",
"version": "0.1.10",
"version": "0.1.17",
"description": "Roo Code CLI - Run the Roo Code agent from the command line",
"private": true,
"type": "module",
@ -16,8 +16,8 @@
"test:integration": "tsx scripts/integration/run.ts",
"build": "tsup",
"build:extension": "pnpm --filter roo-cline bundle",
"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",
"dev": "tsx src/index.ts",
"dev:local": "tsx src/index.ts",
"clean": "rimraf dist .turbo"
},
"dependencies": {

View file

@ -0,0 +1,161 @@
import { runStreamCase, StreamEvent } from "../lib/stream-harness"
const START_PROMPT =
'Run exactly this command and do not summarize until it finishes: sleep 12 && echo "done". After it finishes, reply with exactly "done".'
const FOLLOWUP_PROMPT = 'After cancellation, reply with only "RACE-OK".'
async function main() {
const startRequestId = `start-${Date.now()}`
const cancelRequestId = `cancel-${Date.now()}`
const followupRequestId = `message-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
let initSeen = false
let sentCancelAndFollowup = false
let sentShutdown = false
let cancelDoneCode: string | undefined
let followupDoneCode: string | undefined
let followupResult = ""
let sawFollowupUserTurn = false
let sawMisroutedToolResult = false
let sawMessageControlError = false
await runStreamCase({
onEvent(event: StreamEvent, context) {
if (event.type === "system" && event.subtype === "init" && !initSeen) {
initSeen = true
context.sendCommand({
command: "start",
requestId: startRequestId,
prompt: START_PROMPT,
})
return
}
if (event.type === "control" && event.subtype === "error") {
if (event.requestId === followupRequestId) {
sawMessageControlError = true
}
throw new Error(
`received control error for requestId=${event.requestId ?? "unknown"} command=${event.command ?? "unknown"} code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
}
if (
!sentCancelAndFollowup &&
event.type === "tool_use" &&
event.requestId === startRequestId &&
event.subtype === "command"
) {
context.sendCommand({
command: "cancel",
requestId: cancelRequestId,
})
context.sendCommand({
command: "message",
requestId: followupRequestId,
prompt: FOLLOWUP_PROMPT,
})
sentCancelAndFollowup = true
return
}
if (
event.type === "control" &&
event.command === "cancel" &&
event.subtype === "done" &&
event.requestId === cancelRequestId
) {
cancelDoneCode = event.code
return
}
if (
event.type === "control" &&
event.command === "message" &&
event.subtype === "done" &&
event.requestId === followupRequestId
) {
followupDoneCode = event.code
return
}
if (
event.type === "tool_result" &&
event.requestId === followupRequestId &&
typeof event.content === "string" &&
event.content.includes("<user_message>")
) {
sawMisroutedToolResult = true
return
}
if (event.type === "user" && event.requestId === followupRequestId) {
sawFollowupUserTurn = typeof event.content === "string" && event.content.includes("RACE-OK")
return
}
if (event.type !== "result" || event.done !== true || event.requestId !== followupRequestId) {
return
}
followupResult = event.content ?? ""
if (followupResult.trim().length === 0) {
throw new Error("follow-up after cancel produced an empty result")
}
if (cancelDoneCode !== "cancel_requested") {
throw new Error(
`cancel done code mismatch; expected cancel_requested, got "${cancelDoneCode ?? "none"}"`,
)
}
if (followupDoneCode !== "responded" && followupDoneCode !== "queued") {
throw new Error(
`unexpected follow-up done code after cancel race; expected responded|queued, got "${followupDoneCode ?? "none"}"`,
)
}
if (sawMessageControlError) {
throw new Error("follow-up message emitted control error in cancel recovery race")
}
if (sawMisroutedToolResult) {
throw new Error(
"follow-up message was misrouted into tool_result (<user_message>) in cancel recovery race",
)
}
if (!sawFollowupUserTurn) {
throw new Error("follow-up after cancel did not appear as a normal user turn")
}
console.log(`[PASS] cancel done code: "${cancelDoneCode}"`)
console.log(`[PASS] follow-up done code: "${followupDoneCode}"`)
console.log(`[PASS] follow-up user turn observed: ${sawFollowupUserTurn}`)
console.log(`[PASS] follow-up result: "${followupResult}"`)
if (!sentShutdown) {
context.sendCommand({
command: "shutdown",
requestId: shutdownRequestId,
})
sentShutdown = true
}
},
onTimeoutMessage() {
return [
"timed out waiting for cancel-message-recovery-race validation",
`initSeen=${initSeen}`,
`sentCancelAndFollowup=${sentCancelAndFollowup}`,
`cancelDoneCode=${cancelDoneCode ?? "none"}`,
`followupDoneCode=${followupDoneCode ?? "none"}`,
`sawFollowupUserTurn=${sawFollowupUserTurn}`,
`sawMisroutedToolResult=${sawMisroutedToolResult}`,
`sawMessageControlError=${sawMessageControlError}`,
`haveFollowupResult=${Boolean(followupResult)}`,
].join(" ")
},
})
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -0,0 +1,73 @@
import { runStreamCase, StreamEvent } from "../lib/stream-harness"
async function main() {
const cancelRequestId = `cancel-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
let initSeen = false
let cancelAckSeen = false
let cancelDoneSeen = false
let shutdownSent = false
await runStreamCase({
onEvent(event: StreamEvent, context) {
if (event.type === "system" && event.subtype === "init" && !initSeen) {
initSeen = true
context.sendCommand({
command: "cancel",
requestId: cancelRequestId,
})
return
}
if (
event.type === "control" &&
event.subtype === "ack" &&
event.command === "cancel" &&
event.requestId === cancelRequestId
) {
cancelAckSeen = true
return
}
if (
event.type === "control" &&
event.subtype === "done" &&
event.command === "cancel" &&
event.requestId === cancelRequestId
) {
cancelDoneSeen = true
if (event.code !== "no_active_task") {
throw new Error(`cancel without task should return no_active_task, got "${event.code ?? "none"}"`)
}
if (event.success !== true) {
throw new Error("cancel without task should be treated as successful no-op")
}
if (!shutdownSent) {
context.sendCommand({
command: "shutdown",
requestId: shutdownRequestId,
})
shutdownSent = true
}
return
}
if (event.type === "control" && event.subtype === "error") {
throw new Error(
`unexpected control error command=${event.command ?? "unknown"} code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
}
},
onTimeoutMessage() {
return `timed out waiting for cancel-without-active-task validation (initSeen=${initSeen}, cancelAckSeen=${cancelAckSeen}, cancelDoneSeen=${cancelDoneSeen}, shutdownSent=${shutdownSent})`
},
})
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -0,0 +1,364 @@
import fs from "fs/promises"
import os from "os"
import path from "path"
import readline from "readline"
import { fileURLToPath } from "url"
import { randomUUID } from "crypto"
import { execa } from "execa"
import type { TaskSessionEntry } from "@roo-code/core/cli"
type StreamEvent = {
type?: string
subtype?: string
requestId?: string
command?: string
taskId?: string
content?: string
code?: string
success?: boolean
done?: boolean
}
const RESUME_TIMEOUT_MS = 180_000
const __dirname = path.dirname(fileURLToPath(import.meta.url))
function parseStreamEvent(line: string): StreamEvent | null {
const trimmed = line.trim()
if (!trimmed.startsWith("{")) {
return null
}
try {
return JSON.parse(trimmed) as StreamEvent
} catch {
return null
}
}
async function listSessions(cliRoot: string, workspacePath: string): Promise<TaskSessionEntry[]> {
const result = await execa("pnpm", ["dev", "list", "sessions", "--workspace", workspacePath, "--format", "json"], {
cwd: cliRoot,
reject: false,
})
if (result.exitCode !== 0) {
throw new Error(`list sessions failed with exit code ${result.exitCode}: ${result.stderr || result.stdout}`)
}
const stdoutLines = result.stdout.split("\n")
const jsonStartIndex = stdoutLines.findIndex((line) => line.trim().startsWith("{"))
if (jsonStartIndex === -1) {
throw new Error(`list sessions output did not contain JSON payload: ${result.stdout}`)
}
const jsonPayload = stdoutLines.slice(jsonStartIndex).join("\n").trim()
let parsed: unknown
try {
parsed = JSON.parse(jsonPayload)
} catch (error) {
throw new Error(
`failed to parse list sessions output as JSON: ${error instanceof Error ? error.message : String(error)}`,
)
}
if (
typeof parsed !== "object" ||
parsed === null ||
!("sessions" in parsed) ||
!Array.isArray((parsed as { sessions?: unknown }).sessions)
) {
throw new Error("list sessions output missing sessions array")
}
return (parsed as { sessions: TaskSessionEntry[] }).sessions
}
async function createSessionWithCustomId(
cliRoot: string,
workspacePath: string,
sessionId: string,
prompt: string,
): Promise<void> {
const result = await execa(
"pnpm",
[
"dev",
"--print",
"--provider",
"openrouter",
"--output-format",
"stream-json",
"--workspace",
workspacePath,
"--create-with-session-id",
sessionId,
prompt,
],
{
cwd: cliRoot,
reject: false,
},
)
if (result.exitCode !== 0) {
throw new Error(
`create-with-session-id failed for ${sessionId} with exit code ${result.exitCode}: ${result.stderr || result.stdout}`,
)
}
const lines = result.stdout.split("\n")
const events = lines.map(parseStreamEvent).filter((event): event is StreamEvent => Boolean(event))
const errorEvent = events.find((event) => event.type === "error")
if (errorEvent) {
throw new Error(
`create-with-session-id emitted error for ${sessionId}: code=${errorEvent.code ?? "none"} content=${errorEvent.content ?? ""}`,
)
}
const completion = events.find((event) => event.type === "result" && event.done === true)
if (!completion) {
throw new Error(`create-with-session-id did not emit final result for ${sessionId}`)
}
if (completion.success !== true) {
throw new Error(`create-with-session-id completed unsuccessfully for ${sessionId}`)
}
}
async function resumeSessionAndSendMarker(
cliRoot: string,
workspacePath: string,
sessionId: string,
messageToken: string,
): Promise<void> {
const pingRequestId = `ping-${Date.now()}`
const messageRequestId = `message-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
const messagePrompt = `Resume marker token: ${messageToken}. Reply with exactly "ack-${messageToken}".`
const child = execa(
"pnpm",
[
"dev",
"--print",
"--stdin-prompt-stream",
"--provider",
"openrouter",
"--output-format",
"stream-json",
"--workspace",
workspacePath,
"--session-id",
sessionId,
],
{
cwd: cliRoot,
stdin: "pipe",
stdout: "pipe",
stderr: "pipe",
reject: false,
forceKillAfterDelay: 2_000,
},
)
child.stderr?.on("data", (chunk) => {
process.stderr.write(chunk)
})
let pingSent = false
let messageSent = false
let shutdownSent = false
let sawMessageControlDone = false
let sawUserTurnWithMarker = false
let shutdownTaskId: string | undefined
let handlerError: Error | null = null
let timedOut = false
const sendCommand = (command: { command: "ping" | "message" | "shutdown"; requestId: string; prompt?: string }) => {
if (!child.stdin || child.stdin.destroyed) {
return
}
child.stdin.write(`${JSON.stringify(command)}\n`)
}
const timeout = setTimeout(() => {
timedOut = true
handlerError = new Error(
`timed out resuming session ${sessionId} (pingSent=${pingSent}, messageSent=${messageSent}, sawMessageControlDone=${sawMessageControlDone}, sawUserTurnWithMarker=${sawUserTurnWithMarker})`,
)
child.kill("SIGTERM")
}, RESUME_TIMEOUT_MS)
const rl = readline.createInterface({
input: child.stdout!,
crlfDelay: Infinity,
})
rl.on("line", (line) => {
process.stdout.write(`${line}\n`)
const event = parseStreamEvent(line)
if (!event) {
return
}
if (event.type === "system" && event.subtype === "init" && !pingSent) {
pingSent = true
sendCommand({ command: "ping", requestId: pingRequestId })
return
}
if (
event.type === "control" &&
event.subtype === "done" &&
event.command === "ping" &&
event.requestId === pingRequestId &&
!messageSent
) {
messageSent = true
sendCommand({
command: "message",
requestId: messageRequestId,
prompt: messagePrompt,
})
return
}
if (
event.type === "control" &&
event.subtype === "error" &&
event.command === "message" &&
event.requestId === messageRequestId
) {
handlerError = new Error(
`message command failed while resuming ${sessionId}: code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
child.kill("SIGTERM")
return
}
if (
event.type === "control" &&
event.subtype === "done" &&
event.command === "message" &&
event.requestId === messageRequestId
) {
sawMessageControlDone = true
return
}
if (event.type === "user" && event.requestId === messageRequestId && event.content?.includes(messageToken)) {
sawUserTurnWithMarker = true
if (!shutdownSent) {
shutdownSent = true
sendCommand({ command: "shutdown", requestId: shutdownRequestId })
}
return
}
if (
event.type === "control" &&
(event.subtype === "ack" || event.subtype === "done") &&
event.command === "shutdown" &&
event.requestId === shutdownRequestId &&
typeof event.taskId === "string"
) {
shutdownTaskId = event.taskId
return
}
if (event.type === "control" && event.subtype === "error" && event.requestId !== shutdownRequestId) {
handlerError = new Error(
`unexpected control error while resuming ${sessionId}: command=${event.command ?? "unknown"} code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
child.kill("SIGTERM")
return
}
})
const result = await child
clearTimeout(timeout)
rl.close()
if (handlerError) {
throw handlerError
}
if (timedOut) {
throw new Error(`stream resume for ${sessionId} timed out`)
}
if (result.exitCode !== 0) {
throw new Error(`stream resume for ${sessionId} exited non-zero: ${result.exitCode}`)
}
if (!sawMessageControlDone) {
throw new Error(`did not observe message control completion while resuming ${sessionId}`)
}
if (!sawUserTurnWithMarker) {
throw new Error(`did not observe resumed user marker turn while resuming ${sessionId}`)
}
if (shutdownTaskId !== sessionId) {
throw new Error(
`shutdown taskId did not match resumed session (expected=${sessionId}, actual=${shutdownTaskId ?? "none"})`,
)
}
}
async function main() {
const cliRoot = process.env.ROO_CLI_ROOT
? path.resolve(process.env.ROO_CLI_ROOT)
: path.resolve(__dirname, "../../..")
const workspacePath = await fs.mkdtemp(path.join(os.tmpdir(), "roo-cli-create-session-id-"))
const firstSessionId = randomUUID()
const secondSessionId = randomUUID()
const firstMarker = `FIRST-MARKER-${Date.now()}`
const secondMarker = `SECOND-MARKER-${Date.now()}`
try {
await createSessionWithCustomId(
cliRoot,
workspacePath,
firstSessionId,
`Create first session marker ${firstMarker}. Reply with exactly "ok-${firstMarker}".`,
)
await createSessionWithCustomId(
cliRoot,
workspacePath,
secondSessionId,
`Create second session marker ${secondMarker}. Reply with exactly "ok-${secondMarker}".`,
)
const initialSessions = await listSessions(cliRoot, workspacePath)
if (!initialSessions.some((session) => session.id === firstSessionId)) {
throw new Error(`session list missing first custom session id ${firstSessionId}`)
}
if (!initialSessions.some((session) => session.id === secondSessionId)) {
throw new Error(`session list missing second custom session id ${secondSessionId}`)
}
const resumeMarkerForFirst = `resume-first-${Date.now()}`
await resumeSessionAndSendMarker(cliRoot, workspacePath, firstSessionId, resumeMarkerForFirst)
const resumeMarkerForSecond = `resume-second-${Date.now()}`
await resumeSessionAndSendMarker(cliRoot, workspacePath, secondSessionId, resumeMarkerForSecond)
console.log(`[PASS] created and resumed custom sessions: ${firstSessionId}, ${secondSessionId}`)
} finally {
await fs.rm(workspacePath, { recursive: true, force: true })
}
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -7,18 +7,9 @@ function parseEventContent(text: string | undefined): string {
return typeof text === "string" ? text : ""
}
function validateFollowupAnswer(text: string): void {
const normalized = text.toLowerCase()
const containsExpected = /\b6\b/.test(normalized) || normalized.includes("six")
const containsOldAnswer = /\b1\+1\b/.test(normalized) || /\b2\b/.test(normalized)
const containsQuestionReference = normalized.includes("3+3")
if (!containsExpected) {
throw new Error(`follow-up result did not answer the follow-up question; result="${text}"`)
}
if (!containsQuestionReference && containsOldAnswer && !containsExpected) {
throw new Error(`follow-up result appears anchored to first question; result="${text}"`)
function validateFollowupResult(text: string): void {
if (text.trim().length === 0) {
throw new Error("follow-up produced an empty result")
}
}
@ -32,6 +23,9 @@ async function main() {
let sentShutdown = false
let firstResult = ""
let followupResult = ""
let followupDoneCode: string | undefined
let sawFollowupUserTurn = false
let sawMisroutedToolResult = false
await runStreamCase({
onEvent(event: StreamEvent, context) {
@ -52,6 +46,31 @@ async function main() {
}
if (event.type !== "result" || event.done !== true) {
if (
event.type === "control" &&
event.requestId === followupRequestId &&
event.command === "message" &&
event.subtype === "done"
) {
followupDoneCode = event.code
return
}
if (
event.type === "tool_result" &&
event.requestId === followupRequestId &&
typeof event.content === "string" &&
event.content.includes("<user_message>")
) {
sawMisroutedToolResult = true
return
}
if (event.type === "user" && event.requestId === followupRequestId) {
sawFollowupUserTurn = typeof event.content === "string" && event.content.includes("3+3")
return
}
return
}
@ -77,7 +96,22 @@ async function main() {
}
followupResult = parseEventContent(event.content)
validateFollowupAnswer(followupResult)
validateFollowupResult(followupResult)
if (followupDoneCode !== "responded") {
throw new Error(
`follow-up message was not routed as ask response; code="${followupDoneCode ?? "none"}"`,
)
}
if (!sawFollowupUserTurn) {
throw new Error("follow-up did not appear as a normal user turn in stream output")
}
if (sawMisroutedToolResult) {
throw new Error("follow-up message was misrouted into tool_result (<user_message>), old bug reproduced")
}
console.log(`[PASS] first result="${firstResult}"`)
console.log(`[PASS] follow-up result="${followupResult}"`)

View file

@ -0,0 +1,136 @@
import { runStreamCase, StreamEvent } from "../lib/stream-harness"
const START_PROMPT = 'Answer this question and finish: What is 1+1? Reply with only "2", then complete the task.'
const FOLLOWUP_PROMPT = 'Different question now: what is 3+3? Reply with only "6".'
const ONE_PIXEL_IMAGE =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Y9R4WQAAAAASUVORK5CYII="
async function main() {
const startRequestId = `start-${Date.now()}`
const followupRequestId = `message-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
let initSeen = false
let sentFollowup = false
let sentShutdown = false
let followupDoneCode: string | undefined
let sawFollowupUserTurn = false
let sawMisroutedToolResult = false
let sawQueueImageMetadata = false
let shutdownDoneSeen = false
await runStreamCase({
onEvent(event: StreamEvent, context) {
if (event.type === "system" && event.subtype === "init" && !initSeen) {
initSeen = true
context.sendCommand({
command: "start",
requestId: startRequestId,
prompt: START_PROMPT,
})
return
}
if (event.type === "control" && event.subtype === "error") {
throw new Error(
`received control error for requestId=${event.requestId ?? "unknown"} command=${event.command ?? "unknown"} code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
}
if (
event.type === "control" &&
event.command === "message" &&
event.subtype === "done" &&
event.requestId === followupRequestId
) {
followupDoneCode = event.code
if (!sentShutdown) {
context.sendCommand({
command: "shutdown",
requestId: shutdownRequestId,
})
sentShutdown = true
}
return
}
if (
event.type === "control" &&
event.command === "shutdown" &&
event.subtype === "done" &&
event.requestId === shutdownRequestId
) {
shutdownDoneSeen = true
if (followupDoneCode !== "responded") {
throw new Error(
`follow-up image message was not routed as ask response; code="${followupDoneCode ?? "none"}"`,
)
}
if (sawQueueImageMetadata) {
throw new Error("follow-up image message was unexpectedly queued (observed queue image metadata)")
}
if (sawMisroutedToolResult) {
throw new Error("follow-up image message was misrouted into tool_result (<user_message>)")
}
console.log(`[PASS] follow-up image control code: "${followupDoneCode}"`)
console.log(`[PASS] follow-up image user turn observed before shutdown: ${sawFollowupUserTurn}`)
return
}
if (
event.type === "queue" &&
Array.isArray(event.queue) &&
event.queue.some((item) => item?.imageCount === 1)
) {
sawQueueImageMetadata = true
return
}
if (
event.type === "tool_result" &&
event.requestId === followupRequestId &&
typeof event.content === "string" &&
event.content.includes("<user_message>")
) {
sawMisroutedToolResult = true
return
}
if (event.type === "user" && event.requestId === followupRequestId) {
sawFollowupUserTurn = typeof event.content === "string" && event.content.includes("3+3")
return
}
if (event.type === "result" && event.done === true && event.requestId === startRequestId && !sentFollowup) {
context.sendCommand({
command: "message",
requestId: followupRequestId,
prompt: FOLLOWUP_PROMPT,
images: [ONE_PIXEL_IMAGE],
})
sentFollowup = true
return
}
},
onTimeoutMessage() {
return [
"timed out waiting for followup-completion-ask-response-images validation",
`initSeen=${initSeen}`,
`sentFollowup=${sentFollowup}`,
`sentShutdown=${sentShutdown}`,
`shutdownDoneSeen=${shutdownDoneSeen}`,
`followupDoneCode=${followupDoneCode ?? "none"}`,
`sawFollowupUserTurn=${sawFollowupUserTurn}`,
`sawMisroutedToolResult=${sawMisroutedToolResult}`,
`sawQueueImageMetadata=${sawQueueImageMetadata}`,
].join(" ")
},
})
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -0,0 +1,153 @@
import { runStreamCase, StreamEvent } from "../lib/stream-harness"
const START_PROMPT = 'Answer this question and finish: What is 1+1? Reply with only "2", then complete the task.'
const FOLLOWUP_PROMPT = 'Different question now: what is 3+3? Reply with only "6".'
async function main() {
const startRequestId = `start-${Date.now()}`
const followupRequestId = `message-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
let initSeen = false
let sentFollowup = false
let sentShutdown = false
let startAckCount = 0
let sawStartControlAfterFollowup = false
let followupDoneCode: string | undefined
let sawFollowupUserTurn = false
let sawMisroutedToolResult = false
let sawQueueEventForFollowupRequest = false
let followupResult = ""
await runStreamCase({
onEvent(event: StreamEvent, context) {
if (event.type === "system" && event.subtype === "init" && !initSeen) {
initSeen = true
context.sendCommand({
command: "start",
requestId: startRequestId,
prompt: START_PROMPT,
})
return
}
if (event.type === "control" && event.subtype === "error") {
throw new Error(
`received control error for requestId=${event.requestId ?? "unknown"} command=${event.command ?? "unknown"} code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
}
if (event.type === "control" && event.command === "start" && event.subtype === "ack") {
startAckCount += 1
if (sentFollowup) {
sawStartControlAfterFollowup = true
}
return
}
if (
event.type === "control" &&
event.command === "message" &&
event.subtype === "done" &&
event.requestId === followupRequestId
) {
followupDoneCode = event.code
return
}
if (event.type === "queue" && event.requestId === followupRequestId) {
sawQueueEventForFollowupRequest = true
return
}
if (
event.type === "tool_result" &&
event.requestId === followupRequestId &&
typeof event.content === "string" &&
event.content.includes("<user_message>")
) {
sawMisroutedToolResult = true
return
}
if (event.type === "user" && event.requestId === followupRequestId) {
sawFollowupUserTurn = typeof event.content === "string" && event.content.includes("3+3")
return
}
if (event.type === "result" && event.done === true && event.requestId === startRequestId && !sentFollowup) {
context.sendCommand({
command: "message",
requestId: followupRequestId,
prompt: FOLLOWUP_PROMPT,
})
sentFollowup = true
return
}
if (event.type !== "result" || event.done !== true || event.requestId !== followupRequestId) {
return
}
followupResult = event.content ?? ""
if (followupResult.trim().length === 0) {
throw new Error("follow-up produced an empty result")
}
if (followupDoneCode !== "responded") {
throw new Error(
`follow-up message was not routed as ask response; code="${followupDoneCode ?? "none"}"`,
)
}
if (sawMisroutedToolResult) {
throw new Error("follow-up message was misrouted into tool_result (<user_message>), old bug reproduced")
}
if (sawQueueEventForFollowupRequest) {
throw new Error("follow-up message produced queue events despite responded routing")
}
if (!sawFollowupUserTurn) {
throw new Error("follow-up did not appear as a normal user turn in stream output")
}
if (sawStartControlAfterFollowup) {
throw new Error("unexpected start control event after follow-up; message should not trigger a new task")
}
if (startAckCount !== 1) {
throw new Error(`expected exactly one start ack event, saw ${startAckCount}`)
}
console.log(`[PASS] follow-up control code: "${followupDoneCode}"`)
console.log(`[PASS] follow-up user turn observed: ${sawFollowupUserTurn}`)
console.log(`[PASS] follow-up result: "${followupResult}"`)
if (!sentShutdown) {
context.sendCommand({
command: "shutdown",
requestId: shutdownRequestId,
})
sentShutdown = true
}
},
onTimeoutMessage() {
return [
"timed out waiting for completion ask-response follow-up validation",
`initSeen=${initSeen}`,
`sentFollowup=${sentFollowup}`,
`startAckCount=${startAckCount}`,
`followupDoneCode=${followupDoneCode ?? "none"}`,
`sawFollowupUserTurn=${sawFollowupUserTurn}`,
`sawMisroutedToolResult=${sawMisroutedToolResult}`,
`sawQueueEventForFollowupRequest=${sawQueueEventForFollowupRequest}`,
`haveFollowupResult=${Boolean(followupResult)}`,
].join(" ")
},
})
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -16,11 +16,9 @@ function looksLikeAttemptCompletionToolUse(event: StreamEvent): boolean {
return content.includes('"tool":"attempt_completion"') || content.includes('"name":"attempt_completion"')
}
function validateFollowupAnswer(text: string): void {
const normalized = text.toLowerCase()
const hasSix = /\b6\b/.test(normalized) || normalized.includes("six")
if (!hasSix) {
throw new Error(`follow-up result did not answer follow-up prompt; result="${text}"`)
function validateFollowupResult(text: string): void {
if (text.trim().length === 0) {
throw new Error("follow-up produced an empty result")
}
}
@ -117,7 +115,7 @@ async function main() {
}
followupResult = event.content ?? ""
validateFollowupAnswer(followupResult)
validateFollowupResult(followupResult)
if (sawMisroutedToolResult) {
throw new Error("follow-up message was misrouted into tool_result (<user_message>), old bug reproduced")

View file

@ -0,0 +1,124 @@
import { runStreamCase, StreamEvent } from "../lib/stream-harness"
const LONG_PROMPT =
'Run exactly this command and do not summarize until it finishes: sleep 20 && echo "done". After it finishes, reply with exactly "done".'
async function main() {
const startRequestId = `start-${Date.now()}`
const messageRequestId = `message-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
const testImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB"
let initSeen = false
let startAccepted = false
let messageAccepted = false
let messageQueued = false
let queueImageCountObserved = false
let shutdownSent = false
let shutdownAck = false
let shutdownDone = false
await runStreamCase({
timeoutMs: 180_000,
onEvent(event: StreamEvent, context) {
if (event.type === "system" && event.subtype === "init" && !initSeen) {
initSeen = true
context.sendCommand({ command: "start", requestId: startRequestId, prompt: LONG_PROMPT })
return
}
if (
event.type === "control" &&
event.subtype === "ack" &&
event.command === "start" &&
event.requestId === startRequestId &&
!startAccepted
) {
startAccepted = true
context.sendCommand({
command: "message",
requestId: messageRequestId,
prompt: "Respond with exactly IMAGE-QUEUED when this message is processed.",
images: [testImage],
})
return
}
if (
event.type === "control" &&
event.subtype === "ack" &&
event.command === "message" &&
event.requestId === messageRequestId
) {
messageAccepted = true
return
}
if (
event.type === "control" &&
event.subtype === "done" &&
event.command === "message" &&
event.requestId === messageRequestId &&
event.code === "queued"
) {
messageQueued = true
return
}
if (
event.type === "queue" &&
(event.subtype === "snapshot" || event.subtype === "enqueued" || event.subtype === "updated") &&
Array.isArray(event.queue) &&
event.queue.some((item) => item?.imageCount === 1)
) {
queueImageCountObserved = true
if (!shutdownSent) {
context.sendCommand({ command: "shutdown", requestId: shutdownRequestId })
shutdownSent = true
}
return
}
if (
event.type === "control" &&
event.subtype === "ack" &&
event.command === "shutdown" &&
event.requestId === shutdownRequestId
) {
shutdownAck = true
return
}
if (
event.type === "control" &&
event.subtype === "done" &&
event.command === "shutdown" &&
event.requestId === shutdownRequestId
) {
shutdownDone = true
}
},
onTimeoutMessage() {
return `timed out waiting for queue image metadata (initSeen=${initSeen}, startAccepted=${startAccepted}, messageAccepted=${messageAccepted}, messageQueued=${messageQueued}, queueImageCountObserved=${queueImageCountObserved}, shutdownSent=${shutdownSent}, shutdownAck=${shutdownAck}, shutdownDone=${shutdownDone})`
},
})
if (!messageAccepted || !messageQueued || !queueImageCountObserved) {
throw new Error(
`expected queued message with image metadata (messageAccepted=${messageAccepted}, messageQueued=${messageQueued}, queueImageCountObserved=${queueImageCountObserved})`,
)
}
if (!shutdownAck || !shutdownDone) {
throw new Error("shutdown control events were not fully observed")
}
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -0,0 +1,148 @@
import { runStreamCase, StreamEvent } from "../lib/stream-harness"
const START_PROMPT =
'Run exactly this command and do not summarize until it finishes: sleep 8 && echo "done". After it finishes, reply with exactly "done".'
async function main() {
const startRequestId = `start-${Date.now()}`
const pingARequestId = `ping-a-${Date.now()}`
const messageRequestId = `message-${Date.now()}`
const pingBRequestId = `ping-b-${Date.now()}`
const shutdownRequestId = `shutdown-${Date.now()}`
let initSeen = false
let sentInterleavedCommands = false
let sentShutdown = false
const eventOrderByRequestId = new Map<string, string[]>()
let messageDoneCode: string | undefined
let messageQueueEnqueuedSeen = false
let messageResultSeen = false
function recordControlEvent(event: StreamEvent): void {
if (!event.requestId || event.type !== "control" || !event.subtype) {
return
}
const existing = eventOrderByRequestId.get(event.requestId) ?? []
existing.push(event.subtype)
eventOrderByRequestId.set(event.requestId, existing)
}
await runStreamCase({
onEvent(event: StreamEvent, context) {
if (event.type === "system" && event.subtype === "init" && !initSeen) {
initSeen = true
context.sendCommand({
command: "start",
requestId: startRequestId,
prompt: START_PROMPT,
})
return
}
recordControlEvent(event)
if (event.type === "control" && event.subtype === "error") {
throw new Error(
`received control error for requestId=${event.requestId ?? "unknown"} command=${event.command ?? "unknown"} code=${event.code ?? "unknown"} content=${event.content ?? ""}`,
)
}
if (
!sentInterleavedCommands &&
event.type === "control" &&
event.subtype === "ack" &&
event.command === "start" &&
event.requestId === startRequestId
) {
context.sendCommand({
command: "ping",
requestId: pingARequestId,
})
context.sendCommand({
command: "message",
requestId: messageRequestId,
prompt: 'When this queued message is processed, reply with only "INTERLEAVED".',
})
context.sendCommand({
command: "ping",
requestId: pingBRequestId,
})
sentInterleavedCommands = true
return
}
if (
event.type === "control" &&
event.subtype === "done" &&
event.command === "message" &&
event.requestId === messageRequestId
) {
messageDoneCode = event.code
return
}
if (
event.type === "queue" &&
event.subtype === "enqueued" &&
event.requestId === startRequestId &&
event.queueDepth === 1
) {
messageQueueEnqueuedSeen = true
return
}
if (event.type === "result" && event.done === true && event.requestId === messageRequestId) {
messageResultSeen = true
const pingAOrder = eventOrderByRequestId.get(pingARequestId) ?? []
const pingBOrder = eventOrderByRequestId.get(pingBRequestId) ?? []
const messageOrder = eventOrderByRequestId.get(messageRequestId) ?? []
if (pingAOrder.join(",") !== "ack,done") {
throw new Error(`ping A control order mismatch: ${pingAOrder.join(",") || "none"}`)
}
if (pingBOrder.join(",") !== "ack,done") {
throw new Error(`ping B control order mismatch: ${pingBOrder.join(",") || "none"}`)
}
if (messageOrder.join(",") !== "ack,done") {
throw new Error(`message control order mismatch: ${messageOrder.join(",") || "none"}`)
}
if (messageDoneCode !== "queued") {
throw new Error(
`expected interleaved message done code \"queued\", got \"${messageDoneCode ?? "none"}\"`,
)
}
if (!messageQueueEnqueuedSeen) {
throw new Error("expected queue enqueued event after interleaved message")
}
if (!sentShutdown) {
context.sendCommand({
command: "shutdown",
requestId: shutdownRequestId,
})
sentShutdown = true
}
}
},
onTimeoutMessage() {
return [
"timed out waiting for mixed-command-ordering validation",
`initSeen=${initSeen}`,
`sentInterleavedCommands=${sentInterleavedCommands}`,
`messageDoneCode=${messageDoneCode ?? "none"}`,
`messageQueueEnqueuedSeen=${messageQueueEnqueuedSeen}`,
`messageResultSeen=${messageResultSeen}`,
`pingAOrder=${(eventOrderByRequestId.get(pingARequestId) ?? []).join(",") || "none"}`,
`messageOrder=${(eventOrderByRequestId.get(messageRequestId) ?? []).join(",") || "none"}`,
`pingBOrder=${(eventOrderByRequestId.get(pingBRequestId) ?? []).join(",") || "none"}`,
].join(" ")
},
})
}
main().catch((error) => {
console.error(`[FAIL] ${error instanceof Error ? error.message : String(error)}`)
process.exit(1)
})

View file

@ -30,6 +30,7 @@ export type StreamCommand = {
command: "start" | "message" | "cancel" | "ping" | "shutdown"
requestId: string
prompt?: string
images?: string[]
}
export interface StreamCaseContext {
@ -68,7 +69,7 @@ export async function runStreamCase(options: RunStreamCaseOptions): Promise<void
const child = execa(
"pnpm",
["dev", "--print", "--stdin-prompt-stream", "--provider", "roo", "--output-format", "stream-json"],
["dev", "--print", "--stdin-prompt-stream", "--provider", "openrouter", "--output-format", "stream-json"],
{
cwd: cliRoot,
stdin: "pipe",

View file

@ -158,6 +158,22 @@ describe("ExtensionHost", () => {
createTestHost()
expect(process.env.ROO_CLI_RUNTIME).toBe("1")
})
it("should set execaShellPath in initialSettings when terminalShell is provided", () => {
const host = createTestHost({ terminalShell: "/bin/bash" })
const emitSpy = vi.spyOn(host, "emit")
host.markWebviewReady()
const updateSettingsCall = emitSpy.mock.calls.find(
(call) =>
call[0] === "webviewMessage" &&
typeof call[1] === "object" &&
call[1] !== null &&
(call[1] as WebviewMessage).type === "updateSettings",
)
expect(updateSettingsCall).toBeDefined()
const payload = updateSettingsCall?.[1] as WebviewMessage
expect(payload.updatedSettings?.execaShellPath).toBe("/bin/bash")
})
})
describe("webview provider registration", () => {
@ -238,6 +254,26 @@ describe("ExtensionHost", () => {
)
expect(updateSettingsCall).toBeDefined()
})
it("should force terminalShellIntegrationDisabled when terminalShell is provided", () => {
const host = createTestHost({ terminalShell: "/bin/bash" })
const emitSpy = vi.spyOn(host, "emit")
host.markWebviewReady()
const updateSettingsCall = emitSpy.mock.calls.find(
(call) =>
call[0] === "webviewMessage" &&
typeof call[1] === "object" &&
call[1] !== null &&
(call[1] as WebviewMessage).type === "updateSettings",
)
expect(updateSettingsCall).toBeDefined()
const payload = updateSettingsCall?.[1] as WebviewMessage
expect(payload.type).toBe("updateSettings")
expect(payload.updatedSettings?.terminalShellIntegrationDisabled).toBe(true)
})
})
})

View file

@ -302,10 +302,10 @@ describe("JsonEventEmitter streaming deltas", () => {
emitter.emitCommandOutputChunk("line1\n")
emitter.emitCommandOutputChunk("line1\nline2\n")
emitter.emitCommandOutputDone(17)
emitter.markCommandOutputExited(17)
// This completion say is expected from the extension, but should be suppressed
// because we already streamed and completed via commandExecutionStatus.
// This completion say is expected from the extension and should finalize
// the status-driven command_output stream without duplicating content.
emitMessage(emitter, {
ts: 999,
type: "say",
@ -343,4 +343,47 @@ describe("JsonEventEmitter streaming deltas", () => {
done: true,
})
})
it("flushes remaining output on final say completion after fast status:exited", () => {
const { stdout, lines } = createMockStdout()
const emitter = new JsonEventEmitter({ mode: "stream-json", stdout })
const commandId = 606
emitMessage(
emitter,
createAskMessage({
ts: commandId,
ask: "command",
partial: false,
text: "aws sts get-caller-identity",
}),
)
emitter.emitCommandOutputChunk("{\n")
emitter.markCommandOutputExited(0)
emitMessage(emitter, {
ts: 607,
type: "say",
say: "command_output",
partial: false,
text: '{\n "Account": "123"\n}\n',
} as ClineMessage)
const output = lines()
expect(output).toHaveLength(3)
expect(output[1]).toMatchObject({
type: "tool_result",
id: commandId,
subtype: "command",
tool_result: { name: "execute_command", output: "{\n" },
})
expect(output[2]).toMatchObject({
type: "tool_result",
id: commandId,
subtype: "command",
tool_result: { name: "execute_command", output: ' "Account": "123"\n}\n', exitCode: 0 },
done: true,
})
})
})

View file

@ -80,6 +80,7 @@ export interface ExtensionHostOptions {
ephemeral: boolean
debug: boolean
exitOnComplete: boolean
terminalShell?: string
/**
* When true, exit the process on API request errors instead of retrying.
*/
@ -108,7 +109,7 @@ interface WebviewViewProvider {
export interface ExtensionHostInterface extends IExtensionHost<ExtensionHostEventMap> {
client: ExtensionClient
activate(): Promise<void>
runTask(prompt: string, taskId?: string, configuration?: RooCodeSettings): Promise<void>
runTask(prompt: string, taskId?: string, configuration?: RooCodeSettings, images?: string[]): Promise<void>
resumeTask(taskId: string): Promise<void>
sendToExtension(message: WebviewMessage): void
dispose(): Promise<void>
@ -257,6 +258,11 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
this.initialSettings.reasoningEffort = this.options.reasoningEffort
}
}
if (this.options.terminalShell) {
this.initialSettings.terminalShellIntegrationDisabled = true
this.initialSettings.execaShellPath = this.options.terminalShell
}
}
// ==========================================================================
@ -440,7 +446,7 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
// Apply CLI settings to the runtime config and context proxy BEFORE
// sending webviewDidLaunch. This prevents a race condition where the
// webviewDidLaunch handler's first-time init sync reads default state
// (apiProvider: "anthropic") instead of the CLI-provided settings.
// instead of the CLI-provided settings.
setRuntimeConfigValues("roo-cline", this.initialSettings as Record<string, unknown>)
this.sendToExtension({ type: "updateSettings", updatedSettings: this.initialSettings })
@ -510,8 +516,19 @@ export class ExtensionHost extends EventEmitter implements ExtensionHostInterfac
})
}
public async runTask(prompt: string, taskId?: string, configuration?: RooCodeSettings): Promise<void> {
this.sendToExtension({ type: "newTask", text: prompt, taskId, taskConfiguration: configuration })
public async runTask(
prompt: string,
taskId?: string,
configuration?: RooCodeSettings,
images?: string[],
): Promise<void> {
this.sendToExtension({
type: "newTask",
text: prompt,
taskId,
taskConfiguration: configuration,
...(images !== undefined ? { images } : {}),
})
return this.waitForTaskCompletion()
}

View file

@ -90,6 +90,8 @@ const SKIP_SAY_TYPES = new Set([
/** Key offset for reasoning content to avoid collision with text content delta tracking */
const REASONING_KEY_OFFSET = 1_000_000_000
/** Grace period to wait for final say:command_output after status:exited */
const COMMAND_OUTPUT_EXIT_GRACE_MS = 250
export class JsonEventEmitter {
private mode: "json" | "stream-json"
@ -115,8 +117,8 @@ export class JsonEventEmitter {
private statusDrivenCommandOutputIds = new Set<number>()
// Track command ids that already emitted a terminal command_output done event.
private completedCommandOutputIds = new Set<number>()
// Suppress the next say:command_output completion message after status-driven streaming.
private suppressNextCommandOutputSay = false
// Track exited commands awaiting final say:command_output completion.
private pendingCommandCompletionByToolUseId = new Map<number, { exitCode?: number; timer: NodeJS.Timeout }>()
// Track the completion result content
private completionResultContent: string | undefined
// Track the latest assistant text as a fallback for result.content.
@ -338,6 +340,7 @@ export class JsonEventEmitter {
if (isDone) {
event.done = true
this.clearPendingCommandCompletion(commandId)
this.previousCommandOutputByToolUseId.delete(commandId)
this.statusDrivenCommandOutputIds.delete(commandId)
this.completedCommandOutputIds.add(commandId)
@ -368,6 +371,7 @@ export class JsonEventEmitter {
})
if (isDone) {
this.clearPendingCommandCompletion(commandId)
this.previousCommandOutputByToolUseId.delete(commandId)
this.statusDrivenCommandOutputIds.delete(commandId)
this.completedCommandOutputIds.add(commandId)
@ -387,6 +391,28 @@ export class JsonEventEmitter {
this.emitCommandOutputEvent(commandId, outputSnapshot, false)
}
public markCommandOutputExited(exitCode?: number): void {
const commandId = this.activeCommandToolUseId
if (commandId === undefined) {
return
}
this.statusDrivenCommandOutputIds.add(commandId)
this.clearPendingCommandCompletion(commandId)
const timer = setTimeout(() => {
// Fallback close if final say:command_output never arrives.
if (!this.pendingCommandCompletionByToolUseId.has(commandId)) {
return
}
this.pendingCommandCompletionByToolUseId.delete(commandId)
this.emitCommandOutputEvent(commandId, undefined, true, exitCode)
}, COMMAND_OUTPUT_EXIT_GRACE_MS)
timer.unref?.()
this.pendingCommandCompletionByToolUseId.set(commandId, { exitCode, timer })
}
public emitCommandOutputDone(exitCode?: number): void {
const commandId = this.activeCommandToolUseId
if (commandId === undefined) {
@ -394,10 +420,18 @@ export class JsonEventEmitter {
}
this.statusDrivenCommandOutputIds.add(commandId)
this.suppressNextCommandOutputSay = true
this.emitCommandOutputEvent(commandId, undefined, true, exitCode)
}
private clearPendingCommandCompletion(commandId: number): void {
const pending = this.pendingCommandCompletionByToolUseId.get(commandId)
if (!pending) {
return
}
clearTimeout(pending.timer)
this.pendingCommandCompletionByToolUseId.delete(commandId)
}
/**
* Get content to send for a message (delta for streaming, full for json mode).
*/
@ -624,9 +658,19 @@ export class JsonEventEmitter {
const toolInfo = parseToolInfo(msg.text)
if (subtype === "command") {
if (this.activeCommandToolUseId !== undefined && this.activeCommandToolUseId !== msg.ts) {
const previousCommandId = this.activeCommandToolUseId
const pending = this.pendingCommandCompletionByToolUseId.get(previousCommandId)
if (pending) {
clearTimeout(pending.timer)
this.pendingCommandCompletionByToolUseId.delete(previousCommandId)
this.emitCommandOutputEvent(previousCommandId, undefined, true, pending.exitCode)
}
}
this.activeCommandToolUseId = msg.ts
this.completedCommandOutputIds.delete(msg.ts)
this.suppressNextCommandOutputSay = false
this.clearPendingCommandCompletion(msg.ts)
if (isStreamingPartial) {
const commandDelta = this.computeStructuredDelta(msg.ts, msg.text)
@ -707,17 +751,26 @@ export class JsonEventEmitter {
}
private handleCommandOutputMessage(msg: ClineMessage, isDone: boolean): void {
if (this.suppressNextCommandOutputSay) {
if (isDone) {
this.suppressNextCommandOutputSay = false
}
const commandId = this.activeCommandToolUseId ?? msg.ts
if (this.completedCommandOutputIds.has(commandId)) {
return
}
const commandId = this.activeCommandToolUseId ?? msg.ts
if (this.statusDrivenCommandOutputIds.has(commandId) || this.completedCommandOutputIds.has(commandId)) {
const pending = this.pendingCommandCompletionByToolUseId.get(commandId)
if (pending) {
if (!isDone) {
return
}
clearTimeout(pending.timer)
this.pendingCommandCompletionByToolUseId.delete(commandId)
this.emitCommandOutputEvent(commandId, msg.text, true, pending.exitCode)
return
}
if (this.statusDrivenCommandOutputIds.has(commandId)) {
return
}
this.emitCommandOutputEvent(commandId, msg.text, isDone)
}
@ -841,7 +894,10 @@ export class JsonEventEmitter {
this.previousCommandOutputByToolUseId.clear()
this.statusDrivenCommandOutputIds.clear()
this.completedCommandOutputIds.clear()
this.suppressNextCommandOutputSay = false
for (const pending of this.pendingCommandCompletionByToolUseId.values()) {
clearTimeout(pending.timer)
}
this.pendingCommandCompletionByToolUseId.clear()
this.completionResultContent = undefined
this.lastAssistantText = undefined
this.expectPromptEchoAsUser = true

View file

@ -1,3 +0,0 @@
export * from "./login.js"
export * from "./logout.js"
export * from "./status.js"

View file

@ -1,177 +0,0 @@
import http from "http"
import { randomBytes } from "crypto"
import net from "net"
import { exec } from "child_process"
import { AUTH_BASE_URL } from "@/types/index.js"
import { saveToken } from "@/lib/storage/index.js"
export interface LoginOptions {
timeout?: number
verbose?: boolean
}
export type LoginResult =
| {
success: true
token: string
}
| {
success: false
error: string
}
const LOCALHOST = "127.0.0.1"
export async function login({ timeout = 5 * 60 * 1000, verbose = false }: LoginOptions = {}): Promise<LoginResult> {
const state = randomBytes(16).toString("hex")
const port = await getAvailablePort()
const host = `http://${LOCALHOST}:${port}`
if (verbose) {
console.log(`[Auth] Starting local callback server on port ${port}`)
}
// Create promise that will be resolved when we receive the callback.
const tokenPromise = new Promise<{ token: string; state: string }>((resolve, reject) => {
const server = http.createServer((req, res) => {
const url = new URL(req.url!, host)
if (url.pathname === "/callback") {
const receivedState = url.searchParams.get("state")
const token = url.searchParams.get("token")
const error = url.searchParams.get("error")
if (error) {
const errorUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in?error=error-in-callback`)
errorUrl.searchParams.set("message", error)
res.writeHead(302, { Location: errorUrl.toString() })
res.end(() => {
server.close()
reject(new Error(error))
})
} else if (!token) {
const errorUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in?error=missing-token`)
errorUrl.searchParams.set("message", "Missing token in callback")
res.writeHead(302, { Location: errorUrl.toString() })
res.end(() => {
server.close()
reject(new Error("Missing token in callback"))
})
} else if (receivedState !== state) {
const errorUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in?error=invalid-state-parameter`)
errorUrl.searchParams.set("message", "Invalid state parameter")
res.writeHead(302, { Location: errorUrl.toString() })
res.end(() => {
server.close()
reject(new Error("Invalid state parameter"))
})
} else {
res.writeHead(302, { Location: `${AUTH_BASE_URL}/cli/sign-in?success=true` })
res.end(() => {
server.close()
resolve({ token, state: receivedState })
})
}
} else {
res.writeHead(404, { "Content-Type": "text/plain" })
res.end("Not found")
}
})
server.listen(port, LOCALHOST)
const timeoutId = setTimeout(() => {
server.close()
reject(new Error("Authentication timed out"))
}, timeout)
server.on("close", () => {
clearTimeout(timeoutId)
})
})
const authUrl = new URL(`${AUTH_BASE_URL}/cli/sign-in`)
authUrl.searchParams.set("state", state)
authUrl.searchParams.set("callback", `${host}/callback`)
console.log("Opening browser for authentication...")
console.log(`If the browser doesn't open, visit: ${authUrl.toString()}`)
try {
await openBrowser(authUrl.toString())
} catch (error) {
if (verbose) {
console.warn("[Auth] Failed to open browser automatically:", error)
}
console.log("Please open the URL above in your browser manually.")
}
try {
const { token } = await tokenPromise
await saveToken(token)
console.log("✓ Successfully authenticated!")
return { success: true, token }
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
console.error(`✗ Authentication failed: ${message}`)
return { success: false, error: message }
}
}
async function getAvailablePort(startPort = 49152, endPort = 65535): Promise<number> {
return new Promise((resolve, reject) => {
const server = net.createServer()
let port = startPort
const tryPort = () => {
server.once("error", (err: NodeJS.ErrnoException) => {
if (err.code === "EADDRINUSE" && port < endPort) {
port++
tryPort()
} else {
reject(err)
}
})
server.once("listening", () => {
server.close(() => {
resolve(port)
})
})
server.listen(port, LOCALHOST)
}
tryPort()
})
}
function openBrowser(url: string): Promise<void> {
return new Promise((resolve, reject) => {
const platform = process.platform
let command: string
switch (platform) {
case "darwin":
command = `open "${url}"`
break
case "win32":
command = `start "" "${url}"`
break
default:
// Linux and other Unix-like systems.
command = `xdg-open "${url}"`
break
}
exec(command, (error) => {
if (error) {
reject(error)
} else {
resolve()
}
})
})
}

View file

@ -1,27 +0,0 @@
import { clearToken, hasToken, getCredentialsPath } from "@/lib/storage/index.js"
export interface LogoutOptions {
verbose?: boolean
}
export interface LogoutResult {
success: boolean
wasLoggedIn: boolean
}
export async function logout({ verbose = false }: LogoutOptions = {}): Promise<LogoutResult> {
const wasLoggedIn = await hasToken()
if (!wasLoggedIn) {
console.log("You are not currently logged in.")
return { success: true, wasLoggedIn: false }
}
if (verbose) {
console.log(`[Auth] Removing credentials from ${getCredentialsPath()}`)
}
await clearToken()
console.log("✓ Successfully logged out")
return { success: true, wasLoggedIn: true }
}

View file

@ -1,97 +0,0 @@
import { loadToken, loadCredentials, getCredentialsPath } from "@/lib/storage/index.js"
import { isTokenExpired, isTokenValid, getTokenExpirationDate } from "@/lib/auth/index.js"
export interface StatusOptions {
verbose?: boolean
}
export interface StatusResult {
authenticated: boolean
expired?: boolean
expiringSoon?: boolean
userId?: string
orgId?: string | null
expiresAt?: Date
createdAt?: Date
}
export async function status(options: StatusOptions = {}): Promise<StatusResult> {
const { verbose = false } = options
const token = await loadToken()
if (!token) {
console.log("✗ Not authenticated")
console.log("")
console.log("Run: roo auth login")
return { authenticated: false }
}
const expiresAt = getTokenExpirationDate(token)
const expired = !isTokenValid(token)
const expiringSoon = isTokenExpired(token, 24 * 60 * 60) && !expired
const credentials = await loadCredentials()
const createdAt = credentials?.createdAt ? new Date(credentials.createdAt) : undefined
if (expired) {
console.log("✗ Authentication token expired")
console.log("")
console.log("Run: roo auth login")
return {
authenticated: false,
expired: true,
expiresAt: expiresAt ?? undefined,
}
}
if (expiringSoon) {
console.log("⚠ Expires soon; refresh with `roo auth login`")
} else {
console.log("✓ Authenticated")
}
if (expiresAt) {
const remaining = getTimeRemaining(expiresAt)
console.log(` Expires: ${formatDate(expiresAt)} (${remaining})`)
}
if (createdAt && verbose) {
console.log(` Created: ${formatDate(createdAt)}`)
}
if (verbose) {
console.log(` Credentials: ${getCredentialsPath()}`)
}
return {
authenticated: true,
expired: false,
expiringSoon,
expiresAt: expiresAt ?? undefined,
createdAt,
}
}
function formatDate(date: Date): string {
return date.toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" })
}
function getTimeRemaining(date: Date): string {
const now = new Date()
const diff = date.getTime() - now.getTime()
if (diff <= 0) {
return "expired"
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
if (days > 0) {
return `${days} day${days === 1 ? "" : "s"}`
}
return `${hours} hour${hours === 1 ? "" : "s"}`
}

View file

@ -1,4 +1,4 @@
import { parseStdinStreamCommand } from "../stdin-stream.js"
import { parseStdinStreamCommand, shouldSendMessageAsAskResponse } from "../stdin-stream.js"
describe("parseStdinStreamCommand", () => {
describe("valid commands", () => {
@ -10,6 +10,24 @@ describe("parseStdinStreamCommand", () => {
expect(result).toEqual({ command: "start", requestId: "req-1", prompt: "hello" })
})
it("parses a start command with taskId", () => {
const result = parseStdinStreamCommand(
JSON.stringify({
command: "start",
requestId: "req-task-id",
prompt: "hello",
taskId: "018f7fc8-7c96-7f7c-98aa-2ec4ff7f6d87",
}),
1,
)
expect(result).toEqual({
command: "start",
requestId: "req-task-id",
prompt: "hello",
taskId: "018f7fc8-7c96-7f7c-98aa-2ec4ff7f6d87",
})
})
it("parses a message command", () => {
const result = parseStdinStreamCommand(
JSON.stringify({ command: "message", requestId: "req-2", prompt: "follow up" }),
@ -18,6 +36,40 @@ describe("parseStdinStreamCommand", () => {
expect(result).toEqual({ command: "message", requestId: "req-2", prompt: "follow up" })
})
it("parses start and message images", () => {
const start = parseStdinStreamCommand(
JSON.stringify({
command: "start",
requestId: "req-img-start",
prompt: "hello",
images: ["data:image/jpeg;base64,abc123"],
}),
1,
)
expect(start).toEqual({
command: "start",
requestId: "req-img-start",
prompt: "hello",
images: ["data:image/jpeg;base64,abc123"],
})
const message = parseStdinStreamCommand(
JSON.stringify({
command: "message",
requestId: "req-img-msg",
prompt: "follow up",
images: ["data:image/png;base64,xyz456"],
}),
1,
)
expect(message).toEqual({
command: "message",
requestId: "req-img-msg",
prompt: "follow up",
images: ["data:image/png;base64,xyz456"],
})
})
it.each(["cancel", "ping", "shutdown"] as const)("parses a %s command (no prompt required)", (command) => {
const result = parseStdinStreamCommand(JSON.stringify({ command, requestId: "req-3" }), 1)
expect(result).toEqual({ command, requestId: "req-3" })
@ -95,10 +147,101 @@ describe("parseStdinStreamCommand", () => {
)
})
it("throws when start taskId is empty, not a string, or not a UUID", () => {
expect(() =>
parseStdinStreamCommand(
JSON.stringify({
command: "start",
requestId: "req-start-task-id-empty",
prompt: "hello",
taskId: " ",
}),
1,
),
).toThrow('"start" taskId must be a non-empty string')
expect(() =>
parseStdinStreamCommand(
JSON.stringify({
command: "start",
requestId: "req-start-task-id-num",
prompt: "hello",
taskId: 123,
}),
1,
),
).toThrow('"start" taskId must be a non-empty string')
expect(() =>
parseStdinStreamCommand(
JSON.stringify({
command: "start",
requestId: "req-start-task-id-invalid-format",
prompt: "hello",
taskId: "task-123",
}),
1,
),
).toThrow('"start" taskId must be a valid UUID')
})
it("throws when message command has empty prompt", () => {
expect(() =>
parseStdinStreamCommand(JSON.stringify({ command: "message", requestId: "req", prompt: " " }), 1),
).toThrow('"message" requires non-empty string "prompt"')
})
it("throws when start or message images are not string arrays", () => {
expect(() =>
parseStdinStreamCommand(
JSON.stringify({
command: "start",
requestId: "req-start-img",
prompt: "hello",
images: "not-an-array",
}),
1,
),
).toThrow('"start" images must be an array of strings')
expect(() =>
parseStdinStreamCommand(
JSON.stringify({
command: "message",
requestId: "req-msg-img",
prompt: "follow up",
images: ["ok", 123],
}),
1,
),
).toThrow('"message" images must be an array of strings')
})
})
})
describe("shouldSendMessageAsAskResponse", () => {
it("routes completion_result asks as ask responses", () => {
expect(shouldSendMessageAsAskResponse(true, "completion_result")).toBe(true)
})
it.each([
"followup",
"tool",
"command",
"use_mcp_server",
"resume_task",
"resume_completed_task",
"mistake_limit_reached",
])("routes %s asks as ask responses", (ask) => {
expect(shouldSendMessageAsAskResponse(true, ask)).toBe(true)
})
it("does not route when not waiting for input", () => {
expect(shouldSendMessageAsAskResponse(false, "completion_result")).toBe(false)
})
it("does not route unknown asks", () => {
expect(shouldSendMessageAsAskResponse(true, "unknown")).toBe(false)
expect(shouldSendMessageAsAskResponse(true, undefined)).toBe(false)
})
})

View file

@ -6,11 +6,10 @@ import pWaitFor from "p-wait-for"
import type { TaskSessionEntry } from "@roo-code/core/cli"
import type { Command, ModelRecord, WebviewMessage } from "@roo-code/types"
import { getProviderDefaultModelId } from "@roo-code/types"
import { openRouterDefaultModelId } from "@roo-code/types"
import { ExtensionHost, type ExtensionHostOptions } from "@/agent/index.js"
import { readWorkspaceTaskSessions } from "@/lib/task-history/index.js"
import { loadToken } from "@/lib/storage/index.js"
import { getDefaultExtensionPath } from "@/lib/utils/extension.js"
import { getApiKeyFromEnv } from "@/lib/utils/provider.js"
import { isRecord } from "@/lib/utils/guards.js"
@ -106,14 +105,14 @@ function outputSessionsText(sessions: SessionLike[]): void {
async function createListHost(options: BaseListOptions, hostOptions: ListHostOptions): Promise<ExtensionHost> {
const workspacePath = resolveWorkspacePath(options.workspace)
const extensionPath = resolveExtensionPath(options.extension)
const apiKey = options.apiKey || (await loadToken()) || getApiKeyFromEnv("roo")
const apiKey = options.apiKey || getApiKeyFromEnv("openrouter")
const extensionHostOptions: ExtensionHostOptions = {
mode: "code",
reasoningEffort: undefined,
user: null,
provider: "roo",
model: getProviderDefaultModelId("roo"),
provider: "openrouter",
model: openRouterDefaultModelId,
apiKey,
workspacePath,
extensionPath,
@ -215,26 +214,15 @@ function requestModes(host: ExtensionHost): Promise<ModeLike[]> {
})
}
function requestRooModels(host: ExtensionHost): Promise<ModelRecord> {
return requestFromExtension(host, "requestRooModels", (message) => {
if (message.type !== "singleRouterModelFetchResponse") {
function requestOpenRouterModels(host: ExtensionHost): Promise<ModelRecord> {
return requestFromExtension(host, "requestRouterModels", (message) => {
if (message.type !== "routerModels") {
return undefined
}
const values = isRecord(message.values) ? message.values : undefined
if (values?.provider !== "roo") {
return undefined
}
if (message.success === false) {
const errorMessage =
typeof message.error === "string" && message.error.length > 0
? message.error
: "Failed to fetch Roo models"
throw new Error(errorMessage)
}
return isRecord(values.models) ? (values.models as ModelRecord) : {}
const routerModels = isRecord(message.routerModels) ? message.routerModels : {}
const openRouterModels = routerModels.openrouter
return isRecord(openRouterModels) ? (openRouterModels as ModelRecord) : {}
})
}
@ -299,7 +287,7 @@ export async function listModels(options: BaseListOptions): Promise<void> {
const format = parseFormat(options.format)
await withHostAndSignalHandlers(options, { ephemeral: true }, async (host) => {
const models = await requestRooModels(host)
const models = await requestOpenRouterModels(host)
if (format === "json") {
outputJson({ models })

View file

@ -10,23 +10,20 @@ import { setLogger } from "@roo-code/vscode-shim"
import {
FlagOptions,
isSupportedProvider,
OnboardingProviderChoice,
supportedProviders,
DEFAULT_FLAGS,
REASONING_EFFORTS,
SDK_BASE_URL,
OutputFormat,
} from "@/types/index.js"
import { isValidOutputFormat } from "@/types/json-events.js"
import { JsonEventEmitter } from "@/agent/json-event-emitter.js"
import { createClient } from "@/lib/sdk/index.js"
import { loadToken, loadSettings } from "@/lib/storage/index.js"
import { loadSettings } from "@/lib/storage/index.js"
import { readWorkspaceTaskSessions, resolveWorkspaceResumeSessionId } from "@/lib/task-history/index.js"
import { isRecord } from "@/lib/utils/guards.js"
import { getEnvVarName, getApiKeyFromEnv } from "@/lib/utils/provider.js"
import { runOnboarding } from "@/lib/utils/onboarding.js"
import { validateTerminalShellPath } from "@/lib/utils/shell.js"
import { getDefaultExtensionPath } from "@/lib/utils/extension.js"
import { isValidSessionId } from "@/lib/utils/session-id.js"
import { VERSION } from "@/lib/utils/version.js"
import { ExtensionHost, ExtensionHostOptions } from "@/agent/index.js"
@ -34,7 +31,6 @@ import { isExpectedControlFlowError } from "./cancellation.js"
import { runStdinStreamMode } from "./stdin-stream.js"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const ROO_MODEL_WARMUP_TIMEOUT_MS = 10_000
const SIGNAL_ONLY_EXIT_KEEPALIVE_MS = 60_000
const STREAM_RESUME_WAIT_TIMEOUT_MS = 2_000
@ -52,59 +48,6 @@ function normalizeError(error: unknown): Error {
return error instanceof Error ? error : new Error(String(error))
}
async function warmRooModels(host: ExtensionHost): Promise<void> {
await new Promise<void>((resolve, reject) => {
let settled = false
const cleanup = () => {
clearTimeout(timeoutId)
host.off("extensionWebviewMessage", onMessage)
}
const finish = (fn: () => void) => {
if (settled) return
settled = true
cleanup()
fn()
}
const onMessage = (message: unknown) => {
if (!isRecord(message)) {
return
}
if (message.type !== "singleRouterModelFetchResponse") {
return
}
const values = isRecord(message.values) ? message.values : undefined
if (values?.provider !== "roo") {
return
}
if (message.success === false) {
const errorMessage =
typeof message.error === "string" && message.error.length > 0
? message.error
: "failed to refresh Roo models"
finish(() => reject(new Error(errorMessage)))
return
}
finish(() => resolve())
}
const timeoutId = setTimeout(() => {
finish(() => reject(new Error(`timed out waiting for Roo models after ${ROO_MODEL_WARMUP_TIMEOUT_MS}ms`)))
}, ROO_MODEL_WARMUP_TIMEOUT_MS)
host.on("extensionWebviewMessage", onMessage)
host.sendToExtension({ type: "requestRooModels" })
})
}
export async function run(promptArg: string | undefined, flagOptions: FlagOptions) {
setLogger({
info: () => {},
@ -125,11 +68,32 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
}
const requestedSessionId = flagOptions.sessionId?.trim()
const requestedCreateSessionId = flagOptions.createWithSessionId?.trim()
const shouldContinueSession = flagOptions.continue
const isResumeRequested = Boolean(requestedSessionId || shouldContinueSession)
if (flagOptions.createWithSessionId !== undefined && !requestedCreateSessionId) {
console.error("[CLI] Error: --create-with-session-id requires a non-empty session id")
process.exit(1)
}
if (flagOptions.sessionId !== undefined && !requestedSessionId) {
console.error("[CLI] Error: --session-id requires a non-empty task id")
console.error("[CLI] Error: --session-id requires a non-empty session id")
process.exit(1)
}
if (requestedCreateSessionId && !isValidSessionId(requestedCreateSessionId)) {
console.error("[CLI] Error: --create-with-session-id must be a valid UUID session id")
process.exit(1)
}
if (requestedSessionId && !isValidSessionId(requestedSessionId)) {
console.error("[CLI] Error: --session-id must be a valid UUID session id")
process.exit(1)
}
if (requestedCreateSessionId && isResumeRequested) {
console.error("[CLI] Error: cannot use --create-with-session-id with --session-id/--continue")
process.exit(1)
}
@ -140,25 +104,23 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
if (isResumeRequested && prompt) {
console.error("[CLI] Error: cannot use prompt or --prompt-file with --session-id/--continue")
console.error("[CLI] Usage: roo [--session-id <task-id> | --continue] [options]")
console.error("[CLI] Usage: roo [--session-id <session-id> | --continue] [options]")
process.exit(1)
}
// Options
let rooToken = await loadToken()
const settings = await loadSettings()
const isTuiSupported = process.stdin.isTTY && process.stdout.isTTY
const isTuiEnabled = !flagOptions.print && isTuiSupported
const isOnboardingEnabled = isTuiEnabled && !rooToken && !flagOptions.provider && !settings.provider
// Determine effective values: CLI flags > settings file > DEFAULT_FLAGS.
const effectiveMode = flagOptions.mode || settings.mode || DEFAULT_FLAGS.mode
const effectiveModel = flagOptions.model || settings.model || DEFAULT_FLAGS.model
const effectiveReasoningEffort =
flagOptions.reasoningEffort || settings.reasoningEffort || DEFAULT_FLAGS.reasoningEffort
const effectiveProvider = flagOptions.provider ?? settings.provider ?? (rooToken ? "roo" : "openrouter")
const effectiveProvider = flagOptions.provider ?? settings.provider ?? "openrouter"
const effectiveWorkspacePath = flagOptions.workspace ? path.resolve(flagOptions.workspace) : process.cwd()
const legacyRequireApprovalFromSettings =
settings.requireApproval ??
@ -176,6 +138,19 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
process.exit(1)
}
let terminalShell: string | undefined
if (flagOptions.terminalShell !== undefined) {
const validatedTerminalShell = await validateTerminalShellPath(flagOptions.terminalShell)
if (!validatedTerminalShell.valid) {
console.error(
`[CLI] Warning: ignoring --terminal-shell "${flagOptions.terminalShell}" (${validatedTerminalShell.reason})`,
)
} else {
terminalShell = validatedTerminalShell.shellPath
}
}
const extensionHostOptions: ExtensionHostOptions = {
mode: effectiveMode,
reasoningEffort: effectiveReasoningEffort === "unspecified" ? undefined : effectiveReasoningEffort,
@ -190,49 +165,7 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
ephemeral: flagOptions.ephemeral,
debug: flagOptions.debug,
exitOnComplete: effectiveExitOnComplete,
}
// Roo Code Cloud Authentication
if (isOnboardingEnabled) {
let { onboardingProviderChoice } = settings
if (!onboardingProviderChoice) {
const { choice, token } = await runOnboarding()
onboardingProviderChoice = choice
rooToken = token ?? null
}
if (onboardingProviderChoice === OnboardingProviderChoice.Roo) {
extensionHostOptions.provider = "roo"
}
}
if (extensionHostOptions.provider === "roo") {
if (rooToken) {
try {
const client = createClient({ url: SDK_BASE_URL, authToken: rooToken })
const me = await client.auth.me.query()
if (me?.type !== "user") {
throw new Error("Invalid token")
}
extensionHostOptions.apiKey = rooToken
extensionHostOptions.user = me.user
} catch {
// 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)
}
}
}
// If no rooToken, fall through to the general API key resolution below
// which will check flagOptions.apiKey and ROO_API_KEY env var.
terminalShell,
}
// Validations
@ -250,18 +183,8 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
extensionHostOptions.apiKey || flagOptions.apiKey || getApiKeyFromEnv(extensionHostOptions.provider)
if (!extensionHostOptions.apiKey) {
if (extensionHostOptions.provider === "roo") {
console.error("[CLI] Error: Authentication with Roo Code Cloud failed or was cancelled.")
console.error("[CLI] Please run: roo auth login")
console.error("[CLI] Or use --api-key to provide your own API key.")
} else {
console.error(
`[CLI] Error: No API key provided. Use --api-key or set the appropriate environment variable.`,
)
console.error(
`[CLI] For ${extensionHostOptions.provider}, set ${getEnvVarName(extensionHostOptions.provider)}`,
)
}
console.error(`[CLI] Error: No API key provided. Use --api-key or set the appropriate environment variable.`)
console.error(`[CLI] For ${extensionHostOptions.provider}, set ${getEnvVarName(extensionHostOptions.provider)}`)
process.exit(1)
}
@ -327,6 +250,12 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
process.exit(1)
}
if (flagOptions.stdinPromptStream && requestedCreateSessionId) {
console.error("[CLI] Error: --create-with-session-id is not supported with --stdin-prompt-stream")
console.error('[CLI] Use per-request "taskId" in stdin start commands instead.')
process.exit(1)
}
const useStdinPromptStream = flagOptions.stdinPromptStream
let resolvedResumeSessionId: string | undefined
@ -374,6 +303,7 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
createElement(App, {
...extensionHostOptions,
initialPrompt: prompt,
initialTaskId: requestedCreateSessionId,
initialSessionId: resolvedResumeSessionId,
continueSession: false,
version: VERSION,
@ -562,16 +492,6 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
try {
await host.activate()
if (extensionHostOptions.provider === "roo") {
try {
await warmRooModels(host)
} catch (warmupError) {
if (flagOptions.debug) {
const message = warmupError instanceof Error ? warmupError.message : String(warmupError)
console.error(`[CLI] Warning: Roo model warmup failed: ${message}`)
}
}
}
if (jsonEmitter) {
jsonEmitter.attachToClient(host.client)
@ -597,7 +517,7 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
if (isResumeRequested) {
await host.resumeTask(resolvedResumeSessionId!)
} else {
await host.runTask(prompt!)
await host.runTask(prompt!, requestedCreateSessionId)
}
}

View file

@ -9,6 +9,7 @@ import {
} from "@roo-code/types"
import { isRecord } from "@/lib/utils/guards.js"
import { isValidSessionId } from "@/lib/utils/session-id.js"
import { isCancellationLikeError, isExpectedControlFlowError, isNoActiveTaskLikeError } from "./cancellation.js"
import type { ExtensionHost } from "@/agent/index.js"
@ -63,20 +64,63 @@ export function parseStdinStreamCommand(line: string, lineNumber: number): Stdin
if (command === "start" || command === "message") {
const promptRaw = parsed.prompt
if (typeof promptRaw !== "string" || promptRaw.trim().length === 0) {
throw new Error(`stdin command line ${lineNumber}: "${command}" requires non-empty string "prompt"`)
}
if (command === "start" && isRecord(parsed.configuration)) {
const imagesRaw = parsed.images
let images: string[] | undefined
if (imagesRaw !== undefined) {
if (!Array.isArray(imagesRaw) || !imagesRaw.every((image) => typeof image === "string")) {
throw new Error(`stdin command line ${lineNumber}: "${command}" images must be an array of strings`)
}
images = imagesRaw
}
if (command === "start") {
const taskIdRaw = parsed.taskId
let taskId: string | undefined
if (taskIdRaw !== undefined) {
if (typeof taskIdRaw !== "string" || taskIdRaw.trim().length === 0) {
throw new Error(`stdin command line ${lineNumber}: "start" taskId must be a non-empty string`)
}
taskId = taskIdRaw.trim()
if (!isValidSessionId(taskId)) {
throw new Error(`stdin command line ${lineNumber}: "start" taskId must be a valid UUID`)
}
}
if (isRecord(parsed.configuration)) {
return {
command,
requestId,
prompt: promptRaw,
...(taskId !== undefined ? { taskId } : {}),
...(images !== undefined ? { images } : {}),
configuration: parsed.configuration as RooCliStartCommand["configuration"],
}
}
return {
command,
requestId,
prompt: promptRaw,
configuration: parsed.configuration as RooCliStartCommand["configuration"],
...(taskId !== undefined ? { taskId } : {}),
...(images !== undefined ? { images } : {}),
}
}
return { command, requestId, prompt: promptRaw }
return {
command,
requestId,
prompt: promptRaw,
...(images !== undefined ? { images } : {}),
}
}
return { command, requestId }
@ -196,6 +240,20 @@ const STDIN_EOF_RESUME_WAIT_TIMEOUT_MS = 2_000
const STDIN_EOF_POLL_INTERVAL_MS = 100
const STDIN_EOF_IDLE_ASKS = new Set(["completion_result", "resume_completed_task"])
const STDIN_EOF_IDLE_STABLE_POLLS = 2
const MESSAGE_AS_ASK_RESPONSE_ASKS = new Set([
"followup",
"tool",
"command",
"use_mcp_server",
"completion_result",
"resume_task",
"resume_completed_task",
"mistake_limit_reached",
])
export function shouldSendMessageAsAskResponse(waitingForInput: boolean, currentAsk: string | undefined): boolean {
return waitingForInput && typeof currentAsk === "string" && MESSAGE_AS_ASK_RESPONSE_ASKS.has(currentAsk)
}
function isResumableState(host: ExtensionHost): boolean {
const agentState = host.client.getAgentState()
@ -414,16 +472,22 @@ export async function runStdinStreamMode({ host, jsonEmitter, setStreamRequestId
return
}
if (
parsedStatus.status === "exited" ||
parsedStatus.status === "timeout" ||
parsedStatus.status === "fallback"
) {
if (parsedStatus.status === "exited") {
const exitCode =
parsedStatus.status === "exited" && typeof parsedStatus.exitCode === "number"
? parsedStatus.exitCode
: undefined
jsonEmitter.emitCommandOutputDone(exitCode)
if (typeof parsedStatus.output === "string") {
jsonEmitter.emitCommandOutputChunk(parsedStatus.output)
}
jsonEmitter.markCommandOutputExited(exitCode)
return
}
if (parsedStatus.status === "timeout" || parsedStatus.status === "fallback") {
jsonEmitter.emitCommandOutputDone(undefined)
return
}
@ -578,7 +642,7 @@ export async function runStdinStreamMode({ host, jsonEmitter, setStreamRequestId
activeRequestId = stdinCommand.requestId
activeTaskCommand = "start"
setStreamRequestId(stdinCommand.requestId)
latestTaskId = randomUUID()
latestTaskId = stdinCommand.taskId ?? randomUUID()
cancelRequestedForActiveTask = false
awaitingPostCancelRecovery = false
@ -601,7 +665,7 @@ export async function runStdinStreamMode({ host, jsonEmitter, setStreamRequestId
}
activeTaskPromise = host
.runTask(stdinCommand.prompt, latestTaskId, taskConfiguration)
.runTask(stdinCommand.prompt, latestTaskId, taskConfiguration, stdinCommand.images)
.catch((error) => {
const message = error instanceof Error ? error.message : String(error)
@ -666,6 +730,8 @@ export async function runStdinStreamMode({ host, jsonEmitter, setStreamRequestId
}
const wasResumable = isResumableState(host)
const currentAsk = host.client.getCurrentAsk()
const shouldSendAsAskResponse = shouldSendMessageAsAskResponse(host.isWaitingForInput(), currentAsk)
if (!host.client.hasActiveTask()) {
jsonEmitter.emitControl({
@ -691,7 +757,34 @@ export async function runStdinStreamMode({ host, jsonEmitter, setStreamRequestId
success: true,
})
host.sendToExtension({ type: "queueMessage", text: stdinCommand.prompt })
if (shouldSendAsAskResponse) {
// Match webview behavior: if there is an active ask, route message directly as an ask response.
host.sendToExtension({
type: "askResponse",
askResponse: "messageResponse",
text: stdinCommand.prompt,
images: stdinCommand.images,
})
setStreamRequestId(stdinCommand.requestId)
jsonEmitter.emitControl({
subtype: "done",
requestId: stdinCommand.requestId,
command: "message",
taskId: latestTaskId,
content: "message sent to current ask",
code: "responded",
success: true,
})
awaitingPostCancelRecovery = false
break
}
host.sendToExtension({
type: "queueMessage",
text: stdinCommand.prompt,
images: stdinCommand.images,
})
pendingQueuedMessageRequestIds.push(stdinCommand.requestId)
if (host.isWaitingForInput()) {
setStreamRequestId(stdinCommand.requestId)

View file

@ -1,2 +1 @@
export * from "./auth/index.js"
export * from "./cli/index.js"

View file

@ -2,17 +2,7 @@ import { Command } from "commander"
import { DEFAULT_FLAGS } from "@/types/constants.js"
import { VERSION } from "@/lib/utils/version.js"
import {
run,
login,
logout,
status,
listCommands,
listModes,
listModels,
listSessions,
upgrade,
} from "@/commands/index.js"
import { run, listCommands, listModes, listModels, listSessions, upgrade } from "@/commands/index.js"
const program = new Command()
@ -26,7 +16,8 @@ program
program
.argument("[prompt]", "Your prompt")
.option("--prompt-file <path>", "Read prompt from a file instead of command line argument")
.option("--session-id <task-id>", "Resume a specific task by task ID")
.option("--create-with-session-id <session-id>", "Create a new task with a specific session ID (must be a UUID)")
.option("--session-id <session-id>", "Resume a specific task by session ID")
.option("-c, --continue", "Resume the most recent task in the current workspace", false)
.option("-w, --workspace <path>", "Workspace directory path (defaults to current working directory)")
.option("-p, --print", "Print response and exit (non-interactive mode)", false)
@ -44,9 +35,10 @@ program
.option("-d, --debug", "Enable debug output (includes detailed debug information)", 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("--provider <provider>", "API provider (anthropic, openai, openrouter, etc.)")
.option("-m, --model <model>", "Model to use", DEFAULT_FLAGS.model)
.option("--mode <mode>", "Mode to start in (code, architect, ask, debug, etc.)", DEFAULT_FLAGS.mode)
.option("--terminal-shell <path>", "Absolute path to shell executable for inline terminal commands")
.option(
"-r, --reasoning-effort <effort>",
"Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh)",
@ -77,7 +69,7 @@ const applyListOptions = (command: Command) =>
command
.option("-w, --workspace <path>", "Workspace directory path (defaults to current working directory)")
.option("-e, --extension <path>", "Path to the extension bundle directory")
.option("-k, --api-key <key>", "Roo API key (falls back to saved login/session token)")
.option("-k, --api-key <key>", "API key for the LLM provider")
.option("--format <format>", 'Output format: "json" (default) or "text"', "json")
.option("-d, --debug", "Enable debug output", false)
@ -115,7 +107,7 @@ applyListOptions(listCommand.command("modes").description("List available modes"
},
)
applyListOptions(listCommand.command("models").description("List available Roo models")).action(
applyListOptions(listCommand.command("models").description("List available models")).action(
async (options: Parameters<typeof listModels>[0]) => {
await runListAction(() => listModels(options))
},
@ -134,33 +126,4 @@ program
await runUpgradeAction(() => upgrade())
})
const authCommand = program.command("auth").description("Manage authentication for Roo Code Cloud")
authCommand
.command("login")
.description("Authenticate with Roo Code Cloud")
.option("-v, --verbose", "Enable verbose output", false)
.action(async (options: { verbose: boolean }) => {
const result = await login({ verbose: options.verbose })
process.exit(result.success ? 0 : 1)
})
authCommand
.command("logout")
.description("Log out from Roo Code Cloud")
.option("-v, --verbose", "Enable verbose output", false)
.action(async (options: { verbose: boolean }) => {
const result = await logout({ verbose: options.verbose })
process.exit(result.success ? 0 : 1)
})
authCommand
.command("status")
.description("Show authentication status")
.option("-v, --verbose", "Enable verbose output", false)
.action(async (options: { verbose: boolean }) => {
const result = await status({ verbose: options.verbose })
process.exit(result.authenticated ? 0 : 1)
})
program.parse()

View file

@ -1 +0,0 @@
export * from "./token.js"

View file

@ -1,61 +0,0 @@
export interface DecodedToken {
iss: string
sub: string
exp: number
iat: number
nbf: number
v: number
r?: {
u?: string
o?: string
t: string
}
}
function decodeToken(token: string): DecodedToken | null {
try {
const parts = token.split(".")
if (parts.length !== 3) {
return null
}
const payload = parts[1]
if (!payload) {
return null
}
const padded = payload + "=".repeat((4 - (payload.length % 4)) % 4)
const decoded = Buffer.from(padded, "base64url").toString("utf-8")
return JSON.parse(decoded) as DecodedToken
} catch {
return null
}
}
export function isTokenExpired(token: string, bufferSeconds = 24 * 60 * 60): boolean {
const decoded = decodeToken(token)
if (!decoded?.exp) {
return true
}
const expiresAt = decoded.exp
const bufferTime = Math.floor(Date.now() / 1000) + bufferSeconds
return expiresAt < bufferTime
}
export function isTokenValid(token: string): boolean {
return !isTokenExpired(token, 0)
}
export function getTokenExpirationDate(token: string): Date | null {
const decoded = decodeToken(token)
if (!decoded?.exp) {
return null
}
return new Date(decoded.exp * 1000)
}

View file

@ -1,152 +0,0 @@
import fs from "fs/promises"
import path from "path"
// Use vi.hoisted to make the test directory available to the mock
// This must return the path synchronously since CREDENTIALS_FILE is computed at import time
const { getTestConfigDir } = vi.hoisted(() => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const os = require("os")
// eslint-disable-next-line @typescript-eslint/no-require-imports
const path = require("path")
const testRunId = Date.now().toString()
const testConfigDir = path.join(os.tmpdir(), `roo-cli-test-${testRunId}`)
return { getTestConfigDir: () => testConfigDir }
})
vi.mock("../config-dir.js", () => ({
getConfigDir: getTestConfigDir,
}))
// Import after mocking
import { saveToken, loadToken, loadCredentials, clearToken, hasToken, getCredentialsPath } from "../credentials.js"
// Re-derive the test config dir for use in tests (must match the hoisted one)
const actualTestConfigDir = getTestConfigDir()
describe("Token Storage", () => {
const expectedCredentialsFile = path.join(actualTestConfigDir, "cli-credentials.json")
beforeEach(async () => {
// Clear test directory before each test
await fs.rm(actualTestConfigDir, { recursive: true, force: true })
})
afterAll(async () => {
// Clean up test directory
await fs.rm(actualTestConfigDir, { recursive: true, force: true })
})
describe("getCredentialsPath", () => {
it("should return the correct credentials file path", () => {
expect(getCredentialsPath()).toBe(expectedCredentialsFile)
})
})
describe("saveToken", () => {
it("should save token to disk", async () => {
const token = "test-token-123"
await saveToken(token)
const savedData = await fs.readFile(expectedCredentialsFile, "utf-8")
const credentials = JSON.parse(savedData)
expect(credentials.token).toBe(token)
expect(credentials.createdAt).toBeDefined()
})
it("should save token with user info", async () => {
const token = "test-token-456"
await saveToken(token, { userId: "user_123", orgId: "org_456" })
const savedData = await fs.readFile(expectedCredentialsFile, "utf-8")
const credentials = JSON.parse(savedData)
expect(credentials.token).toBe(token)
expect(credentials.userId).toBe("user_123")
expect(credentials.orgId).toBe("org_456")
})
it("should create config directory if it doesn't exist", async () => {
const token = "test-token-789"
await saveToken(token)
const dirStats = await fs.stat(actualTestConfigDir)
expect(dirStats.isDirectory()).toBe(true)
})
// Unix file permissions don't apply on Windows - skip this test
it.skipIf(process.platform === "win32")("should set restrictive file permissions", async () => {
const token = "test-token-perms"
await saveToken(token)
const stats = await fs.stat(expectedCredentialsFile)
// Check that only owner has read/write (mode 0o600)
const mode = stats.mode & 0o777
expect(mode).toBe(0o600)
})
})
describe("loadToken", () => {
it("should load saved token", async () => {
const token = "test-token-abc"
await saveToken(token)
const loaded = await loadToken()
expect(loaded).toBe(token)
})
it("should return null if no token exists", async () => {
const loaded = await loadToken()
expect(loaded).toBeNull()
})
})
describe("loadCredentials", () => {
it("should load full credentials", async () => {
const token = "test-token-def"
await saveToken(token, { userId: "user_789" })
const credentials = await loadCredentials()
expect(credentials).not.toBeNull()
expect(credentials?.token).toBe(token)
expect(credentials?.userId).toBe("user_789")
expect(credentials?.createdAt).toBeDefined()
})
it("should return null if no credentials exist", async () => {
const credentials = await loadCredentials()
expect(credentials).toBeNull()
})
})
describe("clearToken", () => {
it("should remove saved token", async () => {
const token = "test-token-ghi"
await saveToken(token)
await clearToken()
const loaded = await loadToken()
expect(loaded).toBeNull()
})
it("should not throw if no token exists", async () => {
await expect(clearToken()).resolves.not.toThrow()
})
})
describe("hasToken", () => {
it("should return true if token exists", async () => {
await saveToken("test-token-jkl")
const exists = await hasToken()
expect(exists).toBe(true)
})
it("should return false if no token exists", async () => {
const exists = await hasToken()
expect(exists).toBe(false)
})
})
})

View file

@ -51,7 +51,7 @@ describe("Settings Storage", () => {
it("should load saved settings", async () => {
const settingsData = {
onboardingProviderChoice: OnboardingProviderChoice.Roo,
onboardingProviderChoice: OnboardingProviderChoice.Byok,
mode: "architect",
provider: "anthropic" as const,
model: "claude-sonnet-4-20250514",
@ -138,7 +138,7 @@ describe("Settings Storage", () => {
describe("resetOnboarding", () => {
it("should reset onboarding provider choice", async () => {
await saveSettings({ onboardingProviderChoice: OnboardingProviderChoice.Roo })
await saveSettings({ onboardingProviderChoice: OnboardingProviderChoice.Byok })
await resetOnboarding()

View file

@ -1,72 +0,0 @@
import fs from "fs/promises"
import path from "path"
import { getConfigDir } from "./index.js"
const CREDENTIALS_FILE = path.join(getConfigDir(), "cli-credentials.json")
export interface Credentials {
token: string
createdAt: string
userId?: string
orgId?: string
}
export async function saveToken(token: string, options?: { userId?: string; orgId?: string }): Promise<void> {
await fs.mkdir(getConfigDir(), { recursive: true })
const credentials: Credentials = {
token,
createdAt: new Date().toISOString(),
userId: options?.userId,
orgId: options?.orgId,
}
await fs.writeFile(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
mode: 0o600, // Read/write for owner only
})
}
export async function loadToken(): Promise<string | null> {
try {
const data = await fs.readFile(CREDENTIALS_FILE, "utf-8")
const credentials: Credentials = JSON.parse(data)
return credentials.token
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
return null
}
throw error
}
}
export async function loadCredentials(): Promise<Credentials | null> {
try {
const data = await fs.readFile(CREDENTIALS_FILE, "utf-8")
return JSON.parse(data) as Credentials
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
return null
}
throw error
}
}
export async function clearToken(): Promise<void> {
try {
await fs.unlink(CREDENTIALS_FILE)
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
throw error
}
}
}
export async function hasToken(): Promise<boolean> {
const token = await loadToken()
return token !== null
}
export function getCredentialsPath(): string {
return CREDENTIALS_FILE
}

View file

@ -1,4 +1,3 @@
export * from "./config-dir.js"
export * from "./settings.js"
export * from "./credentials.js"
export * from "./ephemeral.js"

View file

@ -0,0 +1,54 @@
import fs from "fs/promises"
import { validateTerminalShellPath } from "../shell.js"
vi.mock("fs/promises", () => ({
default: {
access: vi.fn(),
stat: vi.fn(),
},
}))
describe("validateTerminalShellPath", () => {
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(fs.access).mockResolvedValue(undefined)
vi.mocked(fs.stat).mockResolvedValue({
isFile: () => true,
} as unknown as Awaited<ReturnType<typeof fs.stat>>)
})
it("returns invalid for an empty path", async () => {
const result = await validateTerminalShellPath(" ")
expect(result).toEqual({ valid: false, reason: "shell path cannot be empty" })
})
it("returns invalid for a relative path", async () => {
const result = await validateTerminalShellPath("bin/bash")
expect(result).toEqual({ valid: false, reason: "shell path must be absolute" })
})
it("returns valid for an absolute executable path", async () => {
const result = await validateTerminalShellPath("/bin/bash")
expect(result).toEqual({ valid: true, shellPath: "/bin/bash" })
})
it("returns invalid when the shell path cannot be accessed", async () => {
vi.mocked(fs.stat).mockRejectedValueOnce(new Error("ENOENT"))
const result = await validateTerminalShellPath("/missing/shell")
expect(result.valid).toBe(false)
if (!result.valid) {
expect(result.reason).toContain("shell path")
}
})
it("returns invalid when the shell path points to a directory", async () => {
vi.mocked(fs.stat).mockResolvedValueOnce({
isFile: () => false,
} as unknown as Awaited<ReturnType<typeof fs.stat>>)
const result = await validateTerminalShellPath("/bin")
expect(result).toEqual({ valid: false, reason: "shell path must point to a file" })
})
})

View file

@ -1,38 +0,0 @@
import { createElement } from "react"
import { type OnboardingResult, OnboardingProviderChoice } from "@/types/index.js"
import { login } from "@/commands/index.js"
import { saveSettings } from "@/lib/storage/index.js"
export async function runOnboarding(): Promise<OnboardingResult> {
const { render } = await import("ink")
const { OnboardingScreen } = await import("../../ui/components/onboarding/index.js")
return new Promise<OnboardingResult>((resolve) => {
const onSelect = async (choice: OnboardingProviderChoice) => {
await saveSettings({ onboardingProviderChoice: choice })
app.unmount()
console.log("")
if (choice === OnboardingProviderChoice.Roo) {
const result = await login()
await saveSettings({ onboardingProviderChoice: choice })
resolve({
choice: OnboardingProviderChoice.Roo,
token: result.success ? result.token : undefined,
skipped: false,
})
} else {
console.log("Using your own API key.")
console.log("Set your API key via --api-key or environment variable.")
console.log("")
resolve({ choice: OnboardingProviderChoice.Byok, skipped: false })
}
}
const app = render(createElement(OnboardingScreen, { onSelect }))
})
}

View file

@ -8,7 +8,6 @@ const envVarMap: Record<SupportedProvider, string> = {
gemini: "GOOGLE_API_KEY",
openrouter: "OPENROUTER_API_KEY",
"vercel-ai-gateway": "VERCEL_AI_GATEWAY_API_KEY",
roo: "ROO_API_KEY",
}
export function getEnvVarName(provider: SupportedProvider): string {
@ -48,10 +47,6 @@ export function getProviderSettings(
if (apiKey) config.vercelAiGatewayApiKey = apiKey
if (model) config.vercelAiGatewayModelId = model
break
case "roo":
if (apiKey) config.rooApiKey = apiKey
if (model) config.apiModelId = model
break
default:
if (apiKey) config.apiKey = apiKey
if (model) config.apiModelId = model

View file

@ -0,0 +1,5 @@
const SESSION_ID_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
export function isValidSessionId(value: string): boolean {
return SESSION_ID_UUID_PATTERN.test(value)
}

View file

@ -0,0 +1,47 @@
import fs from "fs/promises"
import { constants as fsConstants } from "fs"
import path from "path"
export type TerminalShellValidationResult =
| {
valid: true
shellPath: string
}
| {
valid: false
reason: string
}
export async function validateTerminalShellPath(rawShellPath: string): Promise<TerminalShellValidationResult> {
const shellPath = rawShellPath.trim()
if (!shellPath) {
return { valid: false, reason: "shell path cannot be empty" }
}
if (!path.isAbsolute(shellPath)) {
return { valid: false, reason: "shell path must be absolute" }
}
try {
const stats = await fs.stat(shellPath)
if (!stats.isFile()) {
return { valid: false, reason: "shell path must point to a file" }
}
if (process.platform !== "win32") {
await fs.access(shellPath, fsConstants.X_OK)
}
} catch {
return {
valid: false,
reason:
process.platform === "win32"
? "shell path does not exist or is not a file"
: "shell path does not exist, is not a file, or is not executable",
}
}
return { valid: true, shellPath }
}

View file

@ -21,7 +21,3 @@ export const ASCII_ROO = ` _,' ___
\\,\\ / \\\\
// \\\\
,/' \`\\_,`
export const AUTH_BASE_URL = process.env.ROO_AUTH_BASE_URL ?? "https://app.roocode.com"
export const SDK_BASE_URL = process.env.ROO_SDK_BASE_URL ?? "https://cloud-api.roocode.com"

View file

@ -7,7 +7,6 @@ export const supportedProviders = [
"gemini",
"openrouter",
"vercel-ai-gateway",
"roo",
] as const satisfies ProviderName[]
export type SupportedProvider = (typeof supportedProviders)[number]
@ -20,6 +19,7 @@ export type ReasoningEffortFlagOptions = ReasoningEffortExtended | "unspecified"
export type FlagOptions = {
promptFile?: string
createWithSessionId?: string
sessionId?: string
continue: boolean
workspace?: string
@ -34,6 +34,7 @@ export type FlagOptions = {
provider?: SupportedProvider
model?: string
mode?: string
terminalShell?: string
reasoningEffort?: ReasoningEffortFlagOptions
consecutiveMistakeLimit?: number
ephemeral: boolean
@ -42,7 +43,6 @@ export type FlagOptions = {
}
export enum OnboardingProviderChoice {
Roo = "roo",
Byok = "byok",
}

View file

@ -60,6 +60,7 @@ const PICKER_HEIGHT = 10
export interface TUIAppProps extends ExtensionHostOptions {
initialPrompt?: string
initialTaskId?: string
initialSessionId?: string
continueSession?: boolean
version: string
@ -73,6 +74,7 @@ export interface TUIAppProps extends ExtensionHostOptions {
function AppInner({ createExtensionHost, ...extensionHostOptions }: TUIAppProps) {
const {
initialPrompt,
initialTaskId,
initialSessionId,
continueSession,
workspacePath,
@ -174,6 +176,7 @@ function AppInner({ createExtensionHost, ...extensionHostOptions }: TUIAppProps)
const { sendToExtension, runTask, cleanup } = useExtensionHost({
initialPrompt,
initialTaskId,
initialSessionId,
continueSession,
mode,

View file

@ -1,28 +0,0 @@
import { Box, Text } from "ink"
import { Select } from "@inkjs/ui"
import { OnboardingProviderChoice, ASCII_ROO } from "@/types/index.js"
export interface OnboardingScreenProps {
onSelect: (choice: OnboardingProviderChoice) => void
}
export function OnboardingScreen({ onSelect }: OnboardingScreenProps) {
return (
<Box flexDirection="column" gap={1}>
<Text bold color="cyan">
{ASCII_ROO}
</Text>
<Text dimColor>Welcome! How would you like to connect to an LLM provider?</Text>
<Select
options={[
{ label: "Connect to Roo Code Cloud", value: OnboardingProviderChoice.Roo },
{ label: "Bring your own API key", value: OnboardingProviderChoice.Byok },
]}
onChange={(value: string) => {
onSelect(value as OnboardingProviderChoice)
}}
/>
</Box>
)
}

View file

@ -1 +0,0 @@
export * from "./OnboardingScreen.js"

View file

@ -39,6 +39,7 @@ function getMostRecentTaskId(taskHistory: HistoryItem[], workspacePath: string):
// TODO: Unify with TUIAppProps?
export interface UseExtensionHostOptions extends ExtensionHostOptions {
initialPrompt?: string
initialTaskId?: string
initialSessionId?: string
continueSession?: boolean
onExtensionMessage: (msg: ExtensionMessage) => void
@ -63,6 +64,7 @@ export interface UseExtensionHostReturn {
*/
export function useExtensionHost({
initialPrompt,
initialTaskId,
initialSessionId,
continueSession,
mode,
@ -86,6 +88,7 @@ export function useExtensionHost({
const hostRef = useRef<ExtensionHostInterface | null>(null)
const isReadyRef = useRef(false)
const pendingInitialTaskIdRef = useRef<string | undefined>(initialTaskId?.trim() || undefined)
const cleanup = useCallback(async () => {
if (hostRef.current) {
@ -193,7 +196,9 @@ export function useExtensionHost({
setHasStartedTask(true)
setLoading(true)
addMessage({ id: randomUUID(), role: "user", content: initialPrompt })
await host.runTask(initialPrompt)
const taskId = pendingInitialTaskIdRef.current
pendingInitialTaskIdRef.current = undefined
await host.runTask(initialPrompt, taskId)
}
} catch (err) {
setError(err instanceof Error ? err.message : String(err))
@ -221,7 +226,9 @@ export function useExtensionHost({
return Promise.reject(new Error("Extension host not ready"))
}
return hostRef.current.runTask(prompt)
const taskId = pendingInitialTaskIdRef.current
pendingInitialTaskIdRef.current = undefined
return hostRef.current.runTask(prompt, taskId)
}, [])
// Memoized return object to prevent unnecessary re-renders in consumers.

1
apps/docs/.env.example Normal file
View file

@ -0,0 +1 @@
# No environment variables are required for local docs development.

31
apps/docs/.gitignore vendored Normal file
View file

@ -0,0 +1,31 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
*.js
!src/**/*.js
# Misc
.DS_Store
.env
!.env.example
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.devcontainer
TEMP/
.history/
.roo/mcp.json

201
apps/docs/LICENSE Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

21
apps/docs/README.md Normal file
View file

@ -0,0 +1,21 @@
# Roo Code Docs
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator, and lives at https://roocodeinc.github.io/Roo-Code/
### Installation
```
$ pnpm install
```
### Local Development
```
$ pnpm start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### License
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)

View file

@ -0,0 +1,164 @@
---
description: Learn how the access_mcp_resource tool retrieves data from Model Context Protocol servers for additional context in Roo Code tasks.
keywords:
- access_mcp_resource
- MCP
- Model Context Protocol
- MCP resources
- Roo Code tools
- context retrieval
- API integration
---
# access_mcp_resource
The `access_mcp_resource` tool retrieves data from resources exposed by connected Model Context Protocol (MCP) servers. It allows Roo to access files, API responses, documentation, or system information that provides additional context for tasks.
---
## Parameters
The tool accepts these parameters:
- `server_name` (required): The name of the MCP server providing the resource
- `uri` (required): The URI identifying the specific resource to access
---
## What It Does
This tool connects to MCP servers and fetches data from their exposed resources. Unlike `use_mcp_tool` which executes actions, this tool specifically retrieves information that serves as context for tasks.
---
## When is it used?
- When Roo needs additional context from external systems
- When Roo needs to access domain-specific data from specialized MCP servers
- When Roo needs to retrieve reference documentation hosted by MCP servers
- When Roo needs to integrate real-time data from external APIs via MCP
---
## Key Features
- Retrieves both text and image data from MCP resources
- Requires user approval before executing resource access
- Uses URI-based addressing to precisely identify resources
- Integrates with the Model Context Protocol SDK
- Displays resource content appropriately based on content type
- Supports timeouts for reliable network operations
- Handles server connection states (connected, connecting, disconnected)
- Discovers available resources from connected servers
- Processes structured response data with metadata
- Handles image content special rendering
---
## Limitations
- Depends on external MCP servers being available and connected
- Limited to the resources provided by connected servers
- Cannot access resources from disabled servers
- Network issues can affect reliability and performance
- Resource access subject to configured timeouts
- URI formats are determined by the specific MCP server implementation
- No offline or cached resource access capabilities
---
## How It Works
When the `access_mcp_resource` tool is invoked, it follows this process:
1. **Connection Validation**:
- Verifies that an MCP hub is available and initialized
- Confirms the specified server exists in the connection list
- Checks if the server is disabled (returns an error if it is)
2. **User Approval**:
- Presents the resource access request to the user for approval
- Provides server name and resource URI for user verification
- Proceeds only if the user approves the resource access
3. **Resource Request**:
- Uses the Model Context Protocol SDK to communicate with servers
- Makes a `resources/read` request to the server through the MCP hub
- Applies configured timeouts to prevent hanging on unresponsive servers
4. **Response Processing**:
- Receives a structured response with metadata and content arrays
- Processes text content for display to the user
- Handles image data specially for appropriate display
- Returns the processed resource data to Roo for use in the current task
---
## Resource Types
MCP servers can provide two main types of resources:
1. **Standard Resources**:
- Fixed resources with specific URIs
- Defined name, description, and MIME type
- Direct access without parameters
- Typically represent static data or real-time information
2. **Resource Templates**:
- Parameterized resources with placeholder values in URIs
- Allow dynamic resource generation based on provided parameters
- Can represent queries or filtered views of data
- More flexible but require additional URI formatting
---
## Examples When Used
- When helping with API development, Roo retrieves endpoint specifications from MCP resources to ensure correct implementation.
- When assisting with data visualization, Roo accesses current data samples from connected MCP servers.
- When working in specialized domains, Roo retrieves technical documentation to provide accurate guidance.
- When generating industry-specific code, Roo references compliance requirements from documentation resources.
---
## Usage Examples
Accessing current weather data:
```
<access_mcp_resource>
<server_name>weather-server</server_name>
<uri>weather://san-francisco/current</uri>
</access_mcp_resource>
```
Retrieving API documentation:
```
<access_mcp_resource>
<server_name>api-docs</server_name>
<uri>docs://payment-service/endpoints</uri>
</access_mcp_resource>
```
Accessing domain-specific knowledge:
```
<access_mcp_resource>
<server_name>knowledge-base</server_name>
<uri>kb://medical/terminology/common</uri>
</access_mcp_resource>
```
Fetching system configuration:
```
<access_mcp_resource>
<server_name>infra-monitor</server_name>
<uri>config://production/database</uri>
</access_mcp_resource>
```

View file

@ -0,0 +1,120 @@
---
description: Master the apply_diff tool for making surgical code changes using fuzzy matching and line hints in Roo Code with multi-file support.
keywords:
- apply_diff
- file editing
- code modifications
- fuzzy matching
- diff tool
- Roo Code tools
- multi-file edits
---
# apply_diff
The `apply_diff` tool makes precise, surgical changes to files by specifying exactly what content to replace. It uses a sophisticated strategy for finding and applying changes while maintaining proper code formatting and structure.
---
## Parameters
The tool accepts these parameters:
- `path` (required): The path of the file to modify relative to the current working directory.
- `diff` (required): The search/replace block defining the changes using a format specific to the active diff strategy.
- `start_line` (optional): A hint for where the search content begins. _Note: This top-level parameter appears unused by the current main strategy, which relies on `:start_line:` within the diff content._
- `end_line` (optional): A hint for where the search content ends. _Note: This top-level parameter appears unused by the current main strategy._
---
## What It Does
This tool applies targeted changes to existing files using fuzzy matching guided by line number hints to locate and replace content precisely. Unlike simple search and replace, it identifies the exact block for replacement based on the provided content and location hints.
---
## When is it used?
- When Roo needs to make precise changes to existing code without rewriting entire files.
- When refactoring specific sections of code while maintaining surrounding context.
- When fixing bugs in existing code with surgical precision.
- When implementing feature enhancements that modify only certain parts of a file.
---
## Key Features
- Uses fuzzy matching (Levenshtein distance on normalized strings) guided by a `:start_line:` hint, with configurable confidence thresholds (typically 0.8-1.0).
- Provides context around matches using `BUFFER_LINES` (default 40).
- Performs a middle-out search within a configurable context window (`bufferLines`) around the hinted start line.
- Preserves code formatting and indentation passively by replacing exact blocks.
- Shows changes in a diff view for user review and editing before applying.
- Tracks consecutive errors per file (`consecutiveMistakeCountForApplyDiff`) to prevent repeated failures.
- Validates file access against `.rooignore` rules.
- Handles multi-line edits effectively.
---
## Limitations
- Works best with unique, distinctive code sections for reliable identification.
- Performance can vary with very large files or highly repetitive code patterns.
- Fuzzy matching might occasionally select incorrect locations if content is ambiguous.
- Each diff strategy has specific format requirements.
- Complex edits might require careful strategy selection or manual review.
---
## How It Works
When the `apply_diff` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates required `path` and `diff` parameters.
2. **RooIgnore Check**: Validates if the target file path is allowed by `.rooignore` rules.
3. **File Analysis**: Loads the target file content.
4. **Match Finding**: Uses a fuzzy matching algorithm (Levenshtein on normalized strings) guided by the `:start_line:` hint within a context window (`BUFFER_LINES`), searching middle-out to locate the target content based on the confidence threshold.
5. **Change Preparation**: Generates the proposed changes by replacing the identified block.
6. **User Interaction**:
- Displays the changes in a diff view.
- Allows the user to review and potentially edit the proposed changes.
- Waits for user approval or rejection.
7. **Change Application**: If approved, applies the changes (potentially including user edits) to the file.
8. **Error Handling**: If errors occur (e.g., match failure, partial application), increments the `consecutiveMistakeCountForApplyDiff` for the file and reports the failure type.
9. **Feedback**: Returns the result, including any user feedback or error details.
---
## Diff Format Requirements
The `<diff>` parameter requires a specific format supporting one or more changes in a single request. Each change block requires a line number hint for the original content.
- **Requires**: Exact match for the `SEARCH` block content (within the fuzzy threshold), including whitespace and indentation. The `:start_line:` number hint is mandatory within each block. The `:end_line:` hint is optional (but supported by the parser). Markers like `<<<<<<<` within the file's content must be escaped (`\\`) in the SEARCH block.
Example format for the `<diff>` block:
```diff
<<<<<<< SEARCH
:start_line:10
:end_line:12
-------
// Old calculation logic
const result = value * 0.9;
return result;
=======
// Updated calculation logic with logging
console.log(`Calculating for value: ${value}`);
const result = value * 0.95; // Adjusted factor
return result;
>>>>>>> REPLACE
<<<<<<< SEARCH
:start_line:25
:end_line:25
-------
const defaultTimeout = 5000;
=======
const defaultTimeout = 10000; // Increased timeout
>>>>>>> REPLACE
```
---

View file

@ -0,0 +1,110 @@
---
description: Apply unified diff patches to multiple files in a single operation using the apply_patch tool in Roo Code.
keywords:
- apply_patch
- patch
- unified diff
- multi-file edits
- file operations
- Roo Code tools
- diff patches
---
# apply_patch
The `apply_patch` tool applies unified diff patches to multiple files in a single operation. It supports custom patch headers for adding, deleting, and updating files, making it ideal for complex multi-file refactoring operations.
---
## Parameters
The tool accepts these parameters:
- `patch` (required): A unified diff patch string with custom headers. Supports `*** Add File:`, `*** Delete File:`, and `*** Update File:` headers.
---
## What It Does
This tool processes unified diff patches containing operations for multiple files. It parses the patch content, identifies file operations (add, delete, update), and applies the changes atomically. Unlike [`apply_diff`](/advanced-usage/available-tools/apply-diff) which handles single-file search-and-replace operations, `apply_patch` works with traditional unified diff format.
---
## When is it used?
- When applying patches generated by version control systems or diff tools
- When performing complex multi-file refactoring with precise line-level changes
- When migrating code changes from one branch or repository to another
- When bulk-adding, updating, or removing multiple files in one operation
- When working with patches from external sources or automated tools
---
## Key Features
- Supports multiple files in a single patch operation
- Handles file addition, deletion, and modification
- Uses unified diff format for precise line-level control
- Custom headers (`*** Add File:`, `*** Delete File:`, `*** Update File:`) for clarity
- Atomic operations with validation before applying changes
- Compatible with standard diff/patch tooling output
---
## Limitations
- Requires proper unified diff format syntax
- Line numbers and context must match existing file content
- Cannot apply patches with conflicts or mismatched context
- Less flexible than search-and-replace tools for fuzzy matching
- Requires exact line-level accuracy in patches
---
## How It Works
When the `apply_patch` tool is invoked, it follows this process:
1. **Patch Parsing**: Parses the patch string to identify custom headers (`*** Add File:`, `*** Delete File:`, `*** Update File:`) and unified diff blocks.
2. **Operation Identification**: Groups changes by file path and operation type (add, delete, update).
3. **Validation**: Validates that target files exist (for updates/deletes) or can be created (for adds).
4. **RooIgnore Check**: Ensures target files are not restricted by `.rooignore` rules.
5. **User Review**: Presents the patch operations for user review and approval.
6. **Application**: Applies approved changes to each file sequentially.
7. **Feedback**: Reports success or failure for each file operation.
---
## Patch Format
The patch format uses custom headers followed by unified diff blocks:
```diff
*** Add File: src/utils/newHelper.ts
--- /dev/null
+++ b/src/utils/newHelper.ts
@@ -0,0 +1,5 @@
+export function helperFunction(value: string): string {
+ return value.toUpperCase();
+}
*** Update File: src/main.ts
--- a/src/main.ts
+++ b/src/main.ts
@@ -10,7 +10,7 @@
import { config } from './config';
-const timeout = 5000;
+const timeout = 10000;
function main() {
*** Delete File: src/deprecated/oldUtil.ts
```
---
## Relation to Other Tools
- [`apply_diff`](/advanced-usage/available-tools/apply-diff): Use for single-file search-and-replace with fuzzy matching
- `apply_patch`: Use for multi-file operations with unified diff format
- [`write_to_file`](/advanced-usage/available-tools/write-to-file): Use for creating entire new files

View file

@ -0,0 +1,208 @@
---
description: Enable interactive communication in Roo Code with the ask_followup_question tool for gathering clarification and user preferences.
keywords:
- ask_followup_question
- user interaction
- interactive communication
- Roo Code tools
- clarification
- user feedback
---
# ask_followup_question
The `ask_followup_question` tool enables interactive communication by asking specific questions to gather additional information needed to complete tasks effectively.
---
## Parameters
The tool accepts these parameters:
- `question` (required): The specific question to ask the user
- `follow_up` (optional): A list of 2-4 suggested answers that help guide user responses, each within `<suggest>` tags
---
## What It Does
This tool creates a conversational interface between Roo and the user, allowing for gathering clarification, additional details, or user preferences when facing ambiguities or decision points. Each question can include suggested responses to streamline the interaction.
---
## When is it used?
- When critical information is missing from the original request
- When Roo needs to choose between multiple valid implementation approaches
- When technical details or preferences are required to proceed
- When Roo encounters ambiguities that need resolution
- When additional context would significantly improve the solution quality
---
## Key Features
- Provides a structured way to gather specific information without breaking workflow
- Includes suggested answers to reduce user typing and guide responses
- Maintains conversation history and context across interactions
- Supports responses containing images and code snippets
- Available in all modes as part of the "always available" tool set
- Enables direct user guidance on implementation decisions
- Formats responses with `<answer>` tags to distinguish them from regular conversation
- Resets consecutive error counter when used successfully
---
## Limitations
- Limited to asking one specific question per tool use
- Presents suggestions as selectable options in the UI
- Cannot force structured responses users can still respond freely
- Excessive use can slow down task completion and create a fragmented experience
- Suggested answers must be complete, with no placeholders requiring user edits
- No built-in validation for user responses
- Contains no mechanism to enforce specific answer formats
---
## How It Works
When the `ask_followup_question` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates the required `question` parameter and checks for optional suggestions
- Ensures question text is provided
- Parses any suggested answers from the `follow_up` parameter using the `fast-xml-parser` library
- Normalizes suggestions into an array format even if there's only one suggestion
2. **JSON Transformation**: Converts the XML structure into a standardized JSON format for UI display
```typescript
{
question: "User's question here",
suggest: [
{ answer: "Suggestion 1" },
{ answer: "Suggestion 2" }
]
}
```
3. **UI Integration**:
- Passes the JSON structure to the UI layer via the `ask("followup", ...)` method
- Displays selectable suggestion buttons to the user in the interface
- Creates an interactive experience for selecting or typing a response
4. **Response Collection and Processing**:
- Captures user text input and any images included in the response
- Wraps user responses in `<answer>` tags when returning to the assistant
- Preserves any images included in the user's response
- Maintains the conversational context by adding the response to the history
- Resets the consecutive error counter when the tool is used successfully
5. **Error Handling**:
- Tracks consecutive mistakes using a counter
- Resets the counter when the tool is used successfully
- Provides specific error messages:
- For missing parameters: "Missing required parameter 'question'"
- For XML parsing: "Failed to parse operations: [error message]"
- For invalid format: "Invalid operations xml format"
- Contains safeguards to prevent tool execution when required parameters are missing
- Increments consecutive mistake count when errors occur
---
## Workflow Sequence
The question-answer cycle follows this sequence:
1. **Information Gap Recognition**: Roo identifies missing information needed to proceed
2. **Specific Question Creation**: Roo formulates a clear, targeted question
3. **Suggestion Development**: Roo creates relevant suggested answers (optional but recommended)
4. **Tool Invocation**: Assistant invokes the tool with question and optional suggestions
5. **UI Presentation**: Question and suggestions are displayed to the user as interactive elements
6. **User Response**: The user selects a suggestion or provides a custom answer
7. **Message Handling**: System handles both partial and complete messages
- For streaming responses, processes chunks as they arrive
- For complete messages, processes the entire response at once
- Maintains state consistency regardless of message chunking
8. **Response Processing**: System wraps the response in `<answer>` tags and preserves images
9. **Context Integration**: Response is added to the conversation history
10. **Task Continuation**: Roo proceeds with the task using the new information
---
## Examples When Used
- When developing a web application, Roo might ask about preferred styling frameworks (Bootstrap, Tailwind, custom CSS)
- When creating an API, Roo might ask about authentication methods (JWT, OAuth, API keys)
- When refactoring code, Roo might ask about prioritizing performance vs. readability
- When setting up a database, Roo might ask about specific schema design preferences
- When creating a custom feature, Roo might ask about specific behavior expectations
- When troubleshooting errors, Roo might ask about specific environment details
---
## Response Format
When a user responds to a question, the response is formatted with `<answer>` tags for clarity and consistency. This format helps clearly separate the user's answer from other conversation elements.
Example response format:
```
<answer>
Use Tailwind CSS for utility-first styling with maximum flexibility
</answer>
```
Key characteristics of the response format:
- Surrounded by `<answer>` tags
- Preserves formatting of the original response
- Maintains images if included in the response
- Returns the complete text, even for long responses
---
## Usage Examples
Asking about implementation preferences:
```
<ask_followup_question>
<question>Which styling approach would you prefer for this web application?</question>
<follow_up>
<suggest>Use Bootstrap for rapid development with consistent components</suggest>
<suggest>Use Tailwind CSS for utility-first styling with maximum flexibility</suggest>
<suggest>Use vanilla CSS with custom styling for complete control and minimal dependencies</suggest>
</follow_up>
</ask_followup_question>
```
Requesting technical clarification:
```
<ask_followup_question>
<question>What database should this application use for storing user data?</question>
<follow_up>
<suggest>MongoDB for flexible schema and document-based storage</suggest>
<suggest>PostgreSQL for relational data with strong consistency guarantees</suggest>
<suggest>Firebase for real-time updates and simplified backend management</suggest>
<suggest>SQLite for lightweight local storage without external dependencies</suggest>
</follow_up>
</ask_followup_question>
```
Addressing ambiguity in requirements:
```
<ask_followup_question>
<question>How should the application handle user authentication?</question>
<follow_up>
<suggest>Implement email/password authentication with account verification</suggest>
<suggest>Use social login providers (Google, GitHub, etc.) for quick signup</suggest>
<suggest>Implement both email/password and social login options</suggest>
</follow_up>
</ask_followup_question>
```

View file

@ -0,0 +1,215 @@
---
description: Learn how the attempt_completion tool signals task completion, presents results, and enables iterative refinement in Roo Code.
keywords:
- attempt_completion
- task completion
- result presentation
- Roo Code tools
- user feedback
- task summary
---
# attempt_completion
The `attempt_completion` tool signals that Roo believes a task is complete and presents results to the user. It provides a summary of what was accomplished, optionally includes a command to demonstrate the result, and supports continued refinement through user feedback.
---
## Parameters
The tool accepts these parameters:
- `result` (required): The final result description summarizing what was accomplished
- `command` (optional): A CLI command to execute to demonstrate the result
---
## What It Does
This tool marks the end of a task by presenting a final summary of what was accomplished. It signals to both the user and the system that the current task is complete. When a command is provided, it can also demonstrate the result through a live execution.
---
## When is it used?
- When Roo believes the user's task has been completed
- When summarizing what changes or improvements were made
- When demonstrating the current result with a command execution
- When providing a checkpoint for user feedback on the solution
- When transitioning from one phase of work to potential refinements
---
## Key Features
- Provides a clear signal that Roo believes the task is complete
- Summarizes accomplishments in a concise message
- Optionally demonstrates results through command execution
- Enables user feedback for further refinements
- Displays results in a special UI format distinct from regular messages
- Maintains a structured conversation flow by providing checkpoints
- Supports subtask completion within larger workflows
- Ensures users receive a clear summary of what was done
- Available in all modes as part of the "always available" tool group
---
## Limitations
- Should not be used until previous tool uses are confirmed successful (guideline, not enforced)
- Limited to a single command for result demonstration
- Cannot present multiple command options
- Commands require user approval before execution
- Limited to demonstrating results that can be shown via CLI commands
- Cannot be used for partial task completion or progress updates
- Result formatting strips XML closing tags through internal processing
---
## How It Works
When the `attempt_completion` tool is invoked, it follows this process:
1. **Safety Consideration** (guideline, not enforced):
- The AI is instructed to confirm previous tool uses were successful
- This is a best practice rather than a programmatically enforced mechanism
2. **Result Presentation**:
- Displays the completion message to the user in a special "completion_result" UI format
- Removes XML closing tags from the result text using the `removeClosingTag` function
- Presents the result differently than regular messages for visual distinction
3. **Command Execution** (if provided):
- Requests user approval before executing the command
- Only executes if the user approves
- Executes the command using the system's command execution functionality
- Shows the result of the command to the user
4. **Feedback Collection**:
- Waits for user feedback on the completion result
- Processes this feedback and returns it to the AI
- Enables continued refinement based on user input
5. **Task Completion and Continuation**:
- Signals the task as completed in the system
- Captures telemetry data for the completed task
- For subtasks, offers to finish the subtask and resume the parent task
- Supports continued conversation through the feedback mechanism
6. **Implementation Integration**:
- Tool results are parsed through the system's parsing mechanism in `parse-assistant-message.ts`
- The tool is part of the "ALWAYS_AVAILABLE_TOOLS" constant, making it available in all modes
---
## Result Formatting Guidelines
The result message should follow these guidelines:
- Clearly communicate what was accomplished
- Be concise but complete
- Focus on the value delivered to the user
- Avoid unnecessary pleasantries or filler text
- Maintain a professional, straightforward tone
- Present information in a way that's easy to scan and understand
- Acknowledge that the user may provide feedback for further refinements
Note: The system automatically strips XML closing tags from the result text through the `removeClosingTag` function.
---
## Command Selection Guidelines
When including a command, follow these guidelines:
- Choose commands that visually demonstrate the result
- Prefer commands that show the user what was created or modified
- Examples include:
- `open index.html` to display a created website
- `npm start` to launch a development server
- `python app.py` to run a created application
- Avoid commands that merely print text (like `echo` or `cat`)
- Remember that commands require user approval before execution
- Ensure the command is valid for the user's operating system
---
## Feedback and UI Representation
The `attempt_completion` tool has a unique feedback mechanism:
- Results appear in a special "completion_result" UI format distinct from regular messages
- The system waits for user feedback after presenting the result
- Feedback is processed and returned to Roo for further refinements
- This creates an iterative improvement cycle rather than ending the conversation
- The UI includes special elements for providing feedback
- Results serve as clear checkpoints in the conversation flow
When used within subtasks:
- The system offers to finish the subtask and resume the parent task
- If approved, the subtask is completed with a summary
- The parent task resumes with context from the completed subtask
- This enables complex, nested workflows while maintaining context
---
## Examples When Used
- When creating a website, Roo presents the solution and uses `open index.html` to show the result. The user provides feedback, and Roo refines the design.
- When implementing a feature, Roo summarizes the changes and their impact. The user requests additional test coverage, and Roo continues the task.
- When fixing bugs, Roo explains what was fixed and how the solution addresses the root cause. The user confirms the fix works.
- When setting up a development environment, Roo confirms all components are installed. The user requests additional configuration, and Roo continues.
- When creating a data processing script, Roo summarizes the functionality. The user suggests performance improvements, and Roo optimizes the code.
---
## Usage Examples
Completing a task with just a result summary:
```
<attempt_completion>
<result>
I've updated the CSS for the navigation bar to match the design mockup. The changes include:
1. Updated color scheme to use the new brand colors
2. Added responsive behavior for mobile devices
3. Fixed the alignment issues in the dropdown menus
</result>
</attempt_completion>
```
Completing a task with a result and demonstration command:
```
<attempt_completion>
<result>
I've created a simple React application with the following features:
1. A responsive landing page with the requested hero section
2. A working contact form with validation
3. Navigation between all three requested pages
4. Styling that matches the provided design mockup
</result>
<command>npm start</command>
</attempt_completion>
```
Completing a Python script task with execution:
```
<attempt_completion>
<result>
I've created a data processing script that:
1. Reads the CSV files from the data directory
2. Cleans and normalizes the data as requested
3. Generates the summary statistics in JSON format
4. Outputs the processed data to the output directory
</result>
<command>python process_data.py</command>
</attempt_completion>
```

View file

@ -0,0 +1,275 @@
---
description: Perform intelligent semantic searches across your codebase using AI embeddings to find relevant code by meaning, not just keywords.
keywords:
- codebase_search
- semantic search
- AI embeddings
- code search
- Roo Code tools
- vector search
- Qdrant
---
# codebase_search
:::info Setup Required
The `codebase_search` tool is part of the [Codebase Indexing](/features/codebase-indexing) feature. It requires additional setup including an embedding provider and vector database.
:::
The `codebase_search` tool performs semantic searches across your entire codebase using AI embeddings. Unlike traditional text-based search, it understands the meaning of your queries and finds relevant code even when exact keywords don't match.
---
## Parameters
The tool accepts these parameters:
- `query` (required): Natural language search query describing what you're looking for
- `path` (optional): Directory path to limit search scope to a specific part of your codebase
---
## What It Does
This tool searches through your indexed codebase using semantic similarity rather than exact text matching. It finds code blocks that are conceptually related to your query, even if they don't contain the exact words you searched for. Results include relevant code snippets with file paths, line numbers, and similarity scores.
---
## When is it used?
- When Roo needs to find code related to specific functionality across your project
- When looking for implementation patterns or similar code structures
- When searching for error handling, authentication, or other conceptual code patterns
- When exploring unfamiliar codebases to understand how features are implemented
- When finding related code that might be affected by changes or refactoring
---
## Key Features
- **Semantic Understanding**: Finds code by meaning rather than exact keyword matches
- **Cross-Project Search**: Searches across your entire indexed codebase, not just open files
- **Contextual Results**: Returns code snippets with file paths and line numbers for easy navigation
- **Similarity Scoring**: Results ranked by relevance with similarity scores (0-1 scale)
- **Scope Filtering**: Optional path parameter to limit searches to specific directories
- **Intelligent Ranking**: Results sorted by semantic relevance to your query
- **UI Integration**: Results displayed with syntax highlighting and navigation links
- **Performance Optimized**: Fast vector-based search with configurable result limits
---
## Requirements
This tool is only available when the Codebase Indexing feature is properly configured:
- **Feature Configured**: Codebase Indexing must be configured in settings
- **Embedding Provider**: OpenAI API key or Ollama configuration required
- **Vector Database**: Qdrant instance running and accessible
- **Index Status**: Codebase must be indexed (status: "Indexed" or "Indexing")
---
## Limitations
- **Requires Configuration**: Depends on external services (embedding provider + Qdrant)
- **Index Dependency**: Only searches through indexed code blocks
- **Result Limits**: Maximum of 50 results per search to maintain performance
- **Similarity Threshold**: Only returns results above similarity threshold (default: 0.4, configurable)
- **File Size Limits**: Limited to files under 1MB that were successfully indexed
- **Language Support**: Effectiveness depends on Tree-sitter language support
---
## How It Works
When the `codebase_search` tool is invoked, it follows this process:
1. **Availability Validation**:
- Verifies that the CodeIndexManager is available and initialized
- Confirms codebase indexing is enabled in settings
- Checks that indexing is properly configured (API keys, Qdrant URL)
- Validates the current index state allows searching
2. **Query Processing**:
- Takes your natural language query and generates an embedding vector
- Uses the same embedding provider configured for indexing (OpenAI or Ollama)
- Converts the semantic meaning of your query into a mathematical representation
3. **Vector Search Execution**:
- Searches the Qdrant vector database for similar code embeddings
- Uses cosine similarity to find the most relevant code blocks
- Applies the minimum similarity threshold (default: 0.4, configurable) to filter results
- Limits results to 50 matches for optimal performance
4. **Path Filtering** (if specified):
- Filters results to only include files within the specified directory path
- Uses normalized path comparison for accurate filtering
- Maintains relevance ranking within the filtered scope
5. **Result Processing and Formatting**:
- Converts absolute file paths to workspace-relative paths
- Structures results with file paths, line ranges, similarity scores, and code content
- Formats for both AI consumption and UI display with syntax highlighting
6. **Dual Output Format**:
- **AI Output**: Structured text format with query, file paths, scores, and code chunks
- **UI Output**: JSON format with syntax highlighting and navigation capabilities
---
## Search Query Best Practices
### Effective Query Patterns
**Good: Conceptual and specific**
```xml
<codebase_search>
<query>user authentication and password validation</query>
</codebase_search>
```
**Good: Feature-focused**
```xml
<codebase_search>
<query>database connection pool setup</query>
</codebase_search>
```
**Good: Problem-oriented**
```xml
<codebase_search>
<query>error handling for API requests</query>
</codebase_search>
```
**Less effective: Too generic**
```xml
<codebase_search>
<query>function</query>
</codebase_search>
```
### Query Types That Work Well
- **Functional Descriptions**: "file upload processing", "email validation logic"
- **Technical Patterns**: "singleton pattern implementation", "factory method usage"
- **Domain Concepts**: "user profile management", "payment processing workflow"
- **Architecture Components**: "middleware configuration", "database migration scripts"
---
## Directory Scoping
Use the optional `path` parameter to focus searches on specific parts of your codebase:
**Search within API modules:**
```xml
<codebase_search>
<query>endpoint validation middleware</query>
<path>src/api</path>
</codebase_search>
```
**Search in test files:**
```xml
<codebase_search>
<query>mock data setup patterns</query>
<path>tests</path>
</codebase_search>
```
**Search specific feature directories:**
```xml
<codebase_search>
<query>component state management</query>
<path>src/components/auth</path>
</codebase_search>
```
---
## Result Interpretation
### Similarity Scores
- **0.8-1.0**: Highly relevant matches, likely exactly what you're looking for
- **0.6-0.8**: Good matches with strong conceptual similarity
- **0.4-0.6**: Potentially relevant but may require review
- **Below 0.4**: Filtered out as too dissimilar
### Result Structure
Each search result includes:
- **File Path**: Workspace-relative path to the file containing the match
- **Score**: Similarity score indicating relevance (0.4-1.0)
- **Line Range**: Start and end line numbers for the code block
- **Code Chunk**: The actual code content that matched your query
---
## Examples When Used
- When implementing a new feature, Roo searches for "authentication middleware" to understand existing patterns before writing new code.
- When debugging an issue, Roo searches for "error handling in API calls" to find related error patterns across the codebase.
- When refactoring code, Roo searches for "database transaction patterns" to ensure consistency across all database operations.
- When onboarding to a new codebase, Roo searches for "configuration loading" to understand how the application bootstraps.
---
## Usage Examples
Searching for authentication-related code across the entire project:
```xml
<codebase_search>
<query>user login and authentication logic</query>
</codebase_search>
```
Finding database-related code in a specific directory:
```xml
<codebase_search>
<query>database connection and query execution</query>
<path>src/data</path>
</codebase_search>
```
Looking for error handling patterns in API code:
```xml
<codebase_search>
<query>HTTP error responses and exception handling</query>
<path>src/api</path>
</codebase_search>
```
Searching for testing utilities and mock setups:
```xml
<codebase_search>
<query>test setup and mock data creation</query>
<path>tests</path>
</codebase_search>
```
Finding configuration and environment setup code:
```xml
<codebase_search>
<query>environment variables and application configuration</query>
</codebase_search>
```

View file

@ -0,0 +1,91 @@
---
description: Replace a uniquely-identified occurrence of text in files using the edit_file search-and-replace tool in Roo Code.
keywords:
- edit_file
- search and replace
- file editing
- text replacement
- Roo Code tools
- code modifications
---
# edit_file
The `edit_file` tool performs targeted search-and-replace operations on files. By default it replaces **exactly one** uniquely-identified occurrence and errors if multiple matches are found. It also supports a special file-creation mode when `old_string` is empty.
---
## Parameters
The tool accepts these parameters:
- `file_path` (required): The path of the file to modify relative to the current working directory.
- `old_string` (required): The exact text to search for and replace. Pass an empty string (`""`) to create a new file or append to an existing file.
- `new_string` (required): The replacement text.
- `expected_replacements` (optional): Expected number of replacements (defaults to 1). The operation fails if the actual count doesn't match. Use this only when intentionally replacing more than one occurrence.
---
## What It Does
This tool searches for an exact string in a file and replaces **exactly one** occurrence with new text. The search string must uniquely identify the target location. If multiple matches are found, the tool returns an error unless `expected_replacements` is explicitly set to match. When `old_string` is empty, the tool creates a new file or appends `new_string` to an existing file.
---
## When is it used?
- When making a targeted change to a specific, uniquely identifiable location in a file
- When updating a specific string literal or configuration value at a known location
- When fixing a specific instance of a typo or outdated terminology
- When replacing a uniquely-identified occurrence of a deprecated API or import path
- When creating a new file or appending content to an existing file (`old_string=""`)
- When you need to ensure exact match replacement without fuzzy logic
---
## Key Features
- Replaces **exactly one** uniquely-identified occurrence by default
- Errors if multiple matches are found (unless `expected_replacements` is explicitly set)
- `old_string=""` mode: creates a new file or appends content to an existing file
- Exact string matching (no regex or fuzzy matching)
- Optional `expected_replacements` for intentional multi-occurrence replacements
- Shows preview of changes before applying
- Fails safely if actual replacement count doesn't match `expected_replacements`
- Preserves file formatting and structure
---
## Limitations
- Requires exact string matches (case-sensitive, whitespace-sensitive)
- Errors if the search string matches more than one location (unless `expected_replacements` is set)
- Cannot use regular expressions or patterns
- Not suitable for context-dependent replacements
- Less precise than [`apply_diff`](/advanced-usage/available-tools/apply-diff) for complex edits
---
## How It Works
When the `edit_file` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates required `file_path`, `old_string`, and `new_string` parameters.
2. **File Creation Mode**: If `old_string` is empty (`""`), creates the file with `new_string` as content (or appends if the file already exists), then stops.
3. **File Loading**: Reads the target file content.
4. **Uniqueness Check**: Counts occurrences of `old_string`. If the count doesn't match `expected_replacements` (default: 1), returns an error.
5. **Replacement**: Replaces the matched occurrence(s) with `new_string`.
6. **User Review**: Shows a preview of changes for user approval.
7. **Application**: Applies changes to the file if approved.
8. **Feedback**: Reports the number of replacements made.
---
## Relation to Other Tools
- `edit_file`: Replaces **exactly one** uniquely-identified occurrence by default; supports `old_string=""` file creation (this tool)
- [`edit`](/advanced-usage/available-tools/edit): Replaces **first occurrence** only (unless `replace_all: true`)
- [`search_replace`](/advanced-usage/available-tools/search-replace): Also replaces **exactly one** uniquely-identified occurrence
- [`apply_diff`](/advanced-usage/available-tools/apply-diff): Use for precise, context-aware edits with fuzzy matching
These are different implementations of search-and-replace with varying capabilities.

View file

@ -0,0 +1,91 @@
---
description: Replace the first or all occurrences of text using the edit search-and-replace tool in Roo Code.
keywords:
- edit
- search and replace
- file editing
- text replacement
- Roo Code tools
- code modifications
---
# edit
The `edit` tool performs search-and-replace operations on files, replacing either the **first occurrence** (default) or **all occurrences** when explicitly specified. It provides flexible control over replacement scope.
---
## Parameters
The tool accepts these parameters:
- `file_path` (required): The path of the file to modify relative to the current working directory.
- `old_string` (required): The exact text to search for and replace.
- `new_string` (required): The text to replace occurrences with.
- `replace_all` (optional): Boolean flag. When `true`, replaces all occurrences. When `false` or omitted, replaces only the first occurrence.
---
## What It Does
This tool searches for an exact string in a file and replaces either the first occurrence or all occurrences based on the `replace_all` parameter. By default, it replaces only the **first match**, making it suitable for targeted single-instance changes.
---
## When is it used?
- When updating a single specific occurrence of text (default behavior)
- When the first instance requires different handling than subsequent ones
- When you need explicit control over whether to replace once or globally
- When making targeted changes to specific instances without affecting others
- When replacing all instances by setting `replace_all: true`
---
## Key Features
- Replaces **first occurrence only** by default (conservative behavior)
- Optional `replace_all` parameter for global replacement
- Exact string matching (no regex or fuzzy matching)
- Shows preview of changes before applying
- Preserves file formatting and structure
- User approval required before applying changes
---
## Limitations
- Requires exact string matches (case-sensitive, whitespace-sensitive)
- Cannot use regular expressions or patterns
- Not suitable for context-dependent replacements requiring code analysis
- Less precise than [`apply_diff`](/advanced-usage/available-tools/apply-diff) for complex edits
- Cannot specify which specific occurrence to replace (first vs. second vs. third)
---
## How It Works
When the `edit` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates required `file_path`, `old_string`, and `new_string` parameters.
2. **File Loading**: Reads the target file content.
3. **Search Operation**: Searches for occurrences of `old_string` in the file.
4. **Replacement Logic**:
- If `replace_all` is `false` or omitted: replaces only the first occurrence
- If `replace_all` is `true`: replaces all occurrences
5. **User Review**: Shows a preview of changes for user approval.
6. **Application**: Applies changes to the file if approved.
7. **Feedback**: Reports the result of the operation.
---
## Relation to Other Tools
- `edit`: Replaces **first occurrence** by default (this tool)
- [`edit_file`](/advanced-usage/available-tools/edit-file): Always replaces **all occurrences**
- [`search_replace`](/advanced-usage/available-tools/search-replace): Always replaces **all occurrences**
- [`apply_diff`](/advanced-usage/available-tools/apply-diff): Use for precise, context-aware edits with fuzzy matching
:::info Deprecated Alias
`SearchAndReplaceTool` is a deprecated internal alias for `EditTool`. They are the same tool.
:::

View file

@ -0,0 +1,194 @@
---
description: Execute terminal commands in Roo Code for system operations, dependency installation, builds, and development workflows.
keywords:
- execute_command
- CLI commands
- terminal
- system operations
- Roo Code tools
- command execution
- shell integration
---
# execute_command
The `execute_command` tool runs CLI commands on the user's system. It allows Roo to perform system operations, install dependencies, build projects, start servers, and execute other terminal-based tasks needed to accomplish user objectives.
---
## Parameters
The tool accepts these parameters:
- `command` (required): The CLI command to execute. Must be valid for the user's operating system.
- `cwd` (optional): The working directory to execute the command in. If not provided, the current working directory is used.
---
## What It Does
This tool executes terminal commands directly on the user's system, enabling a wide range of operations from file manipulations to running development servers. Commands run in managed terminal instances with real-time output capture, integrated with VS Code's terminal system for optimal performance and security.
---
## When is it used?
- When installing project dependencies (npm install, pip install, etc.)
- When building or compiling code (make, npm run build, etc.)
- When starting development servers or running applications
- When initializing new projects (git init, npm init, etc.)
- When performing file operations beyond what other tools provide
- When running tests or linting operations
- When needing to execute specialized commands for specific technologies
---
## Key Features
- Integrates with VS Code shell API for reliable terminal execution
- Reuses terminal instances when possible through a registry system
- Captures command output line by line with real-time feedback
- Supports long-running commands that continue in the background
- Allows specification of custom working directories
- Maintains terminal history and state across command executions
- Handles complex command chains appropriate for the user's shell
- Provides detailed command completion status and exit code interpretation
- Supports interactive terminal applications with user feedback loop
- Shows terminals during execution for transparency
- Validates commands for security using shell-quote parsing
- Blocks potentially dangerous subshell execution patterns
- Integrates with RooIgnore system for file access control
- Handles terminal escape sequences for clean output
---
## Limitations
- Command access may be restricted by RooIgnore rules and security validations
- Commands with elevated permission requirements may need user configuration
- Behavior may vary across operating systems for certain commands
- Very long-running commands may require specific handling
- File paths should be properly escaped according to the OS shell rules
- Not all terminal features may work with remote development scenarios
---
## How It Works
When the `execute_command` tool is invoked, it follows this process:
1. **Command Validation and Security Checks**:
- Parses the command using shell-quote to identify components
- Validates against security restrictions (subshell usage, restricted files)
- Checks against RooIgnore rules for file access permissions
- Ensures the command meets system security requirements
2. **Terminal Management**:
- Gets or creates a terminal through TerminalRegistry
- Sets up the working directory context
- Prepares event listeners for output capture
- Shows the terminal for user visibility
3. **Command Execution and Monitoring**:
- Executes via VS Code's shellIntegration API
- Captures output with escape sequence processing
- Throttles output handling (100ms intervals)
- Monitors for command completion or errors
- Detects "hot" processes like compilers for special handling
4. **Result Processing**:
- Strips ANSI/VS Code escape sequences for clean output
- Interprets exit codes with detailed signal information
- Updates working directory tracking if changed by command
- Provides command status with appropriate context
---
## Terminal Implementation Details
The tool uses a sophisticated terminal management system:
1. **First Priority: Terminal Reuse**
- The TerminalRegistry tries to reuse existing terminals when possible
- This reduces proliferation of terminal instances and improves performance
- Terminal state (working directory, history) is preserved across commands
2. **Second Priority: Security Validation**
- Commands are parsed using shell-quote for component analysis
- Dangerous patterns like `$(...)` and backticks are blocked
- Commands are checked against RooIgnore rules for file access control
- A prefix-based allowlist system validates command patterns
3. **Performance Optimizations**
- Output is processed in 100ms throttled intervals to prevent UI overload
- Zero-copy buffer management uses index-based tracking for efficiency
- Special handling for compilation and "hot" processes
- Platform-specific optimizations for Windows PowerShell
4. **Error and Signal Handling**
- Exit codes are mapped to detailed signal information (SIGTERM, SIGKILL, etc.)
- Core dump detection for critical failures
- Working directory changes are tracked and handled automatically
- Clean recovery from terminal disconnection scenarios
---
## Examples When Used
- When setting up a new project, Roo runs initialization commands like `npm init -y` followed by installing dependencies.
- When building a web application, Roo executes build commands like `npm run build` to compile assets.
- When deploying code, Roo runs git commands to commit and push changes to a repository.
- When troubleshooting, Roo executes diagnostic commands to gather system information.
- When starting a development server, Roo launches the appropriate server command (e.g., `npm start`).
- When running tests, Roo executes the test runner command for the project's testing framework.
---
## Usage Examples
Running a simple command in the current directory:
```
<execute_command>
<command>npm run dev</command>
</execute_command>
```
Installing dependencies for a project:
```
<execute_command>
<command>npm install express mongodb mongoose dotenv</command>
</execute_command>
```
Running multiple commands in sequence:
```
<execute_command>
<command>mkdir -p src/components && touch src/components/App.js</command>
</execute_command>
```
Executing a command in a specific directory:
```
<execute_command>
<command>git status</command>
<cwd>./my-project</cwd>
</execute_command>
```
Building and then starting a project:
```
<execute_command>
<command>npm run build && npm start</command>
</execute_command>
```

View file

@ -0,0 +1,128 @@
---
description: Generate or edit images using AI models through the generate_image tool in Roo Code.
keywords:
- generate_image
- AI images
- image generation
- image editing
- OpenRouter
- Roo Code tools
- experimental
---
# generate_image
The `generate_image` tool creates new images from text prompts or modifies existing images using AI models. It supports two providers: **OpenRouter** and the **Roo provider**. This experimental feature enables visual content generation and transformation within your development workflow.
---
## Parameters
The tool accepts these parameters:
- `prompt` (required): The text description of what to generate or how to edit the image.
- `path` (required): The file path where the generated/edited image should be saved (relative to the workspace). The tool automatically adds the appropriate extension if not provided.
- `image` (optional): The file path to an input image to edit or transform (relative to the workspace). Supported formats: PNG, JPG, JPEG, GIF, WEBP.
---
## What It Does
This tool generates images from text descriptions or applies transformations to existing images using AI models. When no input image is provided, it creates new images from scratch. When an input image is provided, it applies the prompt as editing instructions to transform the image.
---
## When is it used?
- When creating visual assets for documentation, mockups, or prototypes
- When generating placeholder images or illustrations
- When transforming existing images (style transfer, enhancement, modifications)
- When creating diagrams or visual explanations from descriptions
- When prototyping UI elements visually
---
## Key Features
- **Text-to-image generation**: Create images from descriptive prompts
- **Image-to-image transformation**: Edit or transform existing images
- Supports multiple input formats (PNG, JPG, JPEG, GIF, WEBP)
- Automatic file extension handling
- Powered by **OpenRouter** or the **Roo provider** for access to various AI models
- Experimental feature with ongoing improvements
---
## Limitations
- Requires OpenRouter or Roo provider API configuration
- Image quality depends on the AI model and prompt quality
- Generation time varies based on complexity and model
- Experimental feature: behavior may change in future releases
- API usage may incur costs based on OpenRouter pricing
- Some image transformations may not produce expected results
---
## How It Works
When the `generate_image` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates required `prompt` and `path` parameters.
2. **Mode Selection**:
- If `image` parameter is provided: operates in **edit mode** (transform existing image)
- Otherwise: operates in **generation mode** (create new image from prompt)
3. **API Request**: Sends request to the configured provider (OpenRouter or Roo) with prompt and optional input image.
4. **Image Processing**: Receives generated/edited image from the API.
5. **File Saving**: Saves the image to the specified `path` with appropriate extension.
6. **Feedback**: Reports success and the location of the generated image.
---
## Usage Examples
Generating a new image:
```
<generate_image>
<prompt>A beautiful sunset over mountains with vibrant orange and purple colors</prompt>
<path>images/sunset.png</path>
</generate_image>
```
Editing an existing image:
```
<generate_image>
<prompt>Transform this image into a watercolor painting style</prompt>
<path>images/watercolor-output.png</path>
<image>images/original-photo.jpg</image>
</generate_image>
```
Upscaling and enhancing:
```
<generate_image>
<prompt>Upscale this image to higher resolution, enhance details, improve clarity and sharpness while maintaining the original content and composition</prompt>
<path>images/enhanced-photo.png</path>
<image>images/low-res-photo.jpg</image>
</generate_image>
```
---
## Relation to Features
The `generate_image` tool is the programmatic interface to the [Image Generation](/features/image-generation) feature. For comprehensive documentation on configuration, model selection, API setup, and advanced usage, see the [Image Generation feature documentation](/features/image-generation).
---
## Configuration
Image generation requires OpenRouter API configuration. See the [Image Generation](/features/image-generation) feature page for detailed setup instructions including:
- OpenRouter API key configuration
- Model selection and capabilities
- Best practices for prompts
- Troubleshooting and limitations

View file

@ -0,0 +1,168 @@
---
description: Learn how the list_files tool helps Roo Code explore project structures, list directories, and navigate codebases with recursive and filtered listing capabilities.
keywords:
- list_files
- Roo Code tools
- directory listing
- file exploration
- project structure
- recursive listing
- codebase navigation
- VS Code AI
---
# list_files
The `list_files` tool displays the files and directories within a specified location. It helps Roo understand your project structure and navigate your codebase effectively.
---
## Parameters
The tool accepts these parameters:
- `path` (required): The path of the directory to list contents for, relative to the current working directory
- `recursive` (optional): Whether to list files recursively. Use `true` for recursive listing, `false` or omit for top-level only.
---
## What It Does
This tool lists all files and directories in a specified location, providing a clear overview of your project structure. It can either show just the top-level contents or recursively explore subdirectories.
---
## When is it used?
- When Roo needs to understand your project structure
- When Roo explores what files are available before reading specific ones
- When Roo maps a codebase to better understand its organization
- Before using more targeted tools like `read_file` or `search_files`
- When Roo needs to check for specific file types (like configuration files) across a project
---
## Key Features
- Lists both files and directories with directories clearly marked
- Offers both recursive and non-recursive listing modes
- Intelligently ignores common large directories like `node_modules` and `.git` in recursive mode
- Respects `.gitignore` rules when in recursive mode
- Marks files ignored by `.rooignore` with a lock symbol (🔒) when `showRooIgnoredFiles` is enabled
- Optimizes file listing performance by leveraging the `ripgrep` tool.
- Sorts results to show directories before their contents, maintaining a logical hierarchy
- Presents results in a clean, organized format
- Automatically creates a mental map of your project structure
---
## Limitations
- File listing is capped at about 200 files by default to prevent performance issues
- The underlying `ripgrep` file listing process has a 10-second timeout; if exceeded, partial results may be returned.
- When the file limit is hit, it adds a note suggesting to use `list_files` on specific subdirectories
- Not designed for confirming the existence of files you've just created
- May have reduced performance in very large directory structures
- Cannot list files in root or home directories for security reasons
---
## How It Works
When the `list_files` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates the required `path` parameter and optional `recursive` parameter
2. **Path Resolution**: Resolves the relative path to an absolute path
3. **Security Checks**: Prevents listing files in sensitive locations like root or home directories
4. **Directory/File Scanning**:
- Uses the `ripgrep` tool to efficiently list files, applying a 10-second timeout.
- Uses Node.js `fs` module to list directories.
- Applies different filtering logic for recursive vs. non-recursive modes.
5. **Result Filtering**:
- In recursive mode, skips common large directories like `node_modules`, `.git`, etc.
- Respects `.gitignore` rules when in recursive mode
- Handles `.rooignore` patterns, either hiding files or marking them with a lock symbol
6. **Formatting**:
- Marks directories with a trailing slash (`/`)
- Sorts results to show directories before their contents for logical hierarchy
- Marks ignored files with a lock symbol (🔒) when `showRooIgnoredFiles` is enabled
- Caps results at 200 files by default with a note about using subdirectories
- Organizes results for readability
---
## File Listing Format
The file listing results include:
- Each file path is displayed on its own line
- Directories are marked with a trailing slash (`/`)
- Files ignored by `.rooignore` are marked with a lock symbol (🔒) when `showRooIgnoredFiles` is enabled
- Results are sorted logically with directories appearing before their contents
- When the file limit is reached, a message appears suggesting to use `list_files` on specific subdirectories
Example output format:
```
src/
src/components/
src/components/Button.tsx
src/components/Header.tsx
src/utils/
src/utils/helpers.ts
src/index.ts
...
File listing truncated (showing 200 of 543 files). Use list_files on specific subdirectories for more details.
```
When `.rooignore` files are used and `showRooIgnoredFiles` is enabled:
```
src/
src/components/
src/components/Button.tsx
src/components/Header.tsx
🔒 src/secrets.json
src/utils/
src/utils/helpers.ts
src/index.ts
```
---
## Examples When Used
- When starting a new task, Roo may list the project files to understand its structure before diving into specific code.
- When asked to find specific types of files (like all JavaScript files), Roo first lists directories to know where to look.
- When providing recommendations for code organization, Roo examines the current project structure first.
- When setting up a new feature, Roo lists related directories to understand the project conventions.
---
## Usage Examples
Listing top-level files in the current directory:
```
<list_files>
<path>.</path>
</list_files>
```
Recursively listing all files in a source directory:
```
<list_files>
<path>src</path>
<recursive>true</recursive>
</list_files>
```
Examining a specific project subdirectory:
```
<list_files>
<path>src/components</path>
<recursive>false</recursive>
</list_files>
```

View file

@ -0,0 +1,171 @@
---
description: Discover how the new_task tool enables complex workflow management by creating subtasks with different modes, maintaining parent-child relationships for organized development.
keywords:
- new_task
- Roo Code tools
- subtasks
- workflow management
- task hierarchy
- mode switching
- complex projects
- task organization
- VS Code AI
---
# new_task
The `new_task` tool creates subtasks with specialized modes while maintaining a parent-child relationship. It breaks down complex projects into manageable pieces, each operating in the mode best suited for specific work.
---
## Parameters
The tool accepts these parameters:
- `mode` (required): The slug of the mode to start the new task in (e.g., "code", "ask", "architect")
- `message` (required): The initial user message or instructions for this new task
- `todos` (optional): Initial todo list in markdown checklist format
---
## What It Does
This tool creates a new task instance with a specified starting mode and initial message. It allows complex workflows to be divided into subtasks with their own conversation history. Parent tasks are paused during subtask execution and resumed when the subtask completes, with results transferred back to the parent.
---
## When is it used?
- When breaking down complex projects into separate, focused subtasks
- When different aspects of a task require different specialized modes
- When different phases of work benefit from context separation
- When organizing multi-phase development workflows
---
## Key Features
- Creates subtasks with their own conversation history and specialized mode
- Pauses parent tasks for later resumption
- Maintains hierarchical task relationships for navigation
- Transfers results back to parent tasks upon completion
- Supports workflow segregation for complex projects
- Allows different parts of a project to use modes optimized for specific work
- Requires explicit user approval for task creation
- Provides clear task transition in the UI
---
## Limitations
- Cannot create tasks with modes that don't exist
- Requires user approval before creating each new task
- Task interface may become complex with deeply nested subtasks
- Subtasks inherit certain workspace and extension configurations from parents
- May require re-establishing context when switching between deeply nested tasks
- Task completion needs explicit signaling to properly return to parent tasks
---
## How It Works
When the `new_task` tool is invoked, it follows this process:
1. **Parameter Validation**:
- Validates the required `mode` and `message` parameters
- Verifies that the requested mode exists in the system
2. **Task Stack Management**:
- Maintains a task stack that tracks all active and paused tasks
- Preserves the current mode for later resumption
- Sets the parent task to paused state
3. **Task Context Management**:
- Creates a new task context with the provided message
- Assigns unique taskId and instanceId identifiers for state management
- Captures telemetry data on tool usage and task lifecycles
4. **Mode Switching and Integration**:
- Switches to the specified mode with appropriate role and capabilities
- Initializes the new task with the provided message
- Integrates with VS Code's command palette and code actions
5. **Task Completion and Result Transfer**:
- When subtask completes, result is passed back to parent task via `finishSubTask()`
- Parent task resumes in its original mode
- Task history and token usage metrics are updated
- The `taskCompleted` event is emitted with performance data
---
## Configuration
Streamline hierarchical task planning with the optional todo list parameter for subtasks:
- **Pass Todo Lists**: Include predefined todo lists when creating subtasks
- **Maintain Context**: Pass along context to the subtask in the form of a todo list
- **Optional Enforcement**: The "New Task Require Todos" setting in VS Code can enforce todo lists for all new subtasks if desired
<img src="/img/v3.25.21/v3.25.21.png" alt="Subtask todo lists configuration in VS Code settings" width="600" />
This feature works out of the box, and you can optionally configure VS Code settings to require todos for all new tasks.
---
## Examples When Used
- When a front-end developer needs to architect a new feature, implement the code, and document it, they can create separate tasks for each phase with results flowing from one phase to the next.
- When debugging an issue before implementing a fix, the debugging task can document findings that are passed to the implementation task.
- When developing a full-stack application, database schema designs from an architect-mode task inform implementation details in a subsequent code-mode task.
- When documenting a system after implementation, the documentation task can reference the completed implementation while using documentation-specific features.
---
## Usage Examples
Creating a new task in code mode:
```
<new_task>
<mode>code</mode>
<message>Implement a user authentication service with login, registration, and password reset functionality.</message>
</new_task>
```
Creating a documentation task after completing implementation:
```
<new_task>
<mode>docs</mode>
<message>Create comprehensive API documentation for the authentication service we just built.</message>
</new_task>
```
Breaking down a complex feature into architectural planning and implementation:
```
<new_task>
<mode>architect</mode>
<message>Design the database schema and system architecture for our new e-commerce platform.</message>
</new_task>
```
Creating a task with an initial todo list:
```
<new_task>
<mode>code</mode>
<message>Build a REST API for user management</message>
<todos>
[ ] Set up Express server
[ ] Create user model
[ ] Implement CRUD endpoints
[ ] Add authentication middleware
[ ] Write API tests
</todos>
</new_task>
```

View file

@ -0,0 +1,126 @@
---
description: Retrieve full command output that was truncated in execute_command using the read_command_output tool in Roo Code.
keywords:
- read_command_output
- command output
- truncated output
- CLI output
- terminal output
- Roo Code tools
- artifact retrieval
---
# read_command_output
The `read_command_output` tool retrieves the full output from commands executed via [`execute_command`](/advanced-usage/available-tools/execute-command) when the output was too large and got truncated. It provides access to stored command output artifacts with advanced filtering and pagination capabilities.
---
## Parameters
The tool accepts these parameters:
- `artifact_id` (required): The artifact filename from the truncated output message (e.g., `cmd-1706119234567.txt`).
- `search` (optional): Pattern to filter lines (supports regex or literal strings). Case-insensitive. Similar to `grep`. **Omit entirely if not needed** (do not pass null or empty string).
- `offset` (optional): Byte offset to start reading from for pagination. Default: 0.
- `limit` (optional): Maximum bytes to return. Default: 40KB (40960 bytes).
---
## What It Does
When [`execute_command`](/advanced-usage/available-tools/execute-command) produces very large output, it gets truncated and saved to an artifact file. This tool retrieves the full output from those artifacts, with support for searching specific patterns (like grep) and paginating through large results.
---
## When is it used?
- When [`execute_command`](/advanced-usage/available-tools/execute-command) output includes the message: `[OUTPUT TRUNCATED - Full output saved to artifact: cmd-XXXX.txt]`
- When you need to search for specific errors or patterns in large command output
- When analyzing verbose build logs, test results, or compilation output
- When paginating through command output that's too large to view at once
- When filtering command output to find relevant lines without reading everything
---
## Key Features
- **Read mode**: Access full output with pagination using `offset` and `limit`
- **Search mode**: Filter lines matching a regex or literal pattern (case-insensitive)
- Handles very large command outputs efficiently
- Similar to `grep` for filtering output
- Byte-level pagination for precise control
- Access to complete untruncated command output
---
## Limitations
- Only works with artifacts created by [`execute_command`](/advanced-usage/available-tools/execute-command)
- Artifacts may be cleaned up after a certain time period
- Search patterns are case-insensitive only
- Returns content as bytes with limits (not entire files at once for very large outputs)
- Requires the exact artifact ID from the truncation message
---
## How It Works
When the `read_command_output` tool is invoked, it follows this process:
1. **Artifact Lookup**: Locates the stored command output artifact by ID.
2. **Mode Selection**:
- If `search` parameter is provided: operates in **search mode** (filter lines)
- Otherwise: operates in **read mode** (return raw content with offset/limit)
3. **Search Mode** (if `search` provided):
- Applies regex or literal pattern matching to each line
- Returns only lines that match the pattern
- Case-insensitive matching
4. **Read Mode** (if no `search`):
- Reads from `offset` byte position
- Returns up to `limit` bytes
- Supports pagination through large files
5. **Result Return**: Returns filtered or paginated content.
---
## Usage Examples
Reading truncated output:
```
When execute_command shows:
"[OUTPUT TRUNCATED - Full output saved to artifact: cmd-1706119234567.txt]"
Use:
<read_command_output>
<artifact_id>cmd-1706119234567.txt</artifact_id>
</read_command_output>
```
Searching for errors:
```
<read_command_output>
<artifact_id>cmd-1706119234567.txt</artifact_id>
<search>error|failed|Error</search>
</read_command_output>
```
Paginating through output (reading next chunk):
```
<read_command_output>
<artifact_id>cmd-1706119234567.txt</artifact_id>
<offset>40960</offset>
<limit>40960</limit>
</read_command_output>
```
---
## Relation to Other Tools
- [`execute_command`](/advanced-usage/available-tools/execute-command): Creates the artifacts that this tool reads
- [`search_files`](/advanced-usage/available-tools/search-files): Use for searching project files with regex
- `read_command_output`: Use for searching command output artifacts

View file

@ -0,0 +1,708 @@
---
description: Explore the read_file tool's capabilities for examining file contents, supporting line ranges, PDF/DOCX extraction, image reading, and experimental multi-file concurrent reading.
keywords:
- read_file
- Roo Code tools
- file reading
- concurrent reads
- line numbers
- PDF extraction
- DOCX support
- image support
- OCR workflows
- code analysis
- VS Code AI
---
# read_file
The `read_file` tool examines the contents of files in a project. It allows Roo to understand code, configuration files, documentation, and now images to provide better assistance.
:::info Multi-File Support
The `read_file` tool accepts multiple files via the `args` format. Concurrency and perrequest limits are configured in the UI; the backend tool doesnt hardenforce a file count cap. Some models may use a simplified singlefile variant.
**Note:** When reading files (even single files), the LLM will see a message encouraging multi-file reads: "Reading multiple files at once is more efficient for the LLM. If other files are relevant to your current task, please read them simultaneously."
:::
---
## Parameters
The tool accepts parameters in two formats:
### Standard Format (Single File)
- `path` (required): The path of the file to read relative to the current working directory
- `mode` (optional): Reading mode — `"slice"` (default) or `"indentation"`
- `offset` (optional): 1-based line offset to start reading from (slice mode only, default: `1`)
- `limit` (optional): Maximum number of lines to return (slice mode only, default: `2000`)
- `indentation` (optional): Indentation-mode options — only used when `mode="indentation"`:
- `anchor_line` (required): 1-based line number to anchor the extraction. The tool extracts the complete semantic code block (function, class, method) containing this line.
- `max_levels` (optional): Maximum indentation levels to include above the anchor.
- `include_siblings` (optional): Whether to include sibling blocks at the same indentation level.
- `include_header` (optional): Whether to include file header content (imports, module-level comments) at the top of output.
- `max_lines` (optional): Hard cap on lines returned in indentation mode.
:::note Mode Summary
- **Slice mode** (default): Reads lines sequentially from `offset` up to `limit` lines. Use for initial file exploration or reading a specific line range.
- **Indentation mode**: Extracts complete, syntactically valid code blocks around `anchor_line` based on indentation hierarchy. Preferred when you have a target line number (e.g., from search results or error messages) and need the entire function/class without mid-function truncation.
- **`start_line` and `end_line` do not exist** as parameters. Use `offset` and `limit` for range reads in slice mode.
:::
### Enhanced Format (Multi-File)
The tool also accepts an `args` parameter containing multiple file entries. Concurrency is UIconfigured; the backend accepts multiple files regardless of that setting. Some models may use a simple singlefile tool.
- `args` (required): Container for multiple file specifications
- `file` (required): Individual file specification
- `path` (required): The path of the file to read
- `line_range` (optional): Line range specification (e.g., "1-50" or "100-150"). Multiple `line_range` elements can be specified per file.
---
## What It Does
This tool reads the content of a specified file and returns it with line numbers for easy reference. It can read entire files or specific sections, extract text from PDFs and Word documents, and display images in various formats.
---
## When is it used?
- When Roo needs to understand existing code structure
- When Roo needs to analyze configuration files
- When Roo needs to extract information from text files
- When Roo needs to see code before suggesting changes
- When specific line numbers need to be referenced in discussions
---
## Key Features
- Displays file content with line numbers for easy reference
- Can read specific portions of files by specifying line ranges
- Extracts readable text from PDF, DOCX, XLSX, and IPYNB files
- **Image support**: Displays images in multiple formats (PNG, JPG, JPEG, GIF, WebP, SVG, BMP, ICO, TIFF/TIF, AVIF)
- **Intelligent reading**: Token-budget aware reading that auto-truncates to fit remaining budget instead of failing
- **Large file preview**: Returns a 100KB preview for very large files to enable quick inspection
- **Graceful error recovery**: Recovers from stream errors and guides you to use line_range for targeted reads
- Automatically truncates large text files when no line range is specified, showing the beginning of the file
- Efficiently streams only requested line ranges for better performance
- Makes it easy to discuss specific parts of code with line numbering
- **Multi-file support**: Read multiple files simultaneously with batch approval
---
## Multi-File Capabilities
Multi-file reads are supported. Concurrency and perrequest limits are configured in Settings; the backend tool doesnt hardenforce a file count cap and behavior may be constrained by model/tool selection:
### Configuration
- **Location**: Settings > Context > "Concurrent file reads limit"
- **Description**: "Maximum number of files the 'read_file' tool can process concurrently. Higher values may speed up reading multiple small files but increase memory usage."
- **Range**: 1-100 (slider control)
- **Default**: 5
### Batch Processing
- UIconfigurable limit up to 100 files per request (default 5). Backend doesnt hardenforce a cap; actual behavior may be constrained by model/tool.
- Parallel processing for improved performance
- Batch approval interface for user consent
### Enhanced User Experience
- Single approval dialog for multiple files
- Individual file override options
- Clear visibility into which files will be accessed
- Graceful handling of mixed success/failure scenarios
### Improved Efficiency
- Reduces interruptions from multiple approval dialogs
- Faster processing through parallel file reading
- Smart batching of related files
- Configurable concurrency limits to match system capabilities
---
## Limitations
- **Large files**: For extremely large files, the tool may return a preview and will guide you to use `line_range` for targeted reading.
- **Binary files**: Except for PDF, DOCX, XLSX, IPYNB, and supported image formats, content may not be humanreadable.
- **UI/model constraints**: Concurrency limits and perrequest file counts are configured in the UI; the backend tool doesnt hardenforce a cap.
- **Image files**: Images are provided as base64 data URLs. Highresolution images can be large.
- Default max single image size: 5MB
- Default max total image size: 20MB
- **Unsupported binary formats**: Returns a `<binary_file format="ext">Binary file - content not displayed</binary_file>` placeholder.
- **Token budget**: Content may be truncated to fit remaining token budget; notices indicate how to proceed.
---
## How It Works
When the `read_file` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates the required `path` parameter and optional parameters
2. **Path Resolution**: Resolves the relative path to an absolute path
3. **Reading Strategy Selection**:
- The tool uses a strict priority hierarchy (explained in detail below)
- It chooses between range reading, auto-truncation, or full file reading
4. **Content Processing**:
- Adds line numbers to the content (e.g., "1 | const x = 13") where `1 |` is the line number.
- For truncated files, adds truncation notice and method definitions
- For special formats (PDF, DOCX, XLSX, IPYNB), extracts readable text
- For image formats, the XML includes a `<notice>` with size; the actual image is attached to the tool result as a base64 data URL (no dimensions returned; MIME type is implied by the data URL)
---
## Reading Strategy Priority
The tool uses a clear decision hierarchy to determine how to read a file:
1. **First Priority: Explicit Line Range**
- Singlefile format: specify `offset` and `limit` for a range read in slice mode, or use `anchor_line` in indentation mode.
- Multifile `args` format: specify one or more `line_range` entries per file.
- Range reads stream only the requested lines and bypass `maxReadFileLine`, taking precedence over other options.
2. **Second Priority: Token Budget Management**
- The tool respects the remaining token budget to prevent context overruns
- If a file would exceed the remaining budget, it automatically truncates to fit
- For very large files (exceeding practical limits), returns a 100KB preview for quick inspection
- Provides guidance to use `line_range` for targeted reading of specific sections
- Recovers gracefully from stream errors and suggests alternative approaches
3. **Third Priority: Automatic Truncation for Large Text Files**
- Applies only when all of the following are true:
- No `offset`/`limit` range is specified (slice mode) and no `anchor_line` is provided (indentation mode).
- The file is identified as a textbased file (not binary like PDF/DOCX/XLSX/IPYNB).
- The file's total line count exceeds the `maxReadFileLine` setting (configurable; UI default may be 500; backend uses `-1`—no line limit—when unset).
- When automatic truncation occurs:
- The tool reads only the first `maxReadFileLine` lines.
- It appends a notice like: `Showing only X of Y total lines. Use line_range if you need to read more lines.`
- **Special Case DefinitionsOnly Mode**: When `maxReadFileLine` is `0`, the tool returns only code definitions without file content (plus a notice).
4. **Default Behavior: Read Entire File**
- If neither an explicit range is given nor automatic truncation applies (e.g., the file is within the line limit, or it's a supported binary type), the tool reads the entire content.
- For supported formats like PDF and DOCX, it attempts to extract the full text content.
- For image formats, it returns a base64-encoded data URL that can be displayed in the chat interface.
---
## Examples When Used
- When asked to explain or improve code, Roo first reads the relevant files to understand the current implementation.
- When troubleshooting configuration issues, Roo reads config files to identify potential problems.
- When working with documentation, Roo reads existing docs to understand the current content before suggesting improvements.
---
## Usage Examples
Here are several scenarios demonstrating how the `read_file` tool is used and the typical output you might receive.
### Reading an Entire File
To read the complete content of a file:
**Input:**
```xml
<read_file>
<path>src/app.js</path>
</read_file>
```
**Simulated Output (for a small file like `example_small.txt`):**
```
1 | This is the first line.
2 | This is the second line.
3 | This is the third line.
```
_(Output will vary based on the actual file content)_
### Reading Specific Lines
To read only a specific range of lines (e.g., lines 46-68), use `offset` and `limit` in slice mode:
**Input:**
```xml
<read_file>
<path>src/app.js</path>
<offset>46</offset>
<limit>23</limit>
</read_file>
```
**Simulated Output (for lines 2-3 of `example_five_lines.txt`):**
```
2 | Content of line two.
3 | Content of line three.
```
_(Output shows only the requested lines with their original line numbers)_
### Reading a Large Text File (Automatic Truncation)
When reading a large text file without specifying a line range, the tool automatically truncates the content if it exceeds the internal line limit (e.g., 500 lines).
**Input:**
```xml
<read_file>
<path>logs/large_app.log</path>
</read_file>
```
**Simulated Output (for a 1500-line log file with a 500-line limit):**
```
1 | Log entry 1...
2 | Log entry 2...
...
500 | Log entry 500...
Showing only 500 of 1500 total lines. Use line_range to read specific sections.
// Optional: Source code definitions summary might appear here for code files
```
_(Output shows the beginning lines up to the `maxReadFileLine` limit, plus a truncation notice. Use line ranges for full access.)_
### Reading Definitions Only
When `maxReadFileLine` is set to `0` in user settings, the tool returns only source code definitions without file content:
**Input:**
```xml
<!-- Assuming maxReadFileLine is set to 0 in user settings -->
<read_file>
<path>src/services/auth.service.ts</path>
</read_file>
```
**Simulated Output:**
```xml
<file>
<path>src/services/auth.service.ts</path>
<notice>Showing only 0 of 150 total lines. Use line_range if you need to read more lines</notice>
</file>
```
_(This mode provides a quick overview of file structure without reading content.)_
### Attempting to Read a Non-Existent File
If the specified file does not exist:
**Input:**
```xml
<read_file>
<path>non_existent_file.txt</path>
</read_file>
```
**Simulated Output (Error):**
```
Error: File not found at path 'non_existent_file.txt'.
```
### Attempting to Read a Blocked File
If the file is excluded by rules in a `.rooignore` file:
**Input:**
```xml
<read_file>
<path>.env</path>
</read_file>
```
**Simulated Output (Error):**
```xml
<file>
<path>.env</path>
<error>Access denied by .rooignore rules</error>
</file>
```
---
### Intelligent Reading with Token Budget Management
When reading large files, the tool automatically manages token budgets to prevent context overruns.
**Scenario:** Reading a very large file without specifying a line range.
**Input:**
```xml
<read_file>
<path>logs/massive-debug.log</path>
</read_file>
```
**Simulated Output (for a file exceeding token budget):**
```
Preview: Showing first …MB of …MB file. Use line_range to read specific sections.
```
Alternative truncation notice:
```
File truncated to N of M characters due to context limitations. Use line_range to read specific sections.
```
This behavior ensures that:
- Small files read completely with zero overhead
- Large files autotruncate to fit remaining token budget
- Very large files provide a quick preview
- You receive guidance to use `line_range` for targeted reads
- Stream errors are handled gracefully
**Example with offset/limit for targeted reading:**
```xml
<read_file>
<path>logs/massive-debug.log</path>
<offset>1000</offset>
<limit>101</limit>
</read_file>
```
## Image Reading Examples
The `read_file` tool now supports reading and displaying images directly in the chat interface. This enables powerful visual analysis workflows.
### Reading a Single Image
**Input:**
```xml
<read_file>
<path>assets/logo.png</path>
</read_file>
```
**Output:**
```xml
<file>
<path>assets/logo.png</path>
<notice>Image file (123 KB)</notice>
</file>
```
The image is displayed inline in the chat (base64 data URL attached to the tool result). No dimensions are returned; MIME type is implied by the data URL.
### OCR Workflow Example
Reading multiple images from a folder for text extraction:
**Input:**
```xml
<read_file>
<args>
<file>
<path>screenshots/page1.png</path>
</file>
<file>
<path>screenshots/page2.png</path>
</file>
<file>
<path>screenshots/page3.png</path>
</file>
</args>
</read_file>
```
**Usage:**
```
Please extract all text from these screenshot images and compile them into a single markdown document.
```
### Design Review Workflow
Analyzing multiple design mockups:
**Input:**
```xml
<read_file>
<args>
<file>
<path>designs/homepage-v1.jpg</path>
</file>
<file>
<path>designs/homepage-v2.jpg</path>
</file>
<file>
<path>designs/mobile-view.png</path>
</file>
</args>
</read_file>
```
**Usage:**
```
Compare these design mockups and provide feedback on:
1. Visual consistency
2. Mobile responsiveness
3. Accessibility concerns
4. UI/UX improvements
```
### Supported Image Formats
The tool supports the following image formats:
- PNG
- JPG/JPEG
- GIF
- WebP
- SVG
- BMP
- ICO
- TIFF/TIF
- AVIF
### Image Analysis Use Cases
1. **Documentation Screenshots**: Extract text and create documentation from UI screenshots
2. **Error Debugging**: Analyze error screenshots to understand issues
3. **Design Reviews**: Compare mockups and provide visual feedback
4. **Diagram Analysis**: Understand architecture diagrams and flowcharts
5. **Code Screenshots**: Extract code from images when text isn't available
6. **UI Testing**: Verify visual elements and layouts
---
## Multi-File Examples
You can read multiple files simultaneously using the enhanced XML format.
### Reading Multiple Complete Files
To read several complete files at once:
**Input:**
```xml
<read_file>
<args>
<file>
<path>src/app.ts</path>
</file>
<file>
<path>src/utils.ts</path>
</file>
<file>
<path>src/config.json</path>
</file>
</args>
</read_file>
```
**Simulated Output:**
```xml
<files>
<file>
<path>src/app.ts</path>
<content>
1 | import React from 'react'
2 | import { Utils } from './utils'
3 | // ... rest of file content
</content>
</file>
<file>
<path>src/utils.ts</path>
<content>
1 | export class Utils {
2 | static formatDate(date: Date): string {
3 | // ... utility functions
</content>
</file>
<file>
<path>src/config.json</path>
<content>
1 | {
2 | "apiUrl": "https://api.example.com",
3 | "timeout": 5000
4 | }
</content>
</file>
</files>
```
### Reading Specific Line Ranges from Multiple Files
To read specific sections from multiple files:
**Input:**
```xml
<read_file>
<args>
<file>
<path>src/app.ts</path>
<line_range>1-20</line_range>
<line_range>45-60</line_range>
</file>
<file>
<path>src/utils.ts</path>
<line_range>10-25</line_range>
</file>
</args>
</read_file>
```
**Simulated Output:**
```xml
<files>
<file>
<path>src/app.ts</path>
<content>
1 | import React from 'react'
2 | import { Utils } from './utils'
...
20 | const App = () => {
45 | const handleSubmit = () => {
46 | // Handle form submission
...
60 | }
</content>
</file>
<file>
<path>src/utils.ts</path>
<content>
10 | static formatDate(date: Date): string {
11 | return date.toISOString().split('T')[0]
...
25 | }
</content>
</file>
</files>
```
### Handling Mixed Results (Some Files Denied/Blocked)
When some files are approved and others are denied or blocked:
**Input:**
```xml
<read_file>
<args>
<file>
<path>src/app.ts</path>
</file>
<file>
<path>.env</path>
</file>
<file>
<path>src/secret-config.ts</path>
</file>
</args>
</read_file>
```
**Simulated Output:**
```xml
<files>
<file>
<path>src/app.ts</path>
<content>
1 | import React from 'react'
2 | // ... file content successfully read
</content>
</file>
<file>
<path>.env</path>
<error>Access denied by .rooignore rules</error>
</file>
<file>
<path>src/secret-config.ts</path>
<error>User denied access to file</error>
</file>
</files>
```
### Batch Approval Interface
When requesting multiple files, you'll see a batch approval interface that allows you to:
- **Approve All**: Grant access to all requested files
- **Deny All**: Deny access to all requested files
- **Individual Control**: Override decisions for specific files
- **File Preview**: Click file headers to open them in your editor
The interface displays each file path clearly, making it easy to understand what Roo wants to access before granting permission.
### Mixed Content Types
You can read different types of files in a single request:
**Input:**
```xml
<read_file>
<args>
<file>
<path>README.md</path>
</file>
<file>
<path>architecture-diagram.png</path>
</file>
<file>
<path>config.json</path>
</file>
<file>
<path>requirements.pdf</path>
</file>
</args>
</read_file>
```
This allows Roo to analyze documentation, visual diagrams, configuration, and specifications all in one context.
---
## Troubleshooting
- Range read returns error
- Cause: Invalid `offset` or `limit` values (e.g., non-positive integers).
- Fix: Use `offset` (1-based starting line) and `limit` (max lines to return) as positive integers in slice mode; or use `anchor_line` in indentation mode; or use the multi-file `args` format with `line_range` entries.
- Prevention: Prefer the multi-file `args` format with `line_range` for targeted reads across multiple files.
- Large file returned a preview
- Cause: File exceeded token budget or the largefile tokenization threshold; a preview was returned.
- Fix: Use `line_range` to request only the section you need; reduce requested ranges.
- Prevention: Adjust `maxReadFileLine` in Settings, or prefer targeted ranges on large files.
- Image not displayed
- Cause: Model may not support images, or image limits exceeded (5MB per image; 20MB total per request).
- Fix: Switch to a visioncapable model; reduce image size; request fewer/smaller images.
- Prevention: Keep images within limits and use supported formats (PNG, JPG/JPEG, GIF, WebP, SVG, BMP, ICO, TIFF/TIF, AVIF).

View file

@ -0,0 +1,359 @@
---
description: Execute predefined slash commands that provide templated instructions for common tasks, with support for built-in, global, and project-specific commands in Roo Code.
keywords:
- run_slash_command
- slash commands
- command templates
- Roo Code tools
- workflow automation
- instruction templates
- custom commands
- experimental feature
---
# run_slash_command
:::warning Experimental Feature
The `run_slash_command` tool is an experimental feature that must be explicitly enabled in settings. Navigate to Settings > Experimental Settings and enable "Run Slash Command" to use this tool.
:::
The `run_slash_command` tool executes predefined slash commands to retrieve specific instructions or content templates. These commands act as reusable instruction sets for common tasks, providing detailed guidance that Roo can interpret and execute. Commands can be defined at three levels with a clear priority hierarchy: project > global > built-in.
---
## Parameters
The tool accepts these parameters:
- `command` (required): Name of the slash command to execute (without the leading slash)
- `args` (optional): Additional arguments or context to pass to the command
---
## What It Does
This tool retrieves and executes instruction templates defined as markdown files in command directories. It enables standardized workflows, reusable task instructions, and team-wide consistency through shared command templates. The tool validates experimental flag status, resolves commands through the priority hierarchy, and returns formatted instructions for Roo to interpret.
---
## When is it used?
- When executing standardized workflows that require consistent steps
- When retrieving project-specific or team-wide instruction templates
- When initializing codebases with analysis and documentation
- When accessing complex multi-step processes as single commands
- When maintaining consistency across team development practices
---
## Key Features
- **Three-Level Command System**: Built-in, global (~/.roo/commands/), and project-specific (.roo/commands/) commands
- **Priority Hierarchy**: Project commands override global, which override built-in commands
- **Markdown-Based Templates**: Simple `.md` files with optional YAML frontmatter for metadata
- **Dynamic Arguments**: Pass context-specific arguments to customize command execution
- **Automatic Discovery**: Commands are automatically found from their respective directories
- **Safe Execution**: Commands are text-only instructions requiring user approval, not executable code
- **Metadata Support**: Optional frontmatter for descriptions and argument hints
- **Error Recovery**: Graceful handling with helpful error messages and command suggestions
- **No Registration Required**: Simply place `.md` files in command directories
---
## Requirements
This tool requires explicit enablement:
1. Open VS Code Settings
2. Navigate to Experimental Settings
3. Enable "Run Slash Command"
4. Restart VS Code if necessary
---
## Limitations
- **Experimental Status**: Feature is disabled by default and requires opt-in
- **Text-Only Instructions**: Commands provide instructions, not direct code execution
- **Approval Required**: All command executions require user approval
- **Directory-Based**: Commands must be in specific directory locations
- **Case-Sensitive**: Command names are matched with case sensitivity
- **Single Command**: Can only execute one command per tool invocation
---
## How It Works
When the `run_slash_command` tool is invoked, it follows this process:
1. **Experimental Flag Validation**:
- Checks if the `runSlashCommand` experiment is enabled
- Returns descriptive error if feature is disabled
- Provides instructions for enabling the feature
2. **Parameter Processing**:
- Validates the required `command` parameter
- Captures optional `args` for command customization
- Increments mistake counter for missing parameters
3. **Command Resolution**:
- Searches project directory first (`.roo/commands/`)
- Falls back to global directory (`~/.roo/commands/`)
- Finally checks built-in commands
- Returns undefined if command doesn't exist
4. **Command Loading**:
- Reads the markdown file for the command
- Parses optional YAML frontmatter using `gray-matter`
- Extracts description and argument hints if present
- Returns command content without frontmatter
5. **Response Formatting**:
- Includes command name and source location
- Adds description and argument hints if available
- Shows provided arguments for context
- Returns the full command content for interpretation
6. **Error Handling**:
- Lists available commands if requested command not found
- Provides helpful error messages with alternatives
- Tracks consecutive mistakes for error patterns
---
## Command Structure
### File Format
Commands are markdown files placed in designated directories:
```markdown
---
description: Brief description of what this command does
argument-hint: What arguments this command accepts
---
# Command Content
Detailed instructions for the task go here.
This can include:
- Step-by-step procedures
- Code templates
- Configuration examples
- Best practices
```
### Naming Convention
- File name becomes the command name
- Use `.md` extension
- Example: `deploy.md` creates `/deploy` command
- Case-sensitive matching
### Directory Locations
1. **Built-in Commands**: Hardcoded in source code
2. **Global Commands**: `~/.roo/commands/`
3. **Project Commands**: `<project-root>/.roo/commands/`
---
## Built-in Commands
### /init Command
The only current built-in command analyzes your codebase and creates documentation:
- Analyzes project structure and architecture
- Creates AGENTS.md documentation files
- Identifies coding patterns and conventions
- Documents non-obvious implementation details
- Provides AI-friendly project context
---
## Creating Custom Commands
### Step-by-Step Guide
1. **Create Command Directory**:
```bash
# For project-specific commands
mkdir -p .roo/commands
# For global commands
mkdir -p ~/.roo/commands
```
2. **Create Command File**:
```bash
# Create a deployment command
touch .roo/commands/deploy.md
```
3. **Add Command Content**:
```markdown
---
description: Deploy application to production environment
argument-hint: environment name (staging, production)
---
## Deployment Process
1. Run test suite to ensure all tests pass
2. Build production bundle with optimizations
3. Update environment variables for target
4. Deploy to specified environment
5. Run post-deployment health checks
6. Update deployment documentation
```
4. **Use the Command**:
The command is immediately available for use without registration.
---
## Command Priority System
When multiple commands with the same name exist:
1. **Project Level** (highest priority)
- Located in `.roo/commands/`
- Allows project-specific overrides
- Committed to version control for team sharing
2. **Global Level** (medium priority)
- Located in `~/.roo/commands/`
- Shared across all projects
- User-specific customizations
3. **Built-in Level** (lowest priority)
- Hardcoded in the extension
- Provides default functionality
- Always available as fallback
---
## Examples When Used
- When initializing a new project, Roo executes `/init` to analyze the codebase structure and create comprehensive documentation.
- When deploying applications, Roo retrieves standardized deployment instructions specific to the project's infrastructure.
- When implementing features, Roo accesses team-agreed patterns and best practices through custom commands.
- When setting up development environments, Roo follows project-specific setup instructions consistently.
- When performing code reviews, Roo uses standardized review checklists defined as commands.
---
## Usage Examples
Executing the built-in initialization command:
```xml
<run_slash_command>
<command>init</command>
</run_slash_command>
```
Running a custom deployment command with arguments:
```xml
<run_slash_command>
<command>deploy</command>
<args>production environment with zero-downtime strategy</args>
</run_slash_command>
```
Executing a test command with specific focus:
```xml
<run_slash_command>
<command>test</command>
<args>focus on integration tests for authentication module</args>
</run_slash_command>
```
Running a project-specific build command:
```xml
<run_slash_command>
<command>build</command>
<args>optimized for production with source maps</args>
</run_slash_command>
```
Accessing team coding standards:
```xml
<run_slash_command>
<command>standards</command>
<args>TypeScript and React best practices</args>
</run_slash_command>
```
---
## Best Practices
### Command Design
1. **Clear Naming**: Use descriptive, action-oriented names
2. **Comprehensive Instructions**: Include all necessary steps
3. **Argument Flexibility**: Design commands to work with or without arguments
4. **Metadata Usage**: Always include description and argument hints
5. **Version Control**: Commit project commands for team consistency
### Organization Strategies
1. **Categorization**: Group related commands with prefixes (e.g., `test-unit`, `test-integration`)
2. **Documentation**: Maintain a README in command directories
3. **Templates**: Create template commands for common patterns
4. **Overrides**: Use project-level to customize global commands
5. **Maintenance**: Regularly review and update command content
### Team Collaboration
1. **Standardization**: Define team-wide commands in global directory
2. **Project Specifics**: Override with project-level customizations
3. **Documentation**: Document available commands and their usage
4. **Review Process**: Include command changes in code reviews
5. **Training**: Share command knowledge across team members
---
## Troubleshooting
### Common Issues
**Feature Not Enabled**:
- Error: "Run slash command is an experimental feature that must be enabled in settings"
- Solution: Enable 'Run Slash Command' in Experimental Settings
**Command Not Found**:
- Error: "Command 'X' not found. Available commands: Y, Z"
- Solution: Check command name spelling and available commands list
**Missing Parameters**:
- Error tracked in consecutive mistake counter
- Solution: Provide required `command` parameter
### Debugging Commands
1. **Verify File Location**: Ensure `.md` file is in correct directory
2. **Check File Name**: Command name must match filename without extension
3. **Validate Frontmatter**: Ensure YAML frontmatter is properly formatted
4. **Test Resolution**: Try same command name at different levels to test priority
5. **Review Content**: Ensure command content is properly formatted markdown

View file

@ -0,0 +1,209 @@
---
description: Learn how search_files performs powerful regex searches across your codebase, finding patterns with context using Ripgrep for high-performance results.
keywords:
- search_files
- Roo Code tools
- regex search
- code patterns
- Ripgrep
- multi-file search
- codebase search
- pattern matching
- VS Code AI
---
# search_files
The `search_files` tool performs regex searches across multiple files within your project's workspace. For security, it cannot search outside the current workspace directory. It helps Roo locate specific code patterns, text, or other content throughout your codebase with contextual results.
---
## Parameters
The tool accepts these parameters:
- `path` (required): The path of the directory to search in, relative to the current workspace directory. The search is confined to the workspace.
- `regex` (required): The regular expression pattern to search for (uses Rust regex syntax)
- `file_pattern` (optional): Glob pattern to filter files (e.g., '\*.ts' for TypeScript files)
- `respect_gitignore` (optional): Whether to respect `.gitignore` patterns (default: `true`). Set to `false` to search all files including those in `.gitignore`.
---
## What It Does
This tool searches across files in a specified directory using regular expressions, showing each match with surrounding context. It's like having a powerful "Find in Files" feature that works across the entire project structure.
---
## When is it used?
- When Roo needs to find where specific functions or variables are used
- When Roo helps with refactoring and needs to understand usage patterns
- When Roo needs to locate all instances of a particular code pattern
- When Roo searches for text across multiple files with filtering capabilities
---
## Key Features
- Searches across multiple files in a single operation using high-performance Ripgrep
- **Respects .gitignore**: Automatically excludes files and directories listed in `.gitignore` (including nested `.gitignore` files)
- Shows context around each match (1 line before and after)
- Filters files by type using glob patterns (e.g., only TypeScript files)
- Provides line numbers for easy reference
- Uses powerful regex patterns for precise searches
- Automatically limits output to 300 results with notification
- Truncates lines longer than 500 characters with "[truncated...]" marker
- Intelligently combines nearby matches into single blocks for readability
---
## Limitations
- Works best with text-based files (not effective for binary files like images)
- Performance may slow with extremely large codebases
- Uses Rust regex syntax, which may differ slightly from other regex implementations
- Cannot search within compressed files or archives
- Default context size is fixed (1 line before and after)
- May display varying context sizes when matches are close together due to result grouping
- For security, searches are strictly limited to the current workspace and cannot access parent directories or other locations on the file system.
- **Respects .gitignore by default**: Files listed in `.gitignore` are excluded from searches unless explicitly overridden with `respect_gitignore: false`
---
## How It Works
When the `search_files` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates the required `path` and `regex` parameters
2. **Path Resolution**: Resolves the relative path to an absolute path
3. **Search Execution**:
- Uses Ripgrep (rg) for high-performance text searching
- Applies file pattern filtering if specified
- Collects matches with surrounding context
4. **Result Formatting**:
- Formats results with file paths, line numbers, and context
- Displays 1 line of context before and after each match
- Structures output for easy readability
- Limits results to a maximum of 300 matches with notification
- Truncates lines longer than 500 characters
- Merges nearby matches into contiguous blocks
---
## Search Results Format
The search results include:
- Relative file paths for each matching file (prefixed with #)
- Context lines before and after each match (1 line by default)
- Line numbers padded to 3 spaces followed by `|` and the line content
- A separator line (----) after each match group
Example output format:
```
# rel/path/to/app.ts
11 | // Some processing logic here
12 | // TODO: Implement error handling
13 | return processedData;
----
# Showing first 300 of 300+ results. Use a more specific search if necessary.
```
When matches occur close to each other, they're merged into a single block rather than shown as separate results:
```
# rel/path/to/auth.ts
13 | // Some code here
14 | // TODO: Add proper validation
15 | function validateUser(credentials) {
16 | // TODO: Implement rate limiting
17 | return checkDatabase(credentials);
----
```
---
## Examples When Used
- When asked to refactor a function, Roo first searches for all places the function is used to ensure comprehensive changes.
- When investigating bugs, Roo searches for similar patterns to identify related issues across the codebase.
- When addressing technical debt, Roo locates all TODO comments across the project.
- When analyzing dependencies, Roo finds all imports of a particular module.
---
## Usage Examples
Searching for TODO comments in all JavaScript files:
```
<search_files>
<path>src</path>
<regex>TODO|FIXME</regex>
<file_pattern>*.js</file_pattern>
</search_files>
```
Finding all usages of a specific function:
```
<search_files>
<path>.</path>
<regex>function\s+calculateTotal</regex>
<file_pattern>*.{js,ts}</file_pattern>
</search_files>
```
Searching for a specific import pattern across the entire project:
```xml
<search_files>
<path>.</path>
<regex>import\s+.*\s+from\s+['"]@components/</regex>
</search_files>
```
## Respecting .gitignore
By default, `search_files` respects `.gitignore` patterns in your workspace, including nested `.gitignore` files. This prevents searches in excluded directories like `node_modules/`, `dist/`, or other ignored paths.
### Default Behavior (Respecting .gitignore)
**Input:**
```xml
<search_files>
<path>.</path>
<regex>TODO</regex>
</search_files>
```
This search will **exclude** files and directories listed in `.gitignore`, ensuring focused results on tracked code.
### Overriding .gitignore (Search All Files)
To search **all files** including those in `.gitignore`, explicitly set `respect_gitignore` to `false`:
**Input:**
```xml
<search_files>
<path>.</path>
<regex>TODO</regex>
<respect_gitignore>false</respect_gitignore>
</search_files>
```
This searches **everything**, including `node_modules/`, build artifacts, and other ignored paths.
**When to override:**
- Debugging issues in dependencies or build output
- Searching through generated code
- Comprehensive audits that need to check all files
- Investigating ignored configuration files
---

View file

@ -0,0 +1,87 @@
---
description: Replace a uniquely-identified occurrence of text in a file using the search_replace tool in Roo Code.
keywords:
- search_replace
- search and replace
- file editing
- text replacement
- Roo Code tools
- code modifications
---
# search_replace
The `search_replace` tool performs a targeted search-and-replace operation on a file, replacing **exactly one** uniquely-identified occurrence of specified text. If the search string matches multiple locations, the tool returns an error—the search string must be specific enough to identify a single target location.
---
## Parameters
The tool accepts these parameters:
- `file_path` (required): The path of the file to modify relative to the current working directory.
- `old_string` (required): The exact text to search for and replace.
- `new_string` (required): The replacement text.
---
## What It Does
This tool searches for an exact string in a file and replaces **exactly one** occurrence with new text. The search string must uniquely identify the target location in the file. If multiple matches are found, the tool returns an error and requires a more specific search string to proceed. This is an intentional safety design to prevent unintended changes.
---
## When is it used?
- When making a targeted change to a specific, uniquely identifiable location in a file
- When updating a specific string literal or configuration value at a known location
- When fixing a specific instance of a pattern or outdated terminology
- When you need simple, exact string replacement at a unique location
- When you need to ensure only one specific location is changed
---
## Key Features
- Replaces **exactly one** uniquely-identified occurrence per call
- Errors if multiple matches are found (intentional safety design)
- Exact string matching (no regex or fuzzy matching)
- Simple three-parameter interface
- Shows preview of changes before applying
- Preserves file formatting and structure
- User approval required before applying changes
---
## Limitations
- Requires exact string matches (case-sensitive, whitespace-sensitive)
- Errors if the search string matches more than one location (must be unique)
- Cannot use regular expressions or patterns
- Not suitable for replacing all occurrences globally (use scripting for that)
- Less precise than [`apply_diff`](/advanced-usage/available-tools/apply-diff) for complex edits
---
## How It Works
When the `search_replace` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates required `file_path`, `old_string`, and `new_string` parameters.
2. **File Loading**: Reads the target file content.
3. **Uniqueness Check**: Counts occurrences of `old_string` in the file. If more than one match is found, returns an error asking for a more specific search string.
4. **Replacement**: Replaces the single found occurrence with `new_string`.
5. **User Review**: Shows a preview of changes for user approval.
6. **Application**: Applies changes to the file if approved.
7. **Feedback**: Reports the result of the operation.
---
## Relation to Other Tools
- `search_replace`: Replaces **exactly one** uniquely-identified occurrence (this tool)
- [`edit_file`](/advanced-usage/available-tools/edit-file): Also replaces **exactly one** occurrence by default; also supports `old_string=""` for file creation
- [`edit`](/advanced-usage/available-tools/edit): Replaces **first occurrence** by default (unless `replace_all: true`)
- [`apply_diff`](/advanced-usage/available-tools/apply-diff): Use for precise, context-aware edits with fuzzy matching
These are different implementations of search-and-replace functionality with varying capabilities.

View file

@ -0,0 +1,110 @@
---
description: Load and execute skill instructions using the skill tool for specialized tasks in Roo Code.
keywords:
- skill
- skills
- specialized tasks
- instructions
- Roo Code tools
- automation
- workflows
---
# skill
The `skill` tool loads and injects specialized skill instructions into the conversation context. Skills provide detailed, step-by-step guidance for specific tasks like creating MCP servers, custom modes, or following standardized workflows.
---
## Parameters
The tool accepts these parameters:
- `skill` (required): The name of the skill to load (e.g., `create-mcp-server`, `create-mode`). Must match a skill name from the available skills list.
- `args` (optional): Additional context or arguments to pass to the skill for customization.
---
## What It Does
This tool retrieves skill instructions from the skills directory and loads them into the active conversation. Skills are pre-written instruction sets that guide Roo through complex, multi-step procedures. The tool is mode-aware, loading skills specific to the current mode when available.
---
## When is it used?
- When executing specialized procedures that have standardized workflows
- When creating MCP servers, custom modes, or other structured artifacts
- When following documented best practices for specific task types
- When you need to invoke expert knowledge for a particular domain
- When the task matches a known skill pattern available in the system
---
## Key Features
- Mode-aware skill resolution (loads mode-specific skills when available)
- Supports project-level skill overrides (take precedence over global skills)
- Progressive disclosure: linked files are not auto-loaded (explicit reads required)
- Optional arguments for skill customization
- Skills persist in context for the duration of the conversation
- Provides structured, step-by-step guidance for complex tasks
---
## How It Works
When the `skill` tool is invoked, it follows this process:
1. **Skill Resolution**: Searches for the named skill in the following locations (highest priority first):
- Project `.roo` mode-specific (e.g., `.roo/skills-code/`)
- Project `.roo` generic (`.roo/skills/`)
- Project `.agents` mode-specific (e.g., `.agents/skills-code/`)
- Project `.agents` generic (`.agents/skills/`)
- Global `.roo` mode-specific (e.g., `~/.roo/skills-code/`)
- Global `.roo` generic (`~/.roo/skills/`)
- Global `.agents` mode-specific (e.g., `~/.agents/skills-code/`)
- Global `.agents` generic (`~/.agents/skills/`)
2. **Skill Loading**: Loads the skill's main instruction file (typically `SKILL.md`).
3. **Context Injection**: Injects skill instructions into conversation context.
4. **Linked Files**: Files referenced in the skill are **not** automatically loaded; Roo must explicitly read them if needed.
5. **Execution**: Roo follows the skill's instructions to complete the task.
---
## Available Skills
Skills are dynamically loaded based on the current mode and project configuration. Common skills include:
- `create-mcp-server`: Guide for creating Model Context Protocol servers
- `create-mode`: Guide for creating custom Roo Code modes
- `find-skills`: Helps discover and install agent skills
To see available skills, check the skills list in the system prompt or ask Roo "what skills are available?"
---
## Relation to Features
The `skill` tool is the programmatic interface to the [Skills](/features/skills) feature. For comprehensive documentation on how skills work, how to create custom skills, and the skills system architecture, see the [Skills feature documentation](/features/skills).
---
## Example Usage
Loading a skill to create an MCP server:
```
<skill>
<skill>create-mcp-server</skill>
<args>weather API integration</args>
</skill>
```
Loading a skill without additional context:
```
<skill>
<skill>create-mode</skill>
</skill>
```

View file

@ -0,0 +1,199 @@
---
description: Understand how switch_mode enables seamless transitions between Code, Architect, Ask, and Debug modes for specialized task handling in Roo Code.
keywords:
- switch_mode
- Roo Code tools
- mode switching
- operational modes
- Code mode
- Architect mode
- Debug mode
- Ask mode
- task transitions
- VS Code AI
---
# switch_mode
The `switch_mode` tool enables Roo to change between different operational modes, each with specialized capabilities for specific types of tasks. This allows seamless transitions between modes like Code, Architect, Ask, or Debug when the current task requires different expertise.
---
## Parameters
The tool accepts these parameters:
- `mode_slug` (required): The slug of the mode to switch to (e.g., "code", "ask", "architect")
- `reason` (optional): The reason for switching modes, providing context for the user
---
## What It Does
This tool requests a mode change when the current task would be better handled by another mode's capabilities. It maintains context while shifting Roo's focus and available toolsets to match the requirements of the new task phase.
---
## When is it used?
- When transitioning from information gathering to code implementation
- When shifting from coding to architecture or design
- When the current task requires capabilities only available in a different mode
- When specialized expertise is needed for a particular phase of a complex project
---
## Key Features
- Maintains context continuity across mode transitions
- Provides clear reasoning for mode switch recommendations
- Requires user approval for all mode changes
- Enforces tool group restrictions specific to each mode
- Seamlessly adapts tool availability based on the selected mode
- Works with both standard and custom modes
- Displays the mode switch and reasoning in the UI
- Uses XML-style formatting for parameter specification
- Handles file type restrictions specific to certain modes
---
## Limitations
- Cannot switch to modes that don't exist in the system
- Requires explicit user approval for each mode transition
- Cannot use tools specific to a mode until the switch is complete
- Applies a 500ms delay after mode switching to allow the change to take effect
- Some modes have file type restrictions (e.g., Architect mode can only edit markdown files)
- Mode preservation for resumption applies only to the `new_task` functionality, not general mode switching
---
## How It Works
When the `switch_mode` tool is invoked, it follows this process:
1. **Request Validation**:
- Validates that the requested mode exists in the system
- Checks that the `mode_slug` parameter is provided and valid
- Verifies the user isn't already in the requested mode
- Ensures the `reason` parameter (if provided) is properly formatted
2. **Mode Transition Preparation**:
- Packages the mode change request with the provided reason
- Presents the change request to the user for approval
3. **Mode Activation (Upon User Approval)**:
- Updates the UI to reflect the new mode
- Adjusts available tools based on the mode's tool group configuration
- Applies the mode-specific prompt and behavior
- Applies a 500ms delay to allow the change to take effect before executing next tool
- Enforces any file restrictions specific to the mode
4. **Continuation**:
- Proceeds with the task using the capabilities of the new mode
- Retains relevant context from the previous interaction
---
## Tool Group Association
The `switch_mode` tool belongs to the "modes" tool group but is also included in the "always available" tools list. This means:
- It can be used in any mode regardless of the mode's configured tool groups
- It's available alongside other core tools like `ask_followup_question` and `attempt_completion`
- It allows mode transitions at any point in a workflow when task requirements change
---
## Mode Structure
Each mode in the system has a specific structure:
- `slug`: Unique identifier for the mode (e.g., "code", "ask")
- `name`: Display name for the mode (e.g., "Code", "Ask")
- `roleDefinition`: The specialized role and capabilities of the mode
- `customInstructions`: Optional mode-specific instructions that guide behavior
- `groups`: Tool groups available to the mode with optional restrictions
---
## Mode Capabilities
The core modes provide these specialized capabilities:
- **Code Mode**: Focused on coding tasks with full access to code editing tools
- **Architect Mode**: Specialized for system design and architecture planning, limited to editing markdown files only
- **Ask Mode**: Optimized for answering questions and providing information
- **Debug Mode**: Equipped for systematic problem diagnosis and resolution
---
## Custom Modes
Beyond the core modes, the system supports custom project-specific modes:
- Custom modes can be defined with specific tool groups enabled
- They can specify custom role definitions and instructions
- The system checks custom modes first before falling back to core modes
- Custom mode definitions take precedence over core modes with the same slug
---
## File Restrictions
Different modes may have specific file type restrictions:
- **Architect Mode**: Can only edit files matching the `.md` extension
- Attempting to edit restricted file types results in a `FileRestrictionError`
- These restrictions help enforce proper separation of concerns between modes
---
## Examples When Used
- When discussing a new feature, Roo switches from Ask mode to Architect mode to help design the system structure.
- After completing architecture planning in Architect mode, Roo switches to Code mode to implement the designed features.
- When encountering bugs during development, Roo switches from Code mode to Debug mode for systematic troubleshooting.
---
## Usage Examples
Switching to Code mode for implementation:
```
<switch_mode>
<mode_slug>code</mode_slug>
<reason>Need to implement the login functionality based on the architecture we've discussed</reason>
</switch_mode>
```
Switching to Architect mode for design:
```
<switch_mode>
<mode_slug>architect</mode_slug>
<reason>Need to design the system architecture before implementation</reason>
</switch_mode>
```
Switching to Debug mode for troubleshooting:
```
<switch_mode>
<mode_slug>debug</mode_slug>
<reason>Need to systematically diagnose the authentication error</reason>
</switch_mode>
```
Switching to Ask mode for information:
```
<switch_mode>
<mode_slug>ask</mode_slug>
<reason>Need to answer questions about the implemented feature</reason>
</switch_mode>
```

View file

@ -0,0 +1,319 @@
---
description: Comprehensive guide to Roo Code's tool system, including tool groups, calling mechanisms, mode integration, and best practices for AI-powered development.
keywords:
- Roo Code tools
- tool system
- tool groups
- AI development
- tool architecture
- mode integration
- tool security
- workflow tools
- VS Code AI
---
# Tool Use Overview
Roo Code implements a sophisticated tool system that allows AI models to interact with your development environment in a controlled and secure manner. This document explains how tools work, when they're called, and how they're managed.
---
## Core Concepts
### Tool Groups
Tools are organized into logical groups based on their functionality:
| Category | Purpose | Tools | Common Use |
| ------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- |
| **Read Group** | File system reading and exploration | [read_file](/advanced-usage/available-tools/read-file), [list_files](/advanced-usage/available-tools/list-files), [read_command_output](/advanced-usage/available-tools/read-command-output) | Code exploration and analysis |
| **Search Group** | Pattern and semantic searching | [search_files](/advanced-usage/available-tools/search-files), [codebase_search](/advanced-usage/available-tools/codebase-search) | Finding code patterns and functionality |
| **Edit Group** | File system modifications | [apply_diff](/advanced-usage/available-tools/apply-diff), [apply_patch](/advanced-usage/available-tools/apply-patch), [edit](/advanced-usage/available-tools/edit), [edit_file](/advanced-usage/available-tools/edit-file), [search_replace](/advanced-usage/available-tools/search-replace), [write_to_file](/advanced-usage/available-tools/write-to-file) | Code changes and file manipulation |
| **Image Group** | AI image generation | [generate_image](/advanced-usage/available-tools/generate-image) | Creating and editing images |
| **Command Group** | System command execution | [execute_command](/advanced-usage/available-tools/execute-command), [run_slash_command](/advanced-usage/available-tools/run-slash-command)\* | Running scripts, building projects, executing command templates |
| **MCP Group** | External tool integration | [use_mcp_tool](/advanced-usage/available-tools/use-mcp-tool), [access_mcp_resource](/advanced-usage/available-tools/access-mcp-resource) | Specialized functionality through external servers |
| **Workflow Group** | Mode and task management | [switch_mode](/advanced-usage/available-tools/switch-mode), [new_task](/advanced-usage/available-tools/new-task), [ask_followup_question](/advanced-usage/available-tools/ask-followup-question), [attempt_completion](/advanced-usage/available-tools/attempt-completion), [update_todo_list](/advanced-usage/available-tools/update-todo-list), [skill](/advanced-usage/available-tools/skill) | Context switching and task organization |
\*_Experimental feature - requires explicit enablement in settings_
### Always Available Tools
Certain tools are accessible regardless of the current mode:
- [ask_followup_question](/advanced-usage/available-tools/ask-followup-question): Gather additional information from users
- [attempt_completion](/advanced-usage/available-tools/attempt-completion): Signal task completion
- [switch_mode](/advanced-usage/available-tools/switch-mode): Change operational modes
- [new_task](/advanced-usage/available-tools/new-task): Create subtasks
---
## Available Tools
### Read Tools
These tools help Roo understand your code and project:
- [read_file](/advanced-usage/available-tools/read-file) - Examines the contents of files
- [list_files](/advanced-usage/available-tools/list-files) - Maps your project's file structure
- [read_command_output](/advanced-usage/available-tools/read-command-output) - Retrieves full output from truncated commands
### Search Tools
These tools help Roo find patterns and functionality across your codebase:
- [search_files](/advanced-usage/available-tools/search-files) - Finds patterns across multiple files using regex
- [codebase_search](/advanced-usage/available-tools/codebase-search) - Performs semantic searches across your indexed codebase
### Edit Tools
These tools help Roo make changes to your code:
- [apply_diff](/advanced-usage/available-tools/apply-diff) - Makes precise, surgical changes to your code
- [apply_patch](/advanced-usage/available-tools/apply-patch) - Applies multi-file unified diff patches
- [edit](/advanced-usage/available-tools/edit) - Search-and-replace editing (first occurrence by default)
- [edit_file](/advanced-usage/available-tools/edit-file) - Search-and-replace editing (all occurrences with count validation)
- [search_replace](/advanced-usage/available-tools/search-replace) - Simple search-and-replace (all occurrences)
- [write_to_file](/advanced-usage/available-tools/write-to-file) - Creates new files or completely rewrites existing ones
### Image Tools
These tools help Roo generate and edit images:
- [generate_image](/advanced-usage/available-tools/generate-image) - Generates AI-powered images from text prompts
### Command Tools
These tools help Roo execute commands:
- [execute_command](/advanced-usage/available-tools/execute-command) - Runs system commands and programs
- [run_slash_command](/advanced-usage/available-tools/run-slash-command) - Executes predefined slash commands for templated instructions _(Experimental - requires enablement)_
### MCP Tools
These tools help Roo connect with external services:
- [use_mcp_tool](/advanced-usage/available-tools/use-mcp-tool) - Uses specialized external tools
- [access_mcp_resource](/advanced-usage/available-tools/access-mcp-resource) - Accesses external data sources
### Workflow Tools
These tools help manage the conversation and task flow:
- [ask_followup_question](/advanced-usage/available-tools/ask-followup-question) - Gets additional information from you
- [attempt_completion](/advanced-usage/available-tools/attempt-completion) - Presents final results
- [switch_mode](/advanced-usage/available-tools/switch-mode) - Changes to a different mode for specialized tasks
- [new_task](/advanced-usage/available-tools/new-task) - Creates a new subtask
- [update_todo_list](/advanced-usage/available-tools/update-todo-list) - Updates task checklist progress
- [skill](/advanced-usage/available-tools/skill) - Loads and executes predefined skill instructions
---
## Tool Calling Mechanism
### Handling Complex Tasks
For certain complex operations that require multiple steps, Roo doesn't just figure them out on the fly. Instead, it follows predefined, internal plans to ensure consistency and accuracy.
A prime example is creating a new MCP server, identified internally by `create_mcp_server`. **This identifier does not represent a tool you will see being called.** Rather, when you ask Roo to create a server, it triggers this known, multi-step workflow.
This specific workflow is initiated by Roo using its internal `fetch_instructions` tool (with the task `create_mcp_server`) to retrieve a detailed plan. This plan then guides Roo to make calls to several standard, documented tools in sequence, such as:
- [`execute_command`](/advanced-usage/available-tools/execute-command) for running setup scripts (e.g., `npx @modelcontextprotocol/create-server`).
- [`write_to_file`](/advanced-usage/available-tools/write-to-file) or [`apply_diff`](/advanced-usage/available-tools/apply-diff) for creating or modifying server code and configuration files.
- [`ask_followup_question`](/advanced-usage/available-tools/ask-followup-question) to gather necessary information like API keys from you.
- Other standard tools as needed for steps like determining file locations or updating configuration entries.
So, while the overall task (like `create_mcp_server`) is complex, it's ultimately accomplished by intelligently orchestrating the standard tools available in your environment. This approach allows Roo to reliably perform complex operations by leveraging the tools documented here.
### When Tools Are Called
Tools are invoked under specific conditions:
1. **Direct Task Requirements**
- When specific actions are needed to complete a task as decided by the LLM
- In response to user requests
- During automated workflows
2. **Mode-Based Availability**
- Different modes enable different tool sets
- Mode switches can trigger tool availability changes
- Some tools are restricted to specific modes
3. **Context-Dependent Calls**
- Based on the current state of the workspace
- In response to system events
- During error handling and recovery
### Decision Process
The system uses a multi-step process to determine tool availability:
1. **Mode Validation**
```typescript
isToolAllowedForMode(
tool: string,
modeSlug: string,
customModes: ModeConfig[],
toolRequirements?: Record<string, boolean>,
toolParams?: Record<string, any>
)
```
2. **Requirement Checking**
- System capability verification
- Resource availability
- Permission validation
3. **Parameter Validation**
- Required parameter presence
- Parameter type checking
- Value validation
---
## Technical Implementation
### Tool Call Processing
1. **Initialization**
- Tool name and parameters are validated
- Mode compatibility is checked
- Requirements are verified
2. **Execution**
```typescript
const toolCall = {
type: "tool_call",
name: chunk.name,
arguments: chunk.input,
callId: chunk.callId,
}
```
3. **Result Handling**
- Success/failure determination
- Result formatting
- Error handling
### Security and Permissions
1. **Access Control**
- File system restrictions
- Command execution limitations
- Network access controls
2. **Validation Layers**
- Tool-specific validation
- Mode-based restrictions
- System-level checks
---
## Mode Integration
### Mode-Based Tool Access
Tools are made available based on the current mode:
- **Code Mode**: Full access to file system tools, code editing capabilities, command execution
- **Ask Mode**: Limited to reading tools, information gathering capabilities, no file system modifications
- **Architect Mode**: Design-focused tools, documentation capabilities, limited execution rights
- **Custom Modes**: Can be configured with specific tool access for specialized workflows
### Mode Switching
1. **Process**
- Current mode state preservation
- Tool availability updates
- Context switching
2. **Impact on Tools**
- Tool set changes
- Permission adjustments
- Context preservation
---
## Best Practices
### Tool Usage Guidelines
1. **Efficiency**
- Use the most specific tool for the task
- Avoid redundant tool calls
- Batch operations when possible
2. **Security**
- Validate inputs before tool calls
- Use minimum required permissions
- Follow security best practices
3. **Error Handling**
- Implement proper error checking
- Provide meaningful error messages
- Handle failures gracefully
### Common Patterns
1. **Information Gathering**
```
[ask_followup_question](/advanced-usage/available-tools/ask-followup-question) → [read_file](/advanced-usage/available-tools/read-file) → [codebase_search](/advanced-usage/available-tools/codebase-search)
```
2. **Code Modification**
```
[read_file](/advanced-usage/available-tools/read-file) → [apply_diff](/advanced-usage/available-tools/apply-diff) → [attempt_completion](/advanced-usage/available-tools/attempt-completion)
```
3. **Task Management**
```
[new_task](/advanced-usage/available-tools/new-task) → [switch_mode](/advanced-usage/available-tools/switch-mode) → [execute_command](/advanced-usage/available-tools/execute-command)
```
---
## Error Handling and Recovery
### Error Types
1. **Tool-Specific Errors**
- Parameter validation failures
- Execution errors
- Resource access issues
2. **System Errors**
- Permission denied
- Resource unavailable
- Network failures
3. **Context Errors**
- Invalid mode for tool
- Missing requirements
- State inconsistencies
### Recovery Strategies
1. **Automatic Recovery**
- Retry mechanisms
- Fallback options
- State restoration
2. **User Intervention**
- Error notifications
- Recovery suggestions
- Manual intervention options

View file

@ -0,0 +1,210 @@
---
description: Learn how update_todo_list creates dynamic TODO lists with status tracking, enabling step-by-step task management for complex workflows in Roo Code.
keywords:
- update_todo_list
- Roo Code tools
- task management
- TODO lists
- workflow tracking
- checklist management
- task status
- interactive UI
- VS Code AI
---
# update_todo_list
The `update_todo_list` tool enables dynamic, interactive task management within the chat interface. It replaces the entire TODO list with an updated checklist, ensuring that task status is always current and providing step-by-step tracking for complex, multi-step workflows.
---
## Parameters
The tool accepts these parameters:
- `todos` (required): A markdown-formatted string representing the complete checklist with status indicators
---
## What It Does
This tool creates and manages an interactive todo list that appears as a UI component in the chat interface. It allows for real-time task tracking, status updates, and dynamic addition of new items as they are discovered during complex workflows. The list provides a structured way to manage multi-step tasks with clear visual progress indicators.
---
## When is it used?
- When managing complex, multi-step tasks that benefit from structured tracking
- When Roo needs to show progress through a series of related activities
- When tasks require step-by-step completion verification before proceeding
- When new actionable items are discovered during long or complex workflows
- When providing clear checkpoints and progress visibility to users
---
## Key Features
- **Full Checklist Replacement**: Overwrites the existing todo list with the updated version provided
- **Interactive UI Component**: Displays as an editable interface element in the chat
- **Multiple Status Types**: Supports pending, in-progress, and completed task states
- **Dynamic Task Management**: Add new tasks as they arise during workflow execution
- **User-Friendly Editing**: Provides direct editing capabilities within the chat interface
- **Step-by-Step Tracking**: Enables confirmation of each step before updating and proceeding
- **Progress Visualization**: Clear visual indicators for task completion status
- **Workflow Integration**: Seamlessly integrates with task execution and completion flows
---
## Limitations
- **Complete Replacement**: Replaces the entire list rather than making incremental updates
- **Single-Level Structure**: Uses single-level markdown checklists without nesting support
- **Format Requirements**: Requires specific markdown checkbox syntax for proper parsing
- **Manual Updates**: Requires explicit tool calls to update the list status
- **State Management**: Todo list state is tied to the current task and conversation context
---
## How It Works
When the `update_todo_list` tool is invoked, it follows this process:
1. **Input Validation**:
- Validates the required `todos` parameter is provided
- Parses the markdown checklist format for syntax correctness
- Checks for valid status indicators: `[ ]`, `[-]`, and `[x]`
2. **List Processing**:
- Processes the markdown-formatted checklist
- Extracts individual todo items with their status indicators
- Validates the structure and format of each item
3. **UI Integration**:
- Presents the updated todo list to the user for approval
- Replaces any existing todo list with the new version
- Renders the list as an interactive component in the chat interface
4. **User Interaction**:
- Allows users to edit todos directly in the UI when in editing mode
- Provides "Add Todo" functionality for real-time list expansion
- Synchronizes changes back to the extension to maintain state consistency
5. **State Management**:
- Updates the task's internal todo list representation
- Maintains synchronization between UI state and backend data
- Preserves todo list state across conversation interactions
---
## Checklist Format Requirements
The tool uses a specific markdown format for todo items:
### Status Options
- `[ ]` - Pending task (not started)
- `[-]` - In progress task (currently being worked on)
- `[x]` - Completed task (fully finished)
### Format Rules
- Use single-level markdown checklist (no nesting or subtasks)
- List todos in intended execution order
- Each todo item should be clear and actionable
- Status should accurately reflect current task state
---
## Task Management Guidelines
### Status Updates
- Mark tasks as completed immediately after all work is finished
- Start the next task by marking it as in progress
- Use pending status for tasks not yet started
- Only mark tasks as completed when fully accomplished with no unresolved dependencies
### Dynamic List Management
- Add new todos as soon as they are identified during task execution
- Remove tasks only if they are no longer relevant or explicitly requested
- Retain all unfinished tasks and update their status as needed
- If a task is blocked, keep it as in progress and add new todos for resolution steps
---
## Examples When Used
- When developing a web application, Roo creates a todo list tracking design, implementation, testing, and deployment phases.
- When setting up a development environment, Roo tracks installation of dependencies, configuration steps, and verification tasks.
- When debugging complex issues, Roo maintains a list of investigation steps, potential causes, and testing procedures.
- When refactoring code, Roo tracks which files need updates, what tests need modification, and documentation changes required.
- When implementing new features, Roo manages tasks for planning, coding, testing, and integration steps.
---
## Usage Examples
Creating an initial todo list for a development task:
```xml
<update_todo_list>
<todos>
[ ] Analyze requirements
[ ] Design architecture
[ ] Implement core logic
[ ] Write tests
[ ] Update documentation
</todos>
</update_todo_list>
```
Updating progress after completing the first task:
```xml
<update_todo_list>
<todos>
[x] Analyze requirements
[-] Design architecture
[ ] Implement core logic
[ ] Write tests
[ ] Update documentation
</todos>
</update_todo_list>
```
Adding new tasks discovered during implementation:
```xml
<update_todo_list>
<todos>
[x] Analyze requirements
[x] Design architecture
[x] Implement core logic
[-] Write tests
[ ] Update documentation
[ ] Add performance benchmarks
[ ] Create deployment script
</todos>
</update_todo_list>
```
Managing a complex debugging workflow:
```xml
<update_todo_list>
<todos>
[x] Reproduce the issue
[x] Check recent code changes
[-] Analyze error logs
[ ] Test with different configurations
[ ] Check database queries
[ ] Verify network connectivity
[ ] Create fix and test
</todos>
</update_todo_list>
```

View file

@ -0,0 +1,231 @@
---
description: Discover how use_mcp_tool integrates external MCP servers to extend Roo Code with specialized tools, domain-specific functionality, and external services.
keywords:
- use_mcp_tool
- MCP tools
- Model Context Protocol
- external tools
- Roo Code integration
- MCP servers
- domain tools
- tool extension
- VS Code AI
---
# use_mcp_tool
The `use_mcp_tool` tool enables interaction with external tools provided by connected Model Context Protocol (MCP) servers. It extends Roo's capabilities with domain-specific functionality through a standardized protocol.
---
## Parameters
The tool accepts these parameters:
- `server_name` (required): The name of the MCP server providing the tool
- `tool_name` (required): The name of the tool to execute
- `arguments` (required/optional): A JSON object containing the tool's input parameters, following the tool's input schema. May be optional for tools that require no input.
---
## What It Does
This tool allows Roo to access specialized functionality provided by external MCP servers. Each MCP server can offer multiple tools with unique capabilities, extending Roo beyond its built-in functionality. The system validates arguments against schemas, manages server connections, and processes responses of various content types (text, image, resource).
---
## When is it used?
- When specialized functionality not available in core tools is needed
- When domain-specific operations are required
- When integration with external systems or services is needed
- When working with data that requires specific processing or analysis
- When accessing proprietary tools through a standardized interface
---
## Key Features
- Uses the standardized MCP protocol via the `@modelcontextprotocol/sdk` library
- Supports multiple transport mechanisms (StdioClientTransport, StreamableHTTPClientTransport and SSEClientTransport)
- Validates arguments using Zod schema validation on both client and server sides
- Processes multiple response content types: text, image, and resource references
- Manages server lifecycle with automatic restarts when server code changes
- Provides an "always allow" mechanism to bypass approval for trusted tools
- Works with the companion `access_mcp_resource` tool for resource retrieval
- Maintains proper error tracking and handling for failed operations
- Supports configurable timeouts (1-3600 seconds, default: 60 seconds)
- Allows file watchers to automatically detect and reload server changes
---
## Limitations
- Depends on external MCP servers being available and connected
- Limited to the tools provided by connected servers
- Tool capabilities vary between different MCP servers
- Network issues can affect reliability and performance
- Requires user approval before execution (unless in the "always allow" list)
- Cannot execute multiple MCP tool operations simultaneously
---
## Server Configuration
MCP servers can be configured globally or at the project level:
- **Global Configuration**: Managed through the Roo Code extension settings in VS Code. These apply across all projects unless overridden.
- **Project-level Configuration**: Defined in a `.roo/mcp.json` file within your project's root directory.
- This allows project-specific server setups.
- Project-level servers take precedence over global servers if they share the same name.
- Since `.roo/mcp.json` can be committed to version control, it simplifies sharing configurations with your team.
---
## How It Works
When the `use_mcp_tool` tool is invoked, it follows this process:
1. **Initialization and Validation**:
- The system verifies that the MCP hub is available
- Confirms the specified server exists and is connected
- Validates the requested tool exists on the server
- Arguments are validated against the tool's schema definition
- Timeout settings are extracted from server configuration (default: 60 seconds)
2. **Execution and Communication**:
- The system selects the appropriate transport mechanism:
- `StdioClientTransport`: For communicating with local processes via standard I/O
- `SSEClientTransport`: For communicating with HTTP servers via Server-Sent Events
- `StreamableHTTPClientTransport`: For communicating with HTTP servers via Streamable HTTP Events
- A request is sent with validated server name, tool name, and arguments
- Communication uses the `@modelcontextprotocol/sdk` library for standardized interactions
- Request execution is tracked with timeout handling to prevent hanging operations
3. **Response Processing**:
- Responses can include multiple content types:
- Text content: Plain text responses
- Image content: Binary image data with MIME type information
- Resource references: URIs to access server resources (works with `access_mcp_resource`)
- The system checks the `isError` flag to determine if error handling is needed
- Results are formatted for display in the Roo interface
4. **Resource and Error Handling**:
- The system uses WeakRef patterns to prevent memory leaks
- A consecutive mistake counter tracks and manages errors
- File watchers monitor for server code changes and trigger automatic restarts
- The security model requires approval for tool execution unless in the "always allow" list
---
## Security and Permissions
The MCP architecture provides several security features:
- Users must approve tool usage before execution (by default)
- Specific tools can be marked for automatic approval in the "always allow" list
- Server configurations are validated with Zod schemas for integrity
- Configurable timeouts prevent hanging operations (1-3600 seconds)
- Server connections can be enabled or disabled through the UI
---
## Examples When Used
- Analyzing specialized data formats using server-side processing tools
- Generating images or other media through AI models hosted on external servers
- Executing complex domain-specific calculations without local implementation
- Accessing proprietary APIs or services through a controlled interface
- Retrieving data from specialized databases or data sources
---
## Usage Examples
Requesting weather forecast data with text response:
```
<use_mcp_tool>
<server_name>weather-server</server_name>
<tool_name>get_forecast</tool_name>
<arguments>
{
"city": "San Francisco",
"days": 5,
"format": "text"
}
</arguments>
</use_mcp_tool>
```
Analyzing source code with a specialized tool that returns JSON:
```
<use_mcp_tool>
<server_name>code-analysis</server_name>
<tool_name>complexity_metrics</tool_name>
<arguments>
{
"language": "typescript",
"file_path": "src/app.ts",
"include_functions": true,
"metrics": ["cyclomatic", "cognitive"]
}
</arguments>
</use_mcp_tool>
```
Generating an image with specific parameters:
```
<use_mcp_tool>
<server_name>image-generation</server_name>
<tool_name>create_image</tool_name>
<arguments>
{
"prompt": "A futuristic city with flying cars",
"style": "photorealistic",
"dimensions": {
"width": 1024,
"height": 768
},
"format": "webp"
}
</arguments>
</use_mcp_tool>
```
Accessing a resource through a tool that returns a resource reference:
```
<use_mcp_tool>
<server_name>database-connector</server_name>
<tool_name>query_and_store</tool_name>
<arguments>
{
"database": "users",
"type": "select",
"fields": ["name", "email", "last_login"],
"where": {
"status": "active"
},
"store_as": "active_users"
}
</arguments>
</use_mcp_tool>
```
Tool with no required arguments:
```
<use_mcp_tool>
<server_name>system-monitor</server_name>
<tool_name>get_current_status</tool_name>
<arguments>
{}
</arguments>
</use_mcp_tool>
```

View file

@ -0,0 +1,207 @@
---
description: Explore write_to_file for creating new files or replacing content with interactive diff view approval, ensuring safe file operations in Roo Code.
keywords:
- write_to_file
- Roo Code tools
- file creation
- file writing
- diff view
- content approval
- file operations
- interactive editing
- VS Code AI
---
# write_to_file
The `write_to_file` tool creates new files or completely replaces existing file content with an interactive approval process. It provides a diff view for reviewing changes before they're applied.
---
## Parameters
The tool accepts these parameters:
- `path` (required): The path of the file to write to, relative to the current working directory
- `content` (required): The complete content to write to the file
- `line_count` (required): The number of lines in the file, including empty lines
---
## What It Does
This tool writes content to a specified file, either creating a new file if it doesn't exist or completely overwriting an existing file. All changes require explicit user approval through a diff view interface, where users can review and even edit the proposed changes before they're applied.
---
## When is it used?
- When Roo needs to create a new file from scratch
- When Roo needs to completely rewrite an existing file
- When creating multiple files for a new project
- When generating configuration files, documentation, or source code
- When you need to review changes before they're applied
---
## Key Features
- Interactive Approval: Shows changes in a diff view requiring explicit approval before applying
- User Edit Support: Allows editing the proposed content before final approval
- Safety Measures: Detects code omission, validates paths, and prevents truncated content
- Editor Integration: Opens a diff view that scrolls to the first difference automatically
- Content Preprocessing: Handles artifacts from different AI models to ensure clean content
- Access Control: Validates against `.rooignore` restrictions before making changes
- Parent Directories: May handle directory creation through system dependencies
- Complete Replacement: Provides a fully transformed file in a single operation
---
## Limitations
- Not suitable for existing files: Much slower and less efficient than `apply_diff` for modifying existing files
- Performance with large files: Operation becomes significantly slower with larger files
- Complete overwrite: Replaces entire file content, cannot preserve original content
- Line count required: Needs accurate line count to detect potential content truncation
- Review overhead: The approval process adds extra steps compared to direct edits
- Interactive only: Cannot be used in automated workflows that require non-interactive execution
---
## How It Works
When the `write_to_file` tool is invoked, it follows this process:
1. **Parameter Validation**: Validates the required parameters and permissions
- Checks that `path`, `content`, and `line_count` are provided
- If `line_count` is missing/invalid, reverts any diff view changes and returns an error suggesting alternative tools (`apply_diff`, etc.) if modifying an existing file.
- Validates the file is allowed (not restricted by `.rooignore`)
- Ensures the path is within the workspace boundaries
- Tracks consecutive mistake counts for missing parameters
- Shows specific error messages for each validation failure
2. **Content Preprocessing**:
- Removes code block markers that might be added by AI models
- Handles escaped HTML entities (specifically for non-Claude models)
- Strips line numbers if accidentally included in content
- Performs model-specific processing for different AI providers
3. **Diff View Generation**:
- Opens a diff view in the editor showing the proposed changes
- Adds a 300ms delay to ensure UI responsiveness
- Scrolls automatically to the first difference
- Highlights changes for easy review
4. **User Approval Process**:
- Waits for explicit user approval to proceed
- Allows users to edit the content in the diff view
- Captures any user edits for the final content
- Provides option to reject changes entirely
- Detects and incorporates user modifications into the final result
5. **Safety Validation**:
- Detects potential content truncation by comparing with provided line count
- Shows warnings if content appears incomplete
- Validates file path and access permissions
- Specifically checks if files are outside the workspace with `isOutsideWorkspace` flag
6. **File Writing**:
- Writes the approved content (with any user edits) to the file
- Provides confirmation of successful write
- Resets the consecutive mistakes counter on success
---
## Examples When Used
- When creating a new project, Roo generates multiple files but lets you review each before committing changes.
- When setting up configuration files, Roo shows the proposed configuration in a diff view for approval.
- When generating documentation, Roo creates markdown files but lets you make final adjustments in the diff view.
- When developing a prototype, Roo shows complete source files in a diff view where you can fine-tune before saving.
---
## Usage Examples
Creating a new JSON configuration file:
```
<write_to_file>
<path>config/settings.json</path>
<content>
{
"apiEndpoint": "https://api.example.com",
"theme": {
"primaryColor": "#007bff",
"secondaryColor": "#6c757d",
"fontFamily": "Arial, sans-serif"
},
"features": {
"darkMode": true,
"notifications": true
},
"version": "1.0.0"
}
</content>
<line_count>13</line_count>
</write_to_file>
```
Creating a simple HTML file:
```
<write_to_file>
<path>src/index.html</path>
<content>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Application</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="app"></div>
<script src="app.js"></script>
</body>
</html>
</content>
<line_count>13</line_count>
</write_to_file>
```
Creating a JavaScript module:
```
<write_to_file>
<path>src/utils/helpers.js</path>
<content>
/**
* Utility functions for the application
*/
export function formatDate(date) {
return new Date(date).toLocaleDateString();
}
export function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
export function debounce(func, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
</content>
<line_count>18</line_count>
</write_to_file>
```

View file

@ -0,0 +1,77 @@
---
description: Learn about context poisoning in AI coding assistants, its symptoms, causes, and effective recovery strategies to maintain accurate AI responses.
keywords:
- context poisoning
- AI accuracy
- Roo Code troubleshooting
- LLM context management
- session recovery
---
# Context Poisoning
:::info
Context poisoning is a persistent issue within a given session. Once a chat session's context is compromised, treat that session as disposable. Starting fresh with a clean context is crucial for maintaining the accuracy and effectiveness of your Roo Code agent.
:::
Context poisoning occurs when inaccurate or irrelevant data contaminates the language model's active context. This leads the model to draw incorrect conclusions, provide erroneous information to tools, and progressively deviate from the intended task with each interaction.
---
## Symptoms of Context Poisoning
Identify context poisoning by observing these behaviors:
- **Degraded Output Quality:** Suggestions become nonsensical, repetitive, or irrelevant.
- **Tool Misalignment:** Tool calls no longer correspond to the user's requests.
- **Orchestration Failures:** Orchestrator chains may stall, loop indefinitely, or fail to complete.
- **Temporary Fixes:** Re-applying a clean prompt or instructions offers only brief respite before issues resurface.
- **Tool Usage Confusion:** The model struggles to correctly use or recall how to use tools defined in the system prompt.
---
## Common Causes
Context poisoning can be triggered by several factors:
- **Model Hallucination:** The model generates an incorrect piece of information and subsequently treats it as a factual part of the context.
- **Code Comments:** Outdated, incorrect, or ambiguous comments in the codebase can be misinterpreted by the model, leading it down the wrong path.
- **Contaminated User Input:** Copy-pasting logs or text containing hidden or rogue control characters.
- **Context Window Overflow:** As a session grows, older, useful information may be pushed out of the model's limited context window, allowing "poisoned" data to have a greater relative impact.
Once bad data enters the context, it tends to persist. The model re-evaluates this tainted information in subsequent reasoning cycles, similar to a permanent flaw affecting its perception until the context is completely reset.
---
## Can a "Wake-Up Prompt" Resolve Context Poisoning?
**Short Answer:** No.
A corrective prompt might temporarily suppress symptoms, but the problematic data remains in the conversational buffer. The model will likely revert to the poisoned state as soon as the interaction deviates from the narrow scope of the corrective prompt.
**Detailed Explanation:**
- Re-injecting the full set of tool definitions or core directives can sometimes mask the damage for one or some interactions following the initial context poisoning .
- However, the underlying poisoned context remains. Any query or task outside the immediate "patch" will likely re-trigger the original issue.
- This approach is unreliable, akin to placing a warning label on a leaking pipe instead of repairing it.
---
## Effective Recovery Strategies
To reliably recover from context poisoning:
- **Hard Reset the Session:** The most dependable solution is to start a new chat session. This clears the contaminated context entirely.
- **Minimize Manual Data Dumps:** When pasting logs or other data, be selective. Only include the essential information the model requires.
- **Manage Context Window Size:** For large or complex tasks, consider breaking them into smaller, focused chat sessions. This helps ensure that stale or irrelevant information ages out of the context window more quickly.
- **Validate Tool Output:** If a tool returns nonsensical or clearly incorrect data, delete that message from the chat history before the model can process it and incorporate it into its context.
---
## Addressing a Common Question: The "Magic Bullet" Prompt
A frequent question from the community is:
> "Have you found a prompt that wakes it back up? Maybe a prompt that just has the tools instructions we can push back in manually?”
As explained, no single prompt offers a lasting fix. Any immediate improvement is superficial because the corrupted lines of text persist in the session's history, ready to cause further issues. The only robust solution is to discard the compromised session, initiate a new one, and provide it with a clean prompt and the correct tool definitions from the outset.

View file

@ -0,0 +1,64 @@
---
description: Learn strategies for effectively using Roo Code with large codebases. Manage context limits, optimize token usage, and handle complex refactoring tasks.
keywords:
- large projects
- context management
- token optimization
- codebase refactoring
- Roo Code scalability
---
# Working with Large Projects
Roo Code can be used with projects of any size, but large projects require some extra care to manage context effectively. Here are some tips for working with large codebases:
---
## Understanding Context Limits
Roo Code uses large language models (LLMs) that have a limited "context window." This is the maximum amount of text (measured in tokens) that the model can process at once. If the context is too large, the model may not be able to understand your request or generate accurate responses.
The context window includes:
- The system prompt (instructions for Roo Code).
- The conversation history.
- The content of any files you mention using `@`.
- The output of any commands or tools Roo Code uses.
---
## Strategies for Managing Context
1. **Be Specific:** When referring to files or code, use specific file paths and function names. Avoid vague references like "the main file."
2. **Use Context Mentions Effectively:** Use `@/path/to/file.ts` to include specific files. Use `@problems` to include current errors and warnings. Use `@` followed by a commit hash to reference specific Git commits.
3. **Break Down Tasks:** Divide large tasks into smaller, more manageable sub-tasks. This helps keep the context focused.
4. **Summarize:** If you need to refer to a large amount of code, consider summarizing the relevant parts in your prompt instead of including the entire code.
5. **Prioritize Recent History:** Roo Code automatically truncates older messages in the conversation history to stay within the context window. Be mindful of this, and re-include important context if needed.
6. **Use Prompt Caching (if available):** Some API providers like Anthropic, OpenAI, OpenRouter and Requesty support "prompt caching". This caches your prompts for use in future tasks and helps reduce the cost and latency of requests.
---
## Example: Refactoring a Large File
Let's say you need to refactor a large TypeScript file (`src/components/MyComponent.tsx`). Here's a possible approach:
1. **Initial Overview:**
```
@/src/components/MyComponent.tsx List the functions and classes in this file.
```
2. **Target Specific Functions:**
```
@/src/components/MyComponent.tsx Refactor the `processData` function to use `async/await` instead of Promises.
```
3. **Iterative Changes:** Make small, incremental changes, reviewing and approving each step.
By breaking down the task and providing specific context, you can work effectively with large files even with a limited context window.

View file

@ -0,0 +1,57 @@
---
description: Learn how to run Roo Code with local AI models using Ollama and LM Studio. Complete setup guide for offline AI coding assistance.
keywords:
- local models
- Ollama
- LM Studio
- offline AI
- local LLM
- self-hosted AI
- privacy-focused AI
---
# Using Local Models
Roo Code supports running language models locally on your own machine using [Ollama](https://ollama.com/) and [LM Studio](https://lmstudio.ai/). This offers several advantages:
- **Privacy:** Your code and data never leave your computer.
- **Offline Access:** You can use Roo Code even without an internet connection.
- **Cost Savings:** Avoid API usage fees associated with cloud-based models.
- **Customization:** Experiment with different models and configurations.
**However, using local models also has some drawbacks:**
- **Resource Requirements:** Local models can be resource-intensive, requiring a powerful computer with a good CPU and, ideally, a dedicated GPU.
- **Setup Complexity:** Setting up local models can be more complex than using cloud-based APIs.
- **Model Performance:** The performance of local models can vary significantly. While some are excellent, they may not always match the capabilities of the largest, most advanced cloud models.
- **Limited Features**: Local models (and many online models) often do not support advanced features such as prompt caching, computer use, and others.
---
## Supported Local Model Providers
Roo Code currently supports two main local model providers:
1. **Ollama:** A popular open-source tool for running large language models locally. It supports a wide range of models.
2. **LM Studio:** A user-friendly desktop application that simplifies the process of downloading, configuring, and running local models. It also provides a local server that emulates the OpenAI API.
---
## Setting Up Local Models
For detailed setup instructions, see:
- [Setting up Ollama](/providers/ollama)
- [Setting up LM Studio](/providers/lmstudio)
Both providers offer similar capabilities but with different user interfaces and workflows. Ollama provides more control through its command-line interface, while LM Studio offers a more user-friendly graphical interface.
---
## Troubleshooting
- **"No connection could be made because the target machine actively refused it":** This usually means that the Ollama or LM Studio server isn't running, or is running on a different port/address than Roo Code is configured to use. Double-check the Base URL setting.
- **Slow Response Times:** Local models can be slower than cloud-based models, especially on less powerful hardware. If performance is an issue, try using a smaller model.
- **Model Not Found:** Ensure you have typed in the name of the model correctly. If you're using Ollama, use the same name that you provide in the `ollama run` command.

View file

@ -0,0 +1,115 @@
---
description: Master the art of writing effective prompts for Roo Code. Learn principles, techniques, and examples to get better AI coding assistance results.
keywords:
- prompt engineering
- AI prompts
- effective communication
- Roo Code tips
- custom instructions
---
# Prompt Engineering Tips
Prompt engineering is the art of crafting effective instructions for AI models like Roo Code. Well-written prompts lead to better results, fewer errors, and a more efficient workflow.
---
## General Principles
- **Be Clear and Specific:** Clearly state what you want Roo Code to do. Avoid ambiguity.
- **Bad:** Fix the code.
- **Good:** Fix the bug in the `calculateTotal` function that causes it to return incorrect results.
- **Provide Context:** Use [Context Mentions](/basic-usage/context-mentions) to refer to specific files, folders, or problems.
- **Good:** `@/src/utils.ts` Refactor the `calculateTotal` function to use async/await.
- **Break Down Tasks:** Divide complex tasks into smaller, well-defined steps.
- **Give Examples:** If you have a specific coding style or pattern in mind, provide examples.
- **Specify Output Format:** If you need the output in a particular format (e.g., JSON, Markdown), specify it in the prompt.
- **Iterate:** Don't be afraid to refine your prompt if the initial results aren't what you expect.
---
## Thinking vs. Doing
It's often helpful to guide Roo Code through a "think-then-do" process:
1. **Analyze:** Ask Roo Code to analyze the current code, identify problems, or plan the approach.
2. **Plan:** Have Roo Code outline the steps it will take to complete the task.
3. **Execute:** Instruct Roo Code to implement the plan, one step at a time.
4. **Review:** Carefully review the results of each step before proceeding.
---
## Using Custom Instructions
You can provide custom instructions to further tailor Roo Code's behavior. There are two types of custom instructions:
- **Global Custom Instructions:** Apply to all modes.
- **Mode-Specific Custom Instructions:** Apply only to a specific mode (e.g., Code, Architect, Ask, Debug, or a custom mode).
Custom instructions are added to the system prompt, providing persistent guidance to the AI model. You can use these to:
- Enforce coding style guidelines.
- Specify preferred libraries or frameworks.
- Define project-specific conventions.
- Adjust Roo Code's tone or personality.
See the [Custom Instructions](/features/custom-instructions) section for more details.
---
## Handling Ambiguity
If your request is ambiguous or lacks sufficient detail, Roo Code might:
- **Make Assumptions:** It might proceed based on its best guess, which may not be what you intended.
- **Ask Follow-Up Questions:** It might use the `ask_followup_question` tool to clarify your request.
It's generally better to provide clear and specific instructions from the start to avoid unnecessary back-and-forth.
---
## Providing Feedback
If Roo Code doesn't produce the desired results, you can provide feedback by:
- **Rejecting Actions:** Click the "Reject" button when Roo Code proposes an action you don't want.
- **Providing Explanations:** When rejecting, explain _why_ you're rejecting the action. This helps Roo Code learn from its mistakes.
- **Rewording Your Request:** Try rephrasing your initial task or providing more specific instructions.
- **Manually Correcting:** If there are a few small issues, you can also directly modify the code before accepting the changes.
---
## Examples
**Good Prompt:**
> `@/src/components/Button.tsx` Refactor the `Button` component to use the `useState` hook instead of the `useReducer` hook.
**Bad Prompt:**
> Fix the button.
**Good Prompt:**
> Create a new file named `utils.py` and add a function called `calculate_average` that takes a list of numbers and returns their average.
**Bad Prompt:**
> Write some Python code.
**Good Prompt:**
> `@problems` Address all errors and warnings in the current file.
**Bad Prompt:**
> Fix everything.
By following these tips, you can write effective prompts that get the most out of Roo Code's capabilities.

View file

@ -0,0 +1,126 @@
---
description: Understand the technical structure of prompts in Roo Code. Learn how messages are constructed, system prompts work, and optimize your interactions.
keywords:
- prompt structure
- system prompt
- message flow
- technical documentation
- LLM communication
---
# Prompt Structure
This page explains the technical structure of prompts in Roo Code - how messages are constructed and sent to the Large Language Model (LLM).
---
## Core Message Types
Roo Code uses three primary message types when communicating with LLMs:
- **System Prompt**: The initial instructions that define Roo's capabilities, persona, and operational rules
- **User Messages**: Content sent by you (the user) to Roo
- **Assistant Messages**: Responses generated by the LLM based on your requests
At the API level, there's also a fourth message role:
- **Tool Messages**: Results returned from tool executions, sent back to the LLM as input
Understanding these message types helps you work more effectively with Roo and can be valuable for troubleshooting or advanced customization.
---
## System Prompt
The system prompt is the foundation of Roo's behavior. It contains:
- **Role Definition**: The core persona instructions based on the selected mode (Code, Ask, Debug, etc.)
- **Tool Descriptions**: Detailed information about available tools, including parameters and examples
- **Tool Use Guidelines**: Rules for how tools should be used (sequential execution, waiting for results)
- **Capabilities**: Description of what Roo can do in the current environment
- **Available Modes**: List of all available modes and their descriptions
- **Operational Rules**: Critical guidelines for handling files, project structure, and user interaction
- **System Information**: Details about your environment (OS, shell, working directory)
- **Custom Instructions**: Your global and mode-specific customizations
The system prompt is generated dynamically each time you interact with Roo, adapting to your current mode, available tools, and custom settings.
---
## User Messages
User messages contain your direct inputs to Roo, plus additional contextual information:
- **Your Query**: The text you type in the chat interface
- **Images**: Any images you include in your message (for supported models)
- **Environment Details**: Automatically appended information about your workspace state:
- Open files/tabs
- Cursor position
- Active terminals with output
- Recently modified files
- Current time
- Token/cost information
- Current mode
- File listing (on initial connection)
This automatic context enrichment helps Roo understand your workspace without requiring you to explicitly describe it.
---
## Assistant Messages
Assistant messages are the LLM's responses, which may include:
- **Text Responses**: Direct answers to your queries
- **Thinking**: Internal reasoning process (visible when enabled)
- **Tool Calls**: Requests to use specific tools like reading files or executing commands
Note that while assistant messages contain tool calls, the results of those tools are sent back to the LLM in separate tool messages, not as part of the assistant message itself.
---
## Message Flow
Here's how these components work together:
1. **Initial Setup**: Roo generates the system prompt based on your selected mode and configuration
2. **User Input**: You send a message, which is enriched with environment details
3. **LLM Processing**: The LLM receives all previous messages plus your new input
4. **Assistant Response**: The LLM generates a response, potentially using tools
5. **Tool Execution**: If the LLM requests a tool, Roo executes it and provides the result
6. **Conversation History**: All messages are maintained in a structured history for context
---
## Technical Implementation
Internally, Roo's prompt construction is handled by several components:
- **System Prompt Generation**: The `SYSTEM_PROMPT` function in `src/core/prompts/system.ts` assembles the complete system prompt
- **Section Generators**: Specialized functions create each section of the system prompt
- **Message Transformation**: Provider-specific transformers convert Roo's internal message format to the format required by each LLM API
---
## Support Prompts
Alongside the main chat flow, Roo uses specialized templates for specific code actions:
- **Code Action Prompts**: For commands like "Explain", "Fix", "Improve", or "Add to Context"
- **Template-Based**: Generated from templates in `src/shared/support-prompt.ts`
- **Independent Context**: Often operates without the main chat history
- **Task-Specific Format**: Optimized for the specific code task being performed
These support prompts work outside the normal conversation flow to provide focused assistance for specific coding tasks.
---
## Optimizing Your Interactions
Understanding this structure can help you:
- **Write Better Prompts**: Knowing what context Roo already has helps you avoid redundant information
- **Troubleshoot Issues**: Understanding message flow helps identify where problems might occur
- **Create Custom Modes**: With knowledge of the system prompt structure, you can create more effective custom modes
This technical foundation powers all of Roo's capabilities, enabling it to understand your requests and effectively utilize available tools to complete tasks.

View file

@ -0,0 +1,68 @@
---
description: Understand token usage, cost calculation, and optimization strategies for Roo Code. Learn how to manage API costs and set request limits effectively.
keywords:
- rate limits
- API costs
- token usage
- cost optimization
- auto-approval limits
- API management
---
# Rate Limits and Costs
Understanding and managing API usage is crucial for a smooth and cost-effective experience with Roo Code. This section explains how to track your token usage and costs. Rate limits, which default to 0 (disabled) and typically don't need adjustment, are now configured per profile; see the [API Configuration Profiles](/features/api-configuration-profiles#creating-a-profile) documentation for details on how to set them if needed.
---
## Token Usage
Roo Code interacts with AI models using tokens. Tokens are essentially pieces of words. The number of tokens used in a request and response affects both the processing time and the cost.
- **Input Tokens:** These are the tokens in your prompt, including the system prompt, your instructions, and any context provided (e.g., file contents).
- **Output Tokens:** These are the tokens generated by the AI model in its response.
You can see the number of input and output tokens used for each interaction in the chat history.
---
## Cost Calculation
Most AI providers charge based on the number of tokens used. Pricing varies depending on the provider and the specific model.
Roo Code automatically calculates the estimated cost of each API request based on the configured model's pricing. This cost is displayed in the chat history, next to the token usage.
For reasoning-capable models (for example, Gemini 3 Pro Preview and other models that expose separate "thinking" or reasoning tokens), Roo Code now includes both normal tokens **and** reasoning / "thought" tokens in its estimates when the provider reports them. This can make the displayed token usage and cost slightly higher than in older versions, but it better matches how providers actually bill you.
**Note:**
- The cost calculation is an _estimate_. The actual cost may vary slightly depending on the provider's billing practices.
- Some providers may offer free tiers or credits. Check your provider's documentation for details.
- Some providers offer prompt caching which greatly lowers cost.
### Limiting Auto-Approved Requests
To further help manage API costs and prevent unexpected expenses, Roo Code includes a "Max Requests" setting for auto-approved actions. This allows you to define a specific limit on how many consecutive API calls Roo Code can make without requiring your explicit re-approval during a task.
- **How it works:** If you set a limit (e.g., 5 requests), Roo Code will perform up to 5 auto-approved API calls. Before making the 6th call, it will pause and prompt you to "Reset and Continue," as shown below.
<img src="/img/v3.18.0/v3.18.0-1.png" alt="Warning message indicating the auto-approved request limit has been reached." width="600" />
_Notification when the auto-approved request limit is met._
- **Configuration:** This limit is configured within the "Auto-approve actions" settings. You can set a specific number or choose "Unlimited." For detailed steps on configuring this and other auto-approval settings, see the [Auto-Approving Actions documentation](/features/auto-approving-actions).
<img src="/img/v3.18.0/v3.18.0.png" alt="Setting the Max Requests limit for auto-approved actions in Roo Code settings." width="600" />
_Setting the "Max Requests" for auto-approved actions._
This feature provides an additional safeguard, particularly for complex or long-running tasks where multiple API calls might be involved.
---
## Tips for Optimizing Token Usage
- **Be Concise:** Use clear and concise language in your prompts. Avoid unnecessary words or details.
- **Provide Only Relevant Context:** Use context mentions (`@file.ts`, `@folder/`) selectively. Only include the files that are directly relevant to the task.
- **Break Down Tasks:** Divide large tasks into smaller, more focused sub-tasks.
- **Use Custom Instructions:** Provide custom instructions to guide Roo Code's behavior and reduce the need for lengthy explanations in each prompt.
- **Choose the Right Model:** Some models are more cost-effective than others. Consider using a smaller, faster model for tasks that don't require the full power of a larger model.
- **Use Modes:** Different modes can access different tools, for example `Architect` can't modify code, which makes it a safe choice when analyzing a complex codebase, without worrying about accidentally allowing expensive operations.
- **Disable MCP If Not Used:** If you're not using MCP (Model Context Protocol) features, consider [disabling it in the MCP settings](/features/mcp/using-mcp-in-roo#enabling-or-disabling-mcp-server-creation) to significantly reduce the size of the system prompt and save tokens.
By understanding and managing your API usage, you can use Roo Code effectively and efficiently.

View file

@ -0,0 +1,51 @@
---
description: Learn how to install and use Roo Code Nightly builds to test the latest features and improvements before official releases.
keywords:
- Roo Code Nightly
- prerelease builds
- beta testing
- latest features
- nightly builds
sidebar_label: Roo Code Nightly
---
# Roo Code Nightly
---
## Understanding Nightly vs. Other Prereleases
It's important to distinguish Roo Code Nightly from other types of prerelease software (like beta versions or release candidates):
* **Roo Code Nightly:**
* **Frequency:** Automated builds, generated on each merge to the main development branch.
* **Content:** Reflects the very latest merged code.
* **Stability:** Highly experimental; may contain bugs or incomplete features.
* **Testing:** Minimal or no manual testing before release.
* **Audience:** Primarily for developers, internal testing, or users comfortable with potentially unstable software who want to see the absolute latest changes and help identify issues early.
* **General Prerelease (e.g., Beta, Release Candidate):**
* **Frequency:** Released periodically (e.g., weekly, monthly) as specific milestones are met.
* **Content:** Represents a more curated and planned intermediate version.
* **Stability:** More stable than Nightly builds; often undergoes some manual testing or validation.
* **Testing:** Typically receives more focused testing.
* **Audience:** Intended for a wider group of early adopters or beta testers to gather feedback before a stable release.
In short: **Nightly = latest code, potentially unstable, frequent updates.** Other prereleases are generally less frequent, more validated, and aimed at broader testing.
---
## Installing Roo Code Nightly
To install Roo Code Nightly:
1. Open VS Code.
2. Access Extensions: Click the Extensions icon in the Activity Bar or press `Ctrl+Shift+X` (Windows/Linux) or `Cmd+Shift+X` (macOS).
3. Search for "Roo Code Nightly".
4. Select "Roo Code Nightly" by Roo Code and click **Install**.
5. Reload VS Code if prompted.
<img src="/img/installing/installing-5.png" alt="Roo Code Nightly extension in VS Code Marketplace" width="400" />
*Roo Code Nightly in the VS Code Marketplace.*
You can have both the stable version of Roo Code and Roo Code Nightly installed simultaneously.

View file

@ -0,0 +1,185 @@
---
description: Learn how to use context mentions (@) in Roo Code to reference files, folders, problems, terminal output, and Git commits for more accurate AI assistance.
keywords:
- "Roo Code context mentions"
- "@ mentions"
- "file references"
- "folder mentions"
- "problems panel"
- "terminal mentions"
- "Git integration"
---
# Context Mentions
Context mentions are a powerful way to provide Roo Code with specific information about your project, allowing it to perform tasks more accurately and efficiently. You can use mentions to refer to files, folders, problems, and Git commits. Context mentions start with the `@` symbol.
<img src="/img/context-mentions/context-mentions.png" alt="Context Mentions Overview - showing the @ symbol dropdown menu in the chat interface" width="600" />
_Context mentions overview showing the @ symbol dropdown menu in the chat interface._
---
## Types of Mentions
<img src="/img/context-mentions/context-mentions-1.png" alt="File mention example showing a file being referenced with @ and its contents appearing in the conversation" width="600" />
_File mentions add actual code content into the conversation for direct reference and analysis._
| Mention Type | Format | Description | Example Usage |
| ----------------- | ---------------------- | -------------------------------------------------------------------------- | -------------------------------------------------- |
| **File** | `@/path/to/file.ts` | Includes file contents in request context | "Explain the function in @/src/utils.ts" |
| **Image** | `@/path/to/image.png` | Includes image as inline visual content (file mention with vision support) | "What's wrong with this UI? @/screenshots/bug.png" |
| **Folder** | `@/path/to/folder/` | Includes contents of all files directly in the folder (non-recursive) | "Analyze the code in @/src/components/" |
| **Problems** | `@problems` | Includes VS Code Problems panel diagnostics | "@problems Fix all errors in my code" |
| **Terminal** | `@terminal` | Includes recent terminal command and output | "Fix the errors shown in @terminal" |
| **Git Commit** | `@a1b2c3d` | References specific commit by hash | "What changed in commit @a1b2c3d?" |
| **Git Changes** | `@git-changes` | Shows uncommitted changes | "Suggest a message for @git-changes" |
| **URL** | `@https://example.com` | Imports website content | "Summarize @https://docusaurus.io/" |
| **Slash Command** | `/<command-name>` | Executes a slash command (uses `/` not `@`) | "/test Run all tests" |
### File Mentions
<img src="/img/context-mentions/context-mentions-1.png" alt="File mention example showing a file being referenced with @ and its contents appearing in the conversation" width="600" />
_File mentions incorporate source code with line numbers for precise references._
| Capability | Details |
|------------|---------|
| **Format** | `@/path/to/file.ts` (always start with `/` from workspace root) |
| **Provides** | Complete file contents with line numbers |
| **Supports** | Text files, PDFs, and DOCX files (with text extraction) |
| **Works in** | Initial requests, feedback responses, and follow-up messages |
| **Limitations** | Very large files may be truncated; binary files not supported |
### Image Mentions
Image mentions are file mentions with special visual processing. When you mention an image file, and the model supports vision, the image is sent as inline visual content rather than text.
| Capability | Details |
| ------------ | ---------------------------------------------------------------------- |
| **Type** | Sub-type of file mentions (not a separate mention type) |
| **Format** | `@/path/to/image.png` (same path format as file mentions) |
| **Provides** | Image sent as inline visual content to the model |
| **Supports** | PNG, JPG, JPEG, GIF, BMP, SVG, WEBP, ICO, AVIF |
| **Best for** | UI reviews, screenshot debugging, diagram analysis |
| **Requires** | A model with vision support (non-vision models can't interpret images) |
### Folder Mentions
<img src="/img/context-mentions/context-mentions-2.png" alt="Folder mention example showing directory contents being referenced in the chat" width="600" />
_Folder mentions include the content of all files within the specified directory._
| Capability | Details |
|------------|---------|
| **Format** | `@/path/to/folder/` (trailing slash required to distinguish from file mentions) |
| **Provides** | Complete contents of all files within the directory |
| **Includes** | Contents of non-binary text files directly within the folder (not recursive) |
| **Best for** | Providing context from multiple files in a directory |
| **Tip** | Be mindful of context window limits when mentioning large directories |
### Problems Mention
<img src="/img/context-mentions/context-mentions-3.png" alt="Problems mention example showing VS Code problems panel being referenced with @problems" width="600" />
_Problems mentions import diagnostics directly from VS Code's problems panel._
| Capability | Details |
|------------|---------|
| **Format** | `@problems` |
| **Provides** | All errors and warnings from VS Code's problems panel |
| **Includes** | File paths, line numbers, and diagnostic messages |
| **Groups** | Problems organized by file for better clarity |
| **Best for** | Fixing errors without manual copying |
For comprehensive details on how Roo Code integrates with VSCode's diagnostics system, see [Diagnostics Integration](/features/diagnostics-integration).
### Terminal Mention
<img src="/img/context-mentions/context-mentions-4.png" alt="Terminal mention example showing terminal output being included in Roo's context" width="600" />
_Terminal mentions capture recent command output for debugging and analysis._
| Capability | Details |
| -------------- | -------------------------------------------------- |
| **Format** | `@terminal` |
| **Captures** | Last command and its complete output |
| **Preserves** | Terminal state (doesn't clear the terminal) |
| **Limitation** | Limited to visible terminal buffer content |
| **Best for** | Debugging build errors or analyzing command output |
### Git Mentions
<img src="/img/context-mentions/context-mentions-5.png" alt="Git commit mention example showing commit details being analyzed by Roo" width="600" />
_Git mentions provide commit details and diffs for context-aware version analysis._
| Type | Format | Provides | Limitations |
|------|--------|----------|------------|
| **Commit** | `@a1b2c3d` | Commit message, author, date, and complete diff | Only works in Git repositories |
| **Working Changes** | `@git-changes` | `git status` output and diff of uncommitted changes | Only works in Git repositories |
### URL Mentions
<img src="/img/context-mentions/context-mentions-6.png" alt="URL mention example showing website content being converted to Markdown in the chat" width="600" />
_URL mentions import external web content and convert it to readable Markdown format._
| Capability | Details |
| -------------- | ------------------------------------------------ |
| **Format** | `@https://example.com` |
| **Processing** | Uses headless browser to fetch content |
| **Cleaning** | Removes scripts, styles, and navigation elements |
| **Output** | Converts content to Markdown for readability |
| **Limitation** | Complex pages may not convert perfectly |
### Slash Command Mentions
Slash commands are processed by the mentions system but use a `/` prefix instead of `@`. They execute predefined commands to perform specific actions.
| Capability | Details |
| ---------------- | ------------------------------------------------------------ |
| **Format** | `/<command-name>` (uses `/` not `@`) |
| **Provides** | Executes the specified command and includes relevant context |
| **Content Type** | Processed as content block type "command" |
| **Examples** | `/test`, `/init`, `/deploy`, and other custom commands |
| **Best for** | Quick access to predefined workflows and actions |
For comprehensive details on available slash commands and how to create custom ones, see [Slash Commands](/features/slash-commands).
---
## How to Use Mentions
1. Type `@` in the chat input to trigger the suggestions dropdown
2. Continue typing to filter suggestions or use arrow keys to navigate
3. Select with Enter key or mouse click
4. Combine multiple mentions in a request: "Fix @problems in @/src/component.ts"
The dropdown automatically suggests:
- Recently opened files
- Visible folders
- Recent git commits
- Special keywords (`problems`, `terminal`, `git-changes`)
- **All currently open files** (regardless of ignore settings or directory filters)
The dropdown respects `.rooignore` by default, hiding ignored files from suggestions. Enable the `showRooIgnoredFiles` setting to include ignored files in the dropdown (they'll appear with a 🔒 indicator). Common directories like `node_modules`, `.git`, `dist`, and `out` are also filtered to reduce noise.
---
## Important Behaviors
### Ignore File Interactions
| Behavior | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Dropdown filtering** | The `@` dropdown hides `.rooignore`-matched files by default. Enable `showRooIgnoredFiles` to see them (marked with 🔒). |
| **`.rooignore` bypass** | File and folder `@mentions` bypass `.rooignore` checks when fetching content for context. Content from ignored files will be included if directly mentioned. |
| **`.gitignore` bypass** | Similarly, file and folder `@mentions` do not respect `.gitignore` rules when fetching content. |
| **Git command respect** | Git-related mentions (`@git-changes`, `@commit-hash`) do respect `.gitignore` since they rely on Git commands. |
---
## Related Features
- [Diagnostics Integration](/features/diagnostics-integration) - Learn about automatic error detection and smart severity filtering
- [Code Actions](/features/code-actions) - Discover quick fixes and AI assistance directly in your editor
- [Shell Integration](/features/shell-integration) - Understand how terminal mentions work with shell integration

View file

@ -0,0 +1,111 @@
---
description: Learn how Roo Code uses tools to interact with your system. Understand file operations, command execution, and the approval workflow.
keywords:
- Roo Code tools
- AI tools
- file operations
- command execution
- tool approval
---
# How Tools Work
Roo Code uses tools to interact with your code and environment. These specialized helpers perform specific actions like reading files, making edits, running commands, or searching your codebase. Tools provide automation for common development tasks without requiring manual execution.
---
## Tool Workflow
Describe what you want to accomplish in natural language, and Roo Code will:
1. Select the appropriate tool based on your request
2. Present the tool with its parameters for your review
3. Execute the approved tool and show you the results
4. Continue this process until your task is complete
---
## Tool Categories
| Category | Purpose | Tool Names |
| :------- | :----------------------------------------- | :---------------------------------------------------------------------------------- |
| Read | Access file content and code structure | `read_file`, `search_files`, `list_files`, `codebase_search`, `read_command_output` |
| Edit | Create or modify files and code | `write_to_file`, `apply_diff`, `apply_patch`, `edit`, `edit_file`, `search_replace` |
| Execute | Run commands and perform system operations | `execute_command` |
| Image | Generate AI-powered images | `generate_image` |
| Workflow | Manage task flow and context | `ask_followup_question`, `attempt_completion`, `switch_mode`, `new_task`, `skill` |
---
## Example: Using Tools
Here's how a typical tool interaction works:
<img src="/img/how-tools-work/how-tools-work.png" alt="Tool approval interface showing Save and Reject buttons along with Auto-approve checkbox" width="600" />
_The tool approval interface shows Save/Reject buttons and Auto-approve options._
**User:** Create a file named `greeting.js` that logs a greeting message
**Roo Code:** (Proposes the `write_to_file` tool as shown in the image above)
```xml
<write_to_file>
<path>greeting.js</path>
<content>
function greet(name) {
console.log(`Hello, ${name}!`);
}
greet('World');
</content>
<line_count>5</line_count>
</write_to_file>
```
**User:** (Clicks "Save" in the interface)
**Roo Code:** (Confirms file creation)
---
## Tool Safety and Approval
Every tool use requires your explicit approval. When Roo proposes a tool, you'll see:
- A "Save" button to approve and execute the tool
- A "Reject" button to decline the proposed tool
- An optional "Auto-approve" setting for trusted operations
This safety mechanism ensures you maintain control over which files are modified, what commands are executed, and how your codebase is changed. Always review tool proposals carefully before saving them.
---
## Core Tools Reference
| Tool Name | Description | Category |
| :---------------------- | :--------------------------------------------------------- | :------- |
| `read_file` | Reads the content of a file with line numbers | Read |
| `search_files` | Searches for text or regex patterns across files | Read |
| `list_files` | Lists files and directories in a specified location | Read |
| `codebase_search` | Performs semantic search across your indexed codebase | Read |
| `read_command_output` | Retrieves truncated output from previous commands | Read |
| `write_to_file` | Creates new files or overwrites existing ones | Edit |
| `apply_diff` | Makes precise changes to specific parts of a file | Edit |
| `apply_patch` | Applies multi-file unified diff patches | Edit |
| `edit` | Search-and-replace (first occurrence by default) | Edit |
| `edit_file` | Search-and-replace (all occurrences with count validation) | Edit |
| `search_replace` | Search-and-replace (all occurrences, simple) | Edit |
| `execute_command` | Runs commands in the VS Code terminal | Execute |
| `generate_image` | Generates AI-powered images from text prompts | Image |
| `ask_followup_question` | Asks you a clarifying question | Workflow |
| `attempt_completion` | Indicates the task is complete | Workflow |
| `switch_mode` | Changes to a different operational mode | Workflow |
| `new_task` | Creates a new subtask with a specific starting mode | Workflow |
| `skill` | Loads and executes predefined skill instructions | Workflow |
---
## Learn More About Tools
For more detailed information about each tool, including complete parameter references and advanced usage patterns, see the [Tool Use Overview](/advanced-usage/available-tools/tool-use-overview) documentation.

View file

@ -0,0 +1,69 @@
---
description: Learn how to use the Roo Code chat interface effectively. Understand the layout, features, and best practices for communicating with your AI coding assistant.
keywords:
- Roo Code chat interface
- AI assistant interaction
- chat features
- user interface
- VS Code extension
---
import KangarooIcon from '@site/src/components/KangarooIcon';
# The Chat Interface
The Roo Code chat interface is your primary way of interacting with it. It's located in the Roo Code panel, which you can open by clicking the Roo Code icon (<KangarooIcon />) in the VS Code Activity Bar.
---
## Components of the Chat Interface
The chat interface consists of the following main elements:
1. **Chat History:** This area displays the conversation history between you and Roo Code. It shows your requests, Roo Code's responses, and any actions taken (like file edits or command executions).
2. **Input Field:** This is where you type your tasks and questions for Roo Code. You can use plain English to communicate.
3. **Action Buttons:** These buttons appear above the input field and allow you to approve or reject Roo Code's proposed actions. The available buttons change depending on the context.
4. **Send Button:** This looks like a small plane and it's located to the far right of the input field. This sends messages to Roo after you've typed them.
5. **Plus Button:** The plus button is located at the top in the header. It switches to the Chat tab and focuses the input. To reset the session, start a new task or clear the current task.
6. **Settings Button:** The settings button is a gear, and it's used for opening the settings to customize features or behavior.
7. **Mode Selector:** The mode selector is a dropdown located to the left of the chat input field. It is used for selecting which mode Roo should use for your tasks. Its settings gear opens the Modes tab, not general settings.
<img src="/img/the-chat-interface/the-chat-interface-1.png" alt="Chat interface components labeled with numbered callouts" width="900" />
_Numbered interface elements showing the key components of the Roo Code chat interface._
---
## Tip: Using the Secondary Sidebar
For a better workflow, you can drag Roo Code to VS Code's [Secondary Sidebar](https://code.visualstudio.com/api/ux-guidelines/sidebars#secondary-sidebar). This allows you to keep Roo Code visible while still having access to the Explorer, Search, Source Control, and other panels in the primary sidebar.
To set this up:
1. Click and drag the Roo Code icon from the Activity Bar
2. Drop it on the right side of your editor to create a secondary sidebar
3. Now you can use both sidebars simultaneously!
For more productivity tips, check out our [Tips & Tricks](/tips-and-tricks) guide.
---
## Interacting with Messages
- **Clickable Links:** File paths, URLs, and other mentions in the chat history are clickable. Clicking a file path will open the file in the editor. Clicking a URL will open it in your default browser.
- **Copying Text:** You can copy text from the chat history by selecting it and using the standard copy command (Ctrl/Cmd + C). Some elements, like code blocks, have a dedicated "Copy" button.
- **Expanding and Collapsing**: Click on a message to expand or collapse it.
---
## Status Indicators
- **Loading Spinner:** When Roo Code is processing a request, you'll see a loading spinner.
- **Error Messages:** If an error occurs, a red error message will be displayed.
- **Success Messages:** Green messages indicate successful completion of actions.

View file

@ -0,0 +1,69 @@
---
description: Learn how to effectively communicate with Roo Code using natural language. Best practices for typing requests, examples, and common pitfalls to avoid.
keywords:
- Roo Code requests
- natural language AI
- typing commands
- AI communication
- request examples
- best practices
---
# Typing Your Requests
Roo Code is designed to understand natural language. You don't need to use any special commands or syntax to communicate with it. Just type your request in plain English, as if you were talking to a human developer.
<img src="/img/typing-your-requests/naturally.gif" alt="Example of typing a request in Roo Code" width="600" />
---
## Effective Request Strategies
Clearly state what you want Roo Code to do. Avoid vague or ambiguous language.
| Strategy | Implementation |
| -------------------- | ------------------------------------------------------------------------------------------ |
| **Be specific** | "Fix the bug in `calculateTotal` that returns incorrect results" instead of "Fix the code" |
| **Provide context** | Use @ [Context Mentions](/basic-usage/context-mentions) for file and code references |
| **Break down tasks** | Submit complex tasks in smaller manageable steps |
| **Include examples** | Provide sample code when you need specific formatting or style |
---
## Example Requests
```
create a new file named `utils.py` and add a function called `add` that takes two numbers as arguments and returns their sum
```
```
in the file @src/components/Button.tsx, change the color of the button to blue
```
```
find all instances of the variable `oldValue` in @/src/App.js and replace them with `newValue`
```
```
run the command `npm install` in the terminal
```
```
explain the function `calculateTotal` in @/src/utils.ts
```
```
@problems address all detected problems
```
---
## Common Pitfalls to Avoid
| DON'T | DO |
| ------------------------------- | ----------------------------------------- |
| Vague requests | Specify exactly what needs to be done |
| Assuming context | Explicitly reference files and functions |
| Excessive technical jargon | Use clear, straightforward language |
| Multiple unrelated tasks | Submit one focused request at a time |
| Proceeding without confirmation | Check the code to make sure it's complete |

View file

@ -0,0 +1,128 @@
---
description: Learn how to use Roo Code's specialized modes for different tasks. Switch between Code, Ask, Architect, Debug, and Orchestrator modes for optimal AI assistance.
keywords:
- Roo Code modes
- Code mode
- Ask mode
- Architect mode
- Debug mode
- Orchestrator mode
- AI assistant modes
- mode switching
---
# Using Modes
Modes in Roo Code are specialized personas that tailor the assistant's behavior to your current task. Each mode offers different capabilities, expertise, and access levels to help you accomplish specific goals.
:::info Sticky Models & Mode Persistence
Each mode remembers your last-used model. When switching modes, Roo automatically selects that model—no manual selection needed. Assign different models to different modes (e.g., Gemini 2.5 Preview for `🏗️ Architect` mode, Claude Sonnet 3.7 for `💻 Code` mode) and Roo will switch models automatically when you change modes.
Additionally, your selected mode persists between sessions—Roo remembers which mode you were using when you return.
:::
---
## Why Use Different Modes?
- **Task specialization:** Get precisely the type of assistance you need for your current task
- **Safety controls:** Prevent unintended file modifications when focusing on planning or learning
- **Focused interactions:** Receive responses optimized for your current activity
- **Workflow optimization:** Seamlessly transition between planning, implementing, debugging, and learning
---
## Switching Between Modes
Four ways to switch modes:
1. **Dropdown menu:** Click the selector to the left of the chat input
<img src="/img/using-modes/using-modes.png" alt="Using the dropdown menu to switch modes" width="400" />
2. **Slash command:** Type `/architect`, `/ask`, `/debug`, `/code`, or `/orchestrator` at the beginning of your message. This will switch to that mode and clear the input field.
<img src="/img/using-modes/using-modes-1.png" alt="Using slash commands to switch modes" width="400" />
3. **Toggle command/Keyboard shortcut:** Use the keyboard shortcut below, applicable to your operating system. Each press cycles through the available modes in sequence, wrapping back to the first mode after reaching the end.
| Operating System | Shortcut |
| ---------------- | -------- |
| macOS | ⌘ + . |
| Windows | Ctrl + . |
| Linux | Ctrl + . |
4. **Accept suggestions:** Click on mode switch suggestions that Roo offers when appropriate
<img src="/img/using-modes/using-modes-2.png" alt="Accepting a mode switch suggestion from Roo" width="400" />
---
## Built-in Modes
### Code Mode (Default)
| Aspect | Details |
| -------------------- | -------------------------------------------------------------------------------------------------------- |
| **Name** | `💻 Code` |
| **Description** | A skilled software engineer with expertise in programming languages, design patterns, and best practices |
| **Tool Access** | Full access to all tool groups: `read`, `edit`, `command`, `mcp` |
| **Ideal For** | Writing code, implementing features, debugging, and general development |
| **Special Features** | No tool restrictions—full flexibility for all coding tasks |
### Ask Mode
| Aspect | Details |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name** | `❓ Ask` |
| **Description** | A knowledgeable technical assistant focused on providing thorough and complete answers. It's less inclined to switch to implementing code unless explicitly requested and may use diagrams for clarification. |
| **Tool Access** | Limited access: `read`, `mcp` only (cannot edit files or run commands) |
| **Ideal For** | Code explanation, concept exploration, and technical learning |
| **Special Features** | Optimized for detailed, informative responses, often using diagrams for clarity, without modifying your project. |
### Architect Mode
| Aspect | Details |
| -------------------- | ---------------------------------------------------------------------------------------------------- |
| **Name** | `🏗️ Architect` |
| **Description** | An experienced technical leader and planner who helps design systems and create implementation plans |
| **Tool Access** | Access to `read`, `mcp`, and restricted `edit` (markdown files only) |
| **Ideal For** | System design, high-level planning, and architecture discussions |
| **Special Features** | Follows a structured approach from information gathering to detailed planning |
### Debug Mode
| Aspect | Details |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name** | `🪲 Debug` |
| **Description** | An expert problem solver specializing in systematic troubleshooting and diagnostics |
| **Tool Access** | Full access to all tool groups: `read`, `edit`, `command`, `mcp` |
| **Ideal For** | Tracking down bugs, diagnosing errors, and resolving complex issues |
| **Special Features** | Uses a methodical approach of analyzing, narrowing possibilities, and fixing issues. Includes custom instructions to reflect, distill possibilities, add logs, and confirm before fixing. |
### Orchestrator Mode (aka Boomerang Mode)
| Aspect | Details |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name** | `🪃 Orchestrator` |
| **Description** | A strategic workflow orchestrator (aka Boomerang Mode) that breaks down complex tasks and delegates them to specialized modes. Learn more about [Boomerang Tasks](/features/boomerang-tasks). |
| **Tool Access** | No direct tool access (uses `new_task` tool to delegate work to other modes) |
| **Ideal For** | Managing multi-step projects, coordinating work across different modes, and automating complex workflows |
| **Special Features** | Uses the [`new_task`](/advanced-usage/available-tools/new-task) tool to delegate subtasks to other modes. |
---
## Customizing Modes
Tailor Roo Code's behavior by customizing existing modes or creating new specialized assistants. Define tool access, file permissions, and behavior instructions to enforce team standards or create purpose-specific assistants. See [Custom Modes documentation](/features/custom-modes) for setup instructions.
### Understanding Tool Groups
Each tool group provides specific capabilities:
- **`read`**: File reading, listing, and searching capabilities
- **`edit`**: File modification and creation capabilities
- **`command`**: Terminal command execution
- **`mcp`**: Model Context Protocol server interactions
For detailed information about available tools, see the [Available Tools documentation](/advanced-usage/available-tools/tool-use-overview).

205
apps/docs/docs/faq.md Normal file
View file

@ -0,0 +1,205 @@
---
description: Find answers to common questions about Roo Code, including setup, usage, troubleshooting, and advanced features. Get help with API keys, modes, and more.
keywords:
- Roo Code FAQ
- frequently asked questions
- troubleshooting
- API setup
- custom modes
- MCP
- local models
---
import KangarooIcon from '@site/src/components/KangarooIcon';
# Frequently Asked Questions
This page answers some common questions about Roo Code.
---
## General
### What is Roo Code?
Roo Code is an open-source AI coding agent for VS Code designed to take full advantage of advanced large-language models.
### How does Roo Code work?
Roo Code uses large language models (LLMs) to understand your requests and translate them into actions. It can:
- Read and write files in your project
- Execute shell commands
- Perform web browsing (if enabled)
- Use external tools via the Model Context Protocol (MCP)
You interact with Roo Code through a chat interface in the extension.
### What can Roo Code do?
Roo Code can help with a variety of coding tasks, including:
- Generating code from natural language descriptions.
- Refactoring existing code.
- Fixing bugs.
- Writing documentation.
- Explaining code.
- Answering questions about your codebase.
- Automating repetitive tasks.
- Creating new files and projects.
### Is Roo Code free to use?
The Roo Code extension is free and [open-source](https://github.com/RooCodeInc/Roo-Code/).
Roo Code relies on external LLM inference providers (like [Anthropic](providers/anthropic), [OpenAI](providers/openai), [OpenRouter](providers/openrouter), [Requesty](providers/requesty), etc.) for its AI capabilities.
These providers typically charge for API usage based on the number of tokens processed. You will need to create an account and obtain an API key from your chosen provider. Learn more [about providers and how to set them up](/providers/) for details.
### What are the risks of using Roo Code?
Roo Code is a powerful tool, and it's important to use it responsibly. Here are some things to keep in mind:
- **Roo Code can make mistakes.** Always review Roo Code's proposed changes carefully before approving them.
- **Roo Code can execute commands.** Be very cautious about allowing Roo Code to run commands, especially if you're using auto-approval.
- **Roo Code can access the internet.** If you're using a provider that supports web browsing, be aware that Roo Code could potentially access sensitive information.
---
## Setup & Installation
### How do I install Roo Code?
See the [Installation Guide](/getting-started/installing) for detailed instructions.
### Which API providers are supported?
See the [full list here](/providers/).
### How do I get an API key?
Each API provider has its own process for obtaining an API key. See the [Setting Up Your First AI Provider](/getting-started/connecting-api-provider) for links to the relevant documentation for each provider.
### Can I use Roo Code with local models?
Yes, Roo Code supports running models locally using [Ollama](/providers/ollama) and [LM Studio](/providers/lmstudio). See [Using Local Models](/advanced-usage/local-models) for instructions.
---
## Extension Usage
### How do I start a new task?
Open the Roo Code panel (<KangarooIcon />) and type your task in the chat box. Be clear and specific about what you want Roo Code to do. See [Typing Your Requests](/basic-usage/typing-your-requests) for best practices.
### What are modes in Roo Code?
[Modes](/basic-usage/using-modes) are different personas that Roo Code can adopt, each with a specific focus and set of capabilities. The built-in modes are:
- **Code:** For general-purpose coding tasks.
- **Architect:** For planning and technical leadership.
- **Ask:** For answering questions and providing information.
- **Debug:** For systematic problem diagnosis.
You can also create [Custom Modes](/features/custom-modes).
### How do I switch between modes?
Use the dropdown menu in the chat input area to select a different mode, or use the `/` command to switch to a specific mode.
### What are tools and how do I use them?
[Tools](/basic-usage/how-tools-work) are how Roo Code interacts with your system. Roo Code automatically selects and uses the appropriate tools to complete your tasks. You don't need to call tools directly. You will be prompted to approve or reject each tool use.
### What are context mentions?
[Context mentions](/basic-usage/context-mentions) are a way to provide Roo Code with specific information about your project, such as files, folders, or problems. Use the "@" symbol followed by the item you want to mention (e.g., `@/src/file.ts`, `@problems`).
### Can Roo Code access the internet?
Yes, if you are using a provider with a model that support web browsing. Be mindful of the security implications of allowing this.
### Can Roo Code run commands in my terminal?
Yes, Roo Code can execute commands in your VS Code terminal. You will be prompted to approve each command before it's executed, unless you've enabled auto-approval for commands. Be extremely cautious about auto-approving commands. If you're experiencing issues with terminal commands, see the [Shell Integration Guide](/features/shell-integration) for troubleshooting.
### How do I provide feedback to Roo Code?
You can provide feedback by approving or rejecting Roo Code's proposed actions. You can provide additional feedback by using the feedback field.
### Can I customize Roo Code's behavior?
Yes, you can customize Roo Code in several ways:
- **Custom Instructions:** Provide general instructions that apply to all modes, or mode-specific instructions.
- **Custom Modes:** Create your own modes with tailored prompts and some tool permissions.
- **`.roorules` Files:** Create `.roorules` files in your project to provide additional guidelines.
- **Settings:** Adjust various settings, such as auto-approval, diff editing, and more.
### Does Roo Code have any auto approval settings?
Yes, Roo Code has a few settings that when enabled will automatically approve actions. Find out more [here](/features/auto-approving-actions).
---
## Advanced Features
### Can I use Roo offline?
Yes, if you use a [local model](/advanced-usage/local-models).
### What is MCP (Model Context Protocol)?
[MCP](/features/mcp/overview) is a protocol that allows Roo Code to communicate with external servers, extending its capabilities with custom tools and resources.
### Can I create my own MCP servers?
Yes, you can create your own MCP servers to add custom functionality to Roo Code. See the [MCP documentation](https://github.com/modelcontextprotocol) for details.
### What is Codebase Indexing?
[Codebase Indexing](/features/codebase-indexing) creates a semantic search index of your project using AI embeddings. This enables Roo Code to better understand and navigate large codebases by finding relevant code based on meaning rather than just keywords.
### How much does Codebase Indexing cost?
Codebase Indexing requires an OpenAI API key for generating embeddings and a Qdrant vector database for storage. Costs depend on your project size and the embedding model used. Initial indexing is the most expensive part; subsequent updates are incremental and much cheaper.
---
## Troubleshooting
### Roo Code isn't responding. What should I do?
- Make sure your API key is correct and hasn't expired.
- Check your internet connection.
- Check the status of your chosen API provider.
- Try restarting VS Code.
### I'm seeing an error message. What does it mean?
### Roo Code made changes I didn't want. How do I undo them?
Roo Code uses VS Code's built-in file editing capabilities. You can use the standard "Undo" command (Ctrl/Cmd + Z) to revert changes. Also, if experimental checkpoints are enabled, Roo can revert changes made to a file.
### Roo Code can't write to markdown files. What's wrong?
If Roo Code fails to write to `.md` files with errors like "Failed to open diff editor" or "write_to_file tool failed", this is typically caused by VS Code extensions or settings that interfere with file editing:
**Common causes:**
- Extensions with "format on save" functionality
- VS Code settings that open markdown files in preview mode by default
- The Markdown Preview extension or similar markdown processing extensions
**Solutions:**
- Disable any extensions that automatically format files on save
- Remove these settings from your VS Code `settings.json`:
```json
"markdown.preview.openMarkdownLinks": "inPreview",
"workbench.editorAssociations": {
"*.md": "vscode.markdown.preview.editor"
}
```
- Temporarily disable markdown-related extensions to test if they're causing the issue
- Restart VS Code after making these changes
### How do I report a bug or suggest a feature?

View file

@ -0,0 +1,128 @@
---
description: Learn how to create and manage API configuration profiles to easily switch between different AI providers and models in Roo Code.
keywords:
- API configuration
- profiles
- AI providers
- model switching
- API management
---
# API Configuration Profiles
API Configuration Profiles allow you to create and switch between different sets of AI settings. Each profile can have different configurations for each mode, letting you optimize your experience based on the task at hand.
:::info
Having multiple configuration profiles lets you quickly switch between different AI providers, models, and settings without reconfiguring everything each time you want to change your setup.
:::
---
## How It Works
Configuration profiles can have their own:
- API providers (OpenAI, Anthropic, OpenRouter, etc.)
- API keys and authentication details
- Model selections (o3-mini-high, Claude 3.7 Sonnet, DeepSeek R1, etc.)
- [Temperature settings](/features/model-temperature) for controlling response randomness
- Thinking budgets
- Provider-specific settings
- Diff editing configuration (see [`apply_diff`](/advanced-usage/available-tools/apply-diff))
- Rate limit settings
Note that available settings vary by provider and model. Each provider offers different configuration options, and even within the same provider, different models may support different parameter ranges or features.
---
## Creating and Managing Profiles
### Creating a Profile
1. Open Settings by clicking the gear icon <Codicon name="gear" /> → Providers
2. Click the "+" button next to the profile selector
<img src="/img/api-configuration-profiles/api-configuration-profiles-1.png" alt="Profile selector with plus button" width="550" />
3. Enter a name for your new profile
<img src="/img/api-configuration-profiles/api-configuration-profiles.png" alt="Creating a new profile dialog" width="550" />
4. Configure the profile settings:
- Select your API provider
<img src="/img/api-configuration-profiles/api-configuration-profiles-2.png" alt="Provider selection dropdown" width="550" />
- Enter API key
<img src="/img/api-configuration-profiles/api-configuration-profiles-3.png" alt="API key entry field" width="550" />
- Choose a model
<img src="/img/api-configuration-profiles/api-configuration-profiles-8.png" alt="Model selection interface" width="550" />
- Configure the **Rate Limit** for this profile:
- **Default is 0 (disabled), which is suitable for most users.** If needed, you can set a minimum time (in seconds) between API requests *for this profile* to help manage costs or avoid provider rate limits.
- A value of 0 disables rate limiting (default).
- Requests using other profiles follow their own rate limits.
<img src="/img/api-configuration-profiles/api-configuration-profiles-12.png" alt="Rate limit slider control within API profile settings" width="550" />
- Adjust model parameters (like [temperature](/features/model-temperature))
### Switching Profiles
Switch profiles in two ways:
1. From Settings panel: Select a different profile from the dropdown
<img src="/img/api-configuration-profiles/api-configuration-profiles-7.png" alt="Profile selection dropdown in Settings" width="550" />
2. During chat: Access the API Configuration dropdown in the chat interface
<img src="/img/api-configuration-profiles/api-configuration-profiles-6.png" alt="API Configuration dropdown in chat interface" width="550" />
### Pinning and Sorting Profiles
The API configuration dropdown now supports pinning your favorite profiles for quicker access:
1. Hover over any profile in the dropdown to reveal the pin icon
2. Click the pin icon to add the profile to your pinned list
3. Pinned profiles appear at the top of the dropdown, sorted alphabetically
4. Unpinned profiles appear below a separator, also sorted alphabetically
5. You can unpin a profile by clicking the same icon again
<img src="/img/api-configuration-profiles/api-configuration-profiles-4.png" alt="Pinning API configuration profiles" width="550" />
This feature makes it easier to navigate between commonly used profiles, especially when you have many configurations.
### Editing and Deleting Profiles
<img src="/img/api-configuration-profiles/api-configuration-profiles-10.png" alt="Profile editing interface" width="550" />
- Select the profile in Settings to modify any settings
- Click the pencil icon to rename a profile
- Click the trash icon to delete a profile (you cannot delete the only remaining profile)
---
## Linking Profiles to Modes
In the <Codicon name="notebook" /> Prompts tab, you can explicitly associate a specific Configuration Profile with each Mode. The system also automatically remembers which profile you last used with each mode, making your workflow more efficient.
<img src="/img/api-configuration-profiles/api-configuration-profiles-11.png" alt="Profile-Mode association interface in Prompts tab" width="550" />
---
## Per-Task Profile Persistence
Each task remembers which profile it started with. This "sticky" behavior means:
- **Reopening from history**: When you resume a task from history, it uses the same profile it had originally—even if you've since changed the global selection.
- **Multi-workspace consistency**: If you switch profiles in another workspace window, existing tasks in the first window keep their original profile.
- **Orchestrator subtasks**: Child tasks created by the orchestrator inherit the parent's profile and retain it for their lifetime.
This prevents unexpected model switches mid-task and keeps your conversation context consistent with the model that generated it.
---
## Security Note
API keys are stored securely in VSCode's Secret Storage and are never exposed in plain text.
---
## Related Features
- Works with [custom modes](/features/custom-modes) you create
- Integrates with [local models](/advanced-usage/local-models) for offline work
- Supports [temperature settings](/features/model-temperature) per mode
- Supports per-profile rate limits (configured here) and general [usage tracking/cost info](/advanced-usage/rate-limits-costs)
- Supports diff-based editing (see [`apply_diff`](/advanced-usage/available-tools/apply-diff)).

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