diff --git a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue-ToolConfirmationQueue-renders-a-multiline-shell-command-with-syntax-highlighting-and-redirection-warning-SVG-snapshot-.snap.svg b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue-ToolConfirmationQueue-renders-a-multiline-shell-command-with-syntax-highlighting-and-redirection-warning-SVG-snapshot-.snap.svg
new file mode 100644
index 0000000000..32ece1f90f
--- /dev/null
+++ b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue-ToolConfirmationQueue-renders-a-multiline-shell-command-with-syntax-highlighting-and-redirection-warning-SVG-snapshot-.snap.svg
@@ -0,0 +1,88 @@
+
\ No newline at end of file
diff --git a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap
index a39d668825..8a367e3ecb 100644
--- a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap
+++ b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap
@@ -90,6 +90,33 @@ exports[`ToolConfirmationQueue > renders ExitPlanMode tool confirmation with Suc
"
`;
+exports[`ToolConfirmationQueue > renders a multiline shell command with syntax highlighting and redirection warning (SVG snapshot) 1`] = `
+"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ Action Required │
+│ │
+│ ? run_shell_command cat << 'EOF' > foo.txtRoses are red,Violets are blue,The CLI is fast,And h… │
+│ │
+│ cat << 'EOF' > foo.txt │
+│ Roses are red, │
+│ Violets are blue, │
+│ The CLI is fast, │
+│ And helpful too. │
+│ End of the poem. │
+│ EOF │
+│ echo "Poem successfully written to foo.txt" │
+│ │
+│ Note: Command contains redirection which can be undesirable. │
+│ Tip: Toggle auto-edit (Shift+Tab) to allow redirection in the future. │
+│ Allow execution of: 'cat, heredoc (<<), redirection (>), echo'? │
+│ │
+│ ● 1. Allow once │
+│ 2. Allow for this session │
+│ 3. Allow for all future sessions │
+│ 4. No, suggest changes (esc) │
+│ │
+╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
+`;
+
exports[`ToolConfirmationQueue > renders expansion hint when content is long and constrained 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────╮
│ Action Required │
diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
index b3b34ae0a8..fec1228c63 100644
--- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
+++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
@@ -240,6 +240,37 @@ describe('ToolConfirmationMessage', () => {
unmount();
});
+ it('should render multiline shell scripts with correct newlines and syntax highlighting (SVG snapshot)', async () => {
+ const confirmationDetails: SerializableConfirmationDetails = {
+ type: 'exec',
+ title: 'Confirm Multiline Script',
+ command: 'echo "hello"\nfor i in 1 2 3; do\n echo $i\ndone',
+ rootCommand: 'echo',
+ rootCommands: ['echo'],
+ };
+
+ const result = renderWithProviders(
+ ,
+ );
+ await result.waitUntilReady();
+
+ const output = result.lastFrame();
+ expect(output).toContain('echo "hello"');
+ expect(output).toContain('for i in 1 2 3; do');
+ expect(output).toContain('echo $i');
+ expect(output).toContain('done');
+
+ await expect(result).toMatchSvgSnapshot();
+ result.unmount();
+ });
+
describe('with folder trust', () => {
const editConfirmationDetails: SerializableConfirmationDetails = {
type: 'edit',
diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
index 022a68e953..b60dd4dc8b 100644
--- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
+++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
@@ -40,6 +40,7 @@ import {
import { AskUserDialog } from '../AskUserDialog.js';
import { ExitPlanModeDialog } from '../ExitPlanModeDialog.js';
import { WarningMessage } from './WarningMessage.js';
+import { colorizeCode } from '../../utils/CodeColorizer.js';
import {
getDeceptiveUrlDetails,
toUnicodeUrl,
@@ -548,9 +549,19 @@ export const ToolConfirmationMessage: React.FC<
>
{commandsToDisplay.map((cmd, idx) => (
-
- {sanitizeForDisplay(cmd)}
-
+
+ {colorizeCode({
+ code: cmd,
+ language: 'bash',
+ maxWidth: Math.max(terminalWidth, 1),
+ settings,
+ hideLineNumbers: true,
+ })}
+
))}
@@ -634,6 +645,7 @@ export const ToolConfirmationMessage: React.FC<
mcpToolDetailsText,
expandDetailsHintKey,
getPreferredEditor,
+ settings,
]);
const bodyOverflowDirection: 'top' | 'bottom' =
diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage-ToolConfirmationMessage-should-render-multiline-shell-scripts-with-correct-newlines-and-syntax-highlighting-SVG-snapshot-.snap.svg b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage-ToolConfirmationMessage-should-render-multiline-shell-scripts-with-correct-newlines-and-syntax-highlighting-SVG-snapshot-.snap.svg
new file mode 100644
index 0000000000..f6500b1d1d
--- /dev/null
+++ b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage-ToolConfirmationMessage-should-render-multiline-shell-scripts-with-correct-newlines-and-syntax-highlighting-SVG-snapshot-.snap.svg
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap
index 9e8dfe3a15..3f207df881 100644
--- a/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap
+++ b/packages/cli/src/ui/components/messages/__snapshots__/ToolConfirmationMessage.test.tsx.snap
@@ -2,7 +2,9 @@
exports[`ToolConfirmationMessage > should display multiple commands for exec type when provided 1`] = `
"echo "hello"
+
ls -la
+
whoami
Allow execution of 3 commands?
@@ -35,6 +37,19 @@ Do you want to proceed?
"
`;
+exports[`ToolConfirmationMessage > should render multiline shell scripts with correct newlines and syntax highlighting (SVG snapshot) 1`] = `
+"echo "hello"
+for i in 1 2 3; do
+ echo $i
+done
+Allow execution of: 'echo'?
+
+● 1. Allow once
+ 2. Allow for this session
+ 3. No, suggest changes (esc)
+"
+`;
+
exports[`ToolConfirmationMessage > should strip BiDi characters from MCP tool and server names 1`] = `
"MCP Server: testserver
Tool: testtool
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts
index 3066d1c173..630566090b 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.ts
+++ b/packages/cli/src/ui/hooks/useGeminiStream.ts
@@ -1799,7 +1799,6 @@ export const useGeminiStream = (
addItem,
registerBackgroundShell,
consumeUserHint,
- config,
isLowErrorVerbosity,
maybeAddSuppressedToolErrorNote,
maybeAddLowVerbosityFailureNote,