Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Skip onboarding flow when a provider is explicitly specified via `--provider` flag or saved in settings
- Unified permission flags: Combined `-y`, `--yes`, and `--dangerously-skip-permissions` into a single option for Claude Code-like CLI compatibility
- Unified permission flags: Combined approval-skipping flags into a single option for Claude Code-like CLI compatibility
- Improved Roo Code Router authentication flow and error messaging

### Fixed
Expand Down
57 changes: 28 additions & 29 deletions apps/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pnpm --filter @roo-code/cli build

### Interactive Mode (Default)

By default, the CLI prompts for approval before executing actions:
By default, the CLI auto-approves actions and runs in interactive TUI mode:

```bash
export OPENROUTER_API_KEY=sk-or-v1-...
Expand All @@ -82,24 +82,23 @@ roo -w ~/Documents/my-project

In interactive mode:

- Tool executions prompt for yes/no approval
- Commands prompt for yes/no approval
- Followup questions show suggestions and wait for user input
- Browser and MCP actions prompt for approval
- Tool executions are auto-approved
- Commands are auto-approved
- Followup questions show suggestions with a 60-second timeout, then auto-select the first suggestion
- Browser and MCP actions are auto-approved

### Non-Interactive Mode (`-y`)
### Approval-Required Mode (`--require-approval`)

For automation and scripts, use `-y` to auto-approve all actions:
If you want manual approval prompts, enable approval-required mode:

```bash
roo "Refactor the utils.ts file" -y -w ~/Documents/my-project
roo "Refactor the utils.ts file" --require-approval -w ~/Documents/my-project
```

In non-interactive mode:
In approval-required mode:

- Tool, command, browser, and MCP actions are auto-approved
- Followup questions show a 60-second timeout, then auto-select the first suggestion
- Typing any key cancels the timeout and allows manual input
- Tool, command, browser, and MCP actions prompt for yes/no approval
- Followup questions wait for manual input (no auto-timeout)

### Roo Code Cloud Authentication

Expand Down Expand Up @@ -147,23 +146,23 @@ Tokens are valid for 90 days. The CLI will prompt you to re-authenticate when yo

## Options

| Option | Description | Default |
| ------------------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------- |
| `[prompt]` | Your prompt (positional argument, optional) | None |
| `--prompt-file <path>` | Read prompt from a file instead of command line argument | None |
| `-w, --workspace <path>` | Workspace path to operate in | Current directory |
| `-p, --print` | Print response and exit (non-interactive mode) | `false` |
| `-e, --extension <path>` | Path to the extension bundle directory | Auto-detected |
| `-d, --debug` | Enable debug output (includes detailed debug information, prompts, paths, etc) | `false` |
| `-y, --yes, --dangerously-skip-permissions` | Auto-approve all actions (use with caution) | `false` |
| `-k, --api-key <key>` | API key for the LLM provider | From env var |
| `--provider <provider>` | API provider (roo, anthropic, openai, openrouter, etc.) | `openrouter` (or `roo` if authenticated) |
| `-m, --model <model>` | Model to use | `anthropic/claude-opus-4.6` |
| `--mode <mode>` | Mode to start in (code, architect, ask, debug, etc.) | `code` |
| `-r, --reasoning-effort <effort>` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` |
| `--ephemeral` | Run without persisting state (uses temporary storage) | `false` |
| `--oneshot` | Exit upon task completion | `false` |
| `--output-format <format>` | Output format with `--print`: `text`, `json`, or `stream-json` | `text` |
| Option | Description | Default |
| --------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------- |
| `[prompt]` | Your prompt (positional argument, optional) | None |
| `--prompt-file <path>` | Read prompt from a file instead of command line argument | None |
| `-w, --workspace <path>` | Workspace path to operate in | Current directory |
| `-p, --print` | Print response and exit (non-interactive mode) | `false` |
| `-e, --extension <path>` | Path to the extension bundle directory | Auto-detected |
| `-d, --debug` | Enable debug output (includes detailed debug information, prompts, paths, etc) | `false` |
| `-a, --require-approval` | Require manual approval before actions execute | `false` |
| `-k, --api-key <key>` | API key for the LLM provider | From env var |
| `--provider <provider>` | API provider (roo, anthropic, openai, openrouter, etc.) | `openrouter` (or `roo` if authenticated) |
| `-m, --model <model>` | Model to use | `anthropic/claude-opus-4.6` |
| `--mode <mode>` | Mode to start in (code, architect, ask, debug, etc.) | `code` |
| `-r, --reasoning-effort <effort>` | Reasoning effort level (unspecified, disabled, none, minimal, low, medium, high, xhigh) | `medium` |
| `--ephemeral` | Run without persisting state (uses temporary storage) | `false` |
| `--oneshot` | Exit upon task completion | `false` |
| `--output-format <format>` | Output format with `--print`: `text`, `json`, or `stream-json` | `text` |

