feat: add terminalAutoShow setting for auto-showing terminal on command execution

Adds a new opt-in setting "terminalAutoShow" that:
- When using VS Code terminal (shell integration enabled): automatically
  shows the terminal panel when Roo runs a command
- When using Inline Terminal (execa mode): auto-expands command output
  in the chat so users can always see what is happening

Addresses options (a) and (c) from Issue #12277.

Changes:
- packages/types: add terminalAutoShow to schema + ExtensionState
- src/core/tools/ExecuteCommandTool: conditionally call terminal.show()
- src/core/webview/ClineProvider: thread setting through state
- webview-ui: add checkbox in TerminalSettings, auto-expand in CommandExecution
- i18n: add English strings for the new setting
This commit is contained in:
Roo Code 2026-05-06 15:56:09 +00:00
parent ad25634905
commit ed32ba1cdb
9 changed files with 45 additions and 4 deletions

View file

@ -176,6 +176,7 @@ export const globalSettingsSchema = z.object({
terminalZshOhMy: z.boolean().optional(),
terminalZshP10k: z.boolean().optional(),
terminalZdotdir: z.boolean().optional(),
terminalAutoShow: z.boolean().optional(),
execaShellPath: z.string().optional(),
diagnosticsEnabled: z.boolean().optional(),
@ -356,6 +357,7 @@ export const EVALS_SETTINGS: RooCodeSettings = {
terminalZshP10k: false,
terminalZdotdir: true,
terminalShellIntegrationDisabled: true,
terminalAutoShow: false,
diagnosticsEnabled: true,

View file

@ -282,6 +282,7 @@ export type ExtensionState = Pick<
| "terminalZshOhMy"
| "terminalZshP10k"
| "terminalZdotdir"
| "terminalAutoShow"
| "execaShellPath"
| "diagnosticsEnabled"
| "language"

View file

@ -75,7 +75,7 @@ export class ExecuteCommandTool extends BaseTool<"execute_command"> {
const provider = await task.providerRef.deref()
const providerState = await provider?.getState()
const { terminalShellIntegrationDisabled = true } = providerState ?? {}
const { terminalShellIntegrationDisabled = true, terminalAutoShow = false } = providerState ?? {}
// Get command execution timeout from VSCode configuration (in seconds)
const commandExecutionTimeoutSeconds = vscode.workspace
@ -157,6 +157,7 @@ export type ExecuteCommandOptions = {
command: string
customCwd?: string
terminalShellIntegrationDisabled?: boolean
terminalAutoShow?: boolean
commandExecutionTimeout?: number
agentTimeout?: number
}
@ -168,6 +169,7 @@ export async function executeCommandInTerminal(
command,
customCwd,
terminalShellIntegrationDisabled = true,
terminalAutoShow = false,
commandExecutionTimeout = 0,
agentTimeout = 0,
}: ExecuteCommandOptions,
@ -369,7 +371,9 @@ export async function executeCommandInTerminal(
const terminal = await TerminalRegistry.getOrCreateTerminal(workingDir, task.taskId, terminalProvider)
if (terminal instanceof Terminal) {
terminal.terminal.show(true)
if (terminalAutoShow) {
terminal.terminal.show(true)
}
// Update the working directory in case the terminal we asked for has
// a different working directory so that the model will know where the

View file

@ -2162,6 +2162,7 @@ export class ClineProvider
terminalZshOhMy,
terminalZshP10k,
terminalZdotdir,
terminalAutoShow,
mcpEnabled,
currentApiConfigName,
listApiConfigMeta,
@ -2282,6 +2283,7 @@ export class ClineProvider
terminalZshOhMy: terminalZshOhMy ?? false,
terminalZshP10k: terminalZshP10k ?? false,
terminalZdotdir: terminalZdotdir ?? false,
terminalAutoShow: terminalAutoShow ?? false,
mcpEnabled: mcpEnabled ?? true,
currentApiConfigName: currentApiConfigName ?? "default",
listApiConfigMeta: listApiConfigMeta ?? [],
@ -2509,6 +2511,7 @@ export class ClineProvider
terminalZshOhMy: stateValues.terminalZshOhMy ?? false,
terminalZshP10k: stateValues.terminalZshP10k ?? false,
terminalZdotdir: stateValues.terminalZdotdir ?? false,
terminalAutoShow: stateValues.terminalAutoShow ?? false,
mode: stateValues.mode ?? defaultModeSlug,
language: stateValues.language ?? formatLanguage(vscode.env.language),
mcpEnabled: stateValues.mcpEnabled ?? true,

View file

@ -35,6 +35,7 @@ interface CommandExecutionProps {
export const CommandExecution = ({ executionId, text, icon, title }: CommandExecutionProps) => {
const {
terminalShellIntegrationDisabled = false,
terminalAutoShow = false,
allowedCommands = [],
deniedCommands = [],
setAllowedCommands,
@ -44,8 +45,10 @@ export const CommandExecution = ({ executionId, text, icon, title }: CommandExec
const { command, output: parsedOutput } = useMemo(() => parseCommandAndOutput(text), [text])
// If we aren't opening the VSCode terminal for this command then we default
// to expanding the command execution output.
const [isExpanded, setIsExpanded] = useState(terminalShellIntegrationDisabled)
// to expanding the command execution output. When terminalAutoShow is
// enabled, also auto-expand output regardless of terminal mode so users
// can always see what is happening.
const [isExpanded, setIsExpanded] = useState(terminalShellIntegrationDisabled || terminalAutoShow)
const [streamingOutput, setStreamingOutput] = useState("")
const [status, setStatus] = useState<CommandExecutionStatus | null>(null)

View file

@ -183,6 +183,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
terminalZshOhMy,
terminalZshP10k,
terminalZdotdir,
terminalAutoShow,
writeDelayMs,
showRooIgnoredFiles,
enableSubfolderRules,
@ -396,6 +397,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
terminalZshOhMy,
terminalZshP10k,
terminalZdotdir,
terminalAutoShow,
terminalOutputPreviewSize: terminalOutputPreviewSize ?? "medium",
mcpEnabled,
maxOpenTabsContext: Math.min(Math.max(0, maxOpenTabsContext ?? 20), 500),
@ -862,6 +864,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
terminalZshOhMy={terminalZshOhMy}
terminalZshP10k={terminalZshP10k}
terminalZdotdir={terminalZdotdir}
terminalAutoShow={terminalAutoShow}
setCachedStateField={setCachedStateField}
/>
)}

View file

@ -26,6 +26,7 @@ type TerminalSettingsProps = HTMLAttributes<HTMLDivElement> & {
terminalZshOhMy?: boolean
terminalZshP10k?: boolean
terminalZdotdir?: boolean
terminalAutoShow?: boolean
setCachedStateField: SetCachedStateField<
| "terminalOutputPreviewSize"
| "terminalShellIntegrationTimeout"
@ -36,6 +37,7 @@ type TerminalSettingsProps = HTMLAttributes<HTMLDivElement> & {
| "terminalZshOhMy"
| "terminalZshP10k"
| "terminalZdotdir"
| "terminalAutoShow"
>
}
@ -49,6 +51,7 @@ export const TerminalSettings = ({
terminalZshOhMy,
terminalZshP10k,
terminalZdotdir,
terminalAutoShow,
setCachedStateField,
className,
...props
@ -124,6 +127,21 @@ export const TerminalSettings = ({
{t("settings:terminal.outputPreviewSize.description")}
</div>
</SearchableSetting>
<SearchableSetting
settingId="terminal-auto-show"
section="terminal"
label={t("settings:terminal.autoShow.label")}>
<VSCodeCheckbox
checked={terminalAutoShow ?? false}
onChange={(e: any) => setCachedStateField("terminalAutoShow", e.target.checked)}
data-testid="terminal-auto-show-checkbox">
<span className="font-medium">{t("settings:terminal.autoShow.label")}</span>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm mt-1">
{t("settings:terminal.autoShow.description")}
</div>
</SearchableSetting>
</div>
</div>

View file

@ -82,6 +82,8 @@ export interface ExtensionStateContextType extends ExtensionState {
setTerminalShellIntegrationTimeout: (value: number) => void
terminalShellIntegrationDisabled?: boolean
setTerminalShellIntegrationDisabled: (value: boolean) => void
terminalAutoShow?: boolean
setTerminalAutoShow: (value: boolean) => void
terminalZdotdir?: boolean
setTerminalZdotdir: (value: boolean) => void
setTtsEnabled: (value: boolean) => void
@ -544,6 +546,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setState((prevState) => ({ ...prevState, terminalShellIntegrationTimeout: value })),
setTerminalShellIntegrationDisabled: (value) =>
setState((prevState) => ({ ...prevState, terminalShellIntegrationDisabled: value })),
setTerminalAutoShow: (value) => setState((prevState) => ({ ...prevState, terminalAutoShow: value })),
setTerminalZdotdir: (value) => setState((prevState) => ({ ...prevState, terminalZdotdir: value })),
setMcpEnabled: (value) => setState((prevState) => ({ ...prevState, mcpEnabled: value })),
setTaskSyncEnabled: (value) => setState((prevState) => ({ ...prevState, taskSyncEnabled: value }) as any),

View file

@ -754,6 +754,10 @@
"label": "Terminal character limit",
"description": "Overrides the line limit to prevent memory issues by enforcing a hard cap on output size. If exceeded, keeps the beginning and end and shows a placeholder to Roo where content is skipped. <0>Learn more</0>"
},
"autoShow": {
"label": "Auto-show terminal on command execution",
"description": "Automatically reveal the terminal panel when Roo runs a command. When using the VS Code terminal (shell integration enabled), the terminal panel is shown. When using the Inline Terminal, command output in chat is auto-expanded instead."
},
"outputPreviewSize": {
"label": "Command output preview size",
"description": "Controls how much command output Roo sees directly. Full output is always saved and accessible when needed.",