## Auth Commands

Expand Down
5 changes: 3 additions & 2 deletions apps/cli/docs/AGENT_LOOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ Routes asks to appropriate handlers:

- Uses type guards: `isIdleAsk()`, `isInteractiveAsk()`, etc.
- Coordinates between `OutputManager` and `PromptManager`
- In non-interactive mode (`-y` flag), auto-approves everything
- By default, the CLI auto-approves tool/command/browser/MCP actions
- In `--require-approval` mode, those actions prompt for manual approval

### OutputManager

Expand Down Expand Up @@ -320,7 +321,7 @@ if (isInteractiveAsk(ask)) {
Enable with `-d` flag. Logs go to `~/.roo/cli-debug.log`:

```bash
roo -d -y -P "Build something" --no-tui
roo -d -P "Build something" --no-tui
```

View logs:
Expand Down
2 changes: 1 addition & 1 deletion apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"test": "vitest run",
"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 -y",
"dev": "ROO_AUTH_BASE_URL=https://app.roocode.com ROO_SDK_BASE_URL=https://cloud-api.roocode.com ROO_CODE_PROVIDER_URL=https://api.roocode.com/proxy tsx src/index.ts",
"dev:local": "ROO_AUTH_BASE_URL=http://localhost:3000 ROO_SDK_BASE_URL=http://localhost:3001 ROO_CODE_PROVIDER_URL=http://localhost:8080/proxy tsx src/index.ts",
"clean": "rimraf dist .turbo"
},
Expand Down
8 changes: 5 additions & 3 deletions apps/cli/src/commands/cli/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
flagOptions.reasoningEffort || settings.reasoningEffort || DEFAULT_FLAGS.reasoningEffort
const effectiveProvider = flagOptions.provider ?? settings.provider ?? (rooToken ? "roo" : "openrouter")
const effectiveWorkspacePath = flagOptions.workspace ? path.resolve(flagOptions.workspace) : process.cwd()
const effectiveDangerouslySkipPermissions =
flagOptions.yes || flagOptions.dangerouslySkipPermissions || settings.dangerouslySkipPermissions || false
const legacyRequireApprovalFromSettings =
settings.requireApproval ??
(settings.dangerouslySkipPermissions === undefined ? undefined : !settings.dangerouslySkipPermissions)
const effectiveRequireApproval = flagOptions.requireApproval || legacyRequireApprovalFromSettings || false
const effectiveExitOnComplete = flagOptions.print || flagOptions.oneshot || settings.oneshot || false

const extensionHostOptions: ExtensionHostOptions = {
Expand All @@ -77,7 +79,7 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
model: effectiveModel,
workspacePath: effectiveWorkspacePath,
extensionPath: path.resolve(flagOptions.extension || getDefaultExtensionPath(__dirname)),
nonInteractive: effectiveDangerouslySkipPermissions,
nonInteractive: !effectiveRequireApproval,
exitOnError: flagOptions.exitOnError,
ephemeral: flagOptions.ephemeral,
debug: flagOptions.debug,
Expand Down
3 changes: 1 addition & 2 deletions apps/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ program
.option("-p, --print", "Print response and exit (non-interactive mode)", false)
.option("-e, --extension <path>", "Path to the extension bundle directory")
.option("-d, --debug", "Enable debug output (includes detailed debug information)", false)
.option("-y, --yes", "Auto-approve all prompts (use with caution)", false)
.option("--dangerously-skip-permissions", "Alias for --yes", false)
.option("-a, --require-approval", "Require manual approval for actions", false)
.option("-k, --api-key <key>", "API key for the LLM provider")
.option("--provider <provider>", "API provider (roo, anthropic, openai, openrouter, etc.)")
.option("-m, --model <model>", "Model to use", DEFAULT_FLAGS.model)
Expand Down
23 changes: 15 additions & 8 deletions apps/cli/src/lib/storage/__tests__/settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,20 @@ describe("Settings Storage", () => {
expect(loaded.reasoningEffort).toBe("low")
})

it("should support dangerouslySkipPermissions setting", async () => {
await saveSettings({ dangerouslySkipPermissions: true })
it("should support requireApproval setting", async () => {
await saveSettings({ requireApproval: true })
const loaded = await loadSettings()

expect(loaded.dangerouslySkipPermissions).toBe(true)
expect(loaded.requireApproval).toBe(true)
})

it("should support all settings together including dangerouslySkipPermissions", async () => {
it("should support all settings together including requireApproval", async () => {
const allSettings = {
mode: "architect",
provider: "anthropic" as const,
model: "claude-sonnet-4-20250514",
reasoningEffort: "high" as const,
dangerouslySkipPermissions: true,
requireApproval: true,
}

await saveSettings(allSettings)
Expand All @@ -202,7 +202,7 @@ describe("Settings Storage", () => {
expect(loaded.provider).toBe("anthropic")
expect(loaded.model).toBe("claude-sonnet-4-20250514")
expect(loaded.reasoningEffort).toBe("high")
expect(loaded.dangerouslySkipPermissions).toBe(true)
expect(loaded.requireApproval).toBe(true)
})

it("should support oneshot setting", async () => {
Expand All @@ -218,7 +218,7 @@ describe("Settings Storage", () => {
provider: "anthropic" as const,
model: "claude-sonnet-4-20250514",
reasoningEffort: "high" as const,
dangerouslySkipPermissions: true,
requireApproval: true,
oneshot: true,
}

Expand All @@ -229,8 +229,15 @@ describe("Settings Storage", () => {
expect(loaded.provider).toBe("anthropic")
expect(loaded.model).toBe("claude-sonnet-4-20250514")
expect(loaded.reasoningEffort).toBe("high")
expect(loaded.dangerouslySkipPermissions).toBe(true)
expect(loaded.requireApproval).toBe(true)
expect(loaded.oneshot).toBe(true)
})

it("should still load legacy dangerouslySkipPermissions setting", async () => {
await saveSettings({ dangerouslySkipPermissions: true })
const loaded = await loadSettings()

expect(loaded.dangerouslySkipPermissions).toBe(true)
})
})
})
7 changes: 4 additions & 3 deletions apps/cli/src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ export type FlagOptions = {
print: boolean
extension?: string
debug: boolean
yes: boolean
dangerouslySkipPermissions: boolean
requireApproval: boolean
exitOnError: boolean
apiKey?: string
provider?: SupportedProvider
Expand Down Expand Up @@ -58,7 +57,9 @@ export interface CliSettings {
model?: string
/** Default reasoning effort level */
reasoningEffort?: ReasoningEffortFlagOptions
/** Auto-approve all prompts (use with caution) */
/** Require manual approval for tools/commands/browser/MCP actions */
requireApproval?: boolean
/** @deprecated Legacy inverse setting kept for backward compatibility */
dangerouslySkipPermissions?: boolean
/** Exit upon task completion */
oneshot?: boolean
Expand Down
1 change: 0 additions & 1 deletion packages/evals/src/cli/runTaskInCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export const runTaskWithCli = async ({ run, task, publish, logger, jobToken }: R
promptSourcePath,
"--workspace",
workspacePath,
"--yes",
"--reasoning-effort",
"disabled",
"--oneshot",
Expand Down
Loading