{t("trust.dialogTitle")}
@@ -28118,15 +28226,15 @@ index 30cea87..1f46ec2 100644
test("only the files tab removes worktrees, never the main one", () => {
diff --git a/components/ProjectWorktreePicker.tsx b/components/ProjectWorktreePicker.tsx
-index 5dd524f..2adf28a 100644
+index 5dd524f..9322ae9 100644
--- a/components/ProjectWorktreePicker.tsx
+++ b/components/ProjectWorktreePicker.tsx
@@ -14,6 +14,8 @@ import {
import { projectNameOf } from "@/lib/session-tree";
import { ActivitySummary } from "./SessionTree";
import { SidebarMenu, type SidebarMenuAnchor, type SidebarMenuItem } from "./SidebarMenu";
-+import { CarbonIcon } from "./CarbonIcon";
-+import * as Carbon from "./carbon/icons";
++import { LucideIcon } from "./LucideIcon";
++import * as Lucide from "./lucide/icons";
import { BranchIcon, ChevronIcon, FolderIcon, FolderPlusIcon, PlusIcon, TrashIcon } from "./SidebarIcons";
import { WorktreeCreateForm } from "./WorktreeCreateForm";
@@ -28263,7 +28371,7 @@ index 5dd524f..2adf28a 100644
+ id: "worktree-switch",
+ label: t("chatWorktree.switch"),
+ title: t("chatWorktree.switchTip", { branch: current ? current.branch ?? displayPath(current.path, homeDir) : "…" }),
-+ icon:
,
++ icon:
,
+ switchOn: worktreeSwitch.on,
+ onSelect: ({ keepOpen }) => {
+ keepOpen();
@@ -28305,7 +28413,7 @@ index 5dd524f..2adf28a 100644
+ whole path, cut at its left (the folder name at its end is what
+ tells paths apart), no icon and no chevron: the path is the box.
+ A project the user named shows that name; the tooltip keeps the path. */}
-+ {chin &&
}
++ {chin &&
}
{/* A twin's parent folder is cut before its name, the "/" never. */}
- {inline && project ? (
+ {chin && project ? (
@@ -28317,7 +28425,7 @@ index 5dd524f..2adf28a 100644
)}
- {inline &&
}
-+ {chin &&
}
++ {chin &&
}
{worktrees && (
-
{current ? current.branch ?? displayPath(current.path, homeDir) : "…"}
+ {chin
-+ ?
++ ?
+ :
}
+ {/* With the switch on the chat will not run in the branch shown but in a new worktree
+ from it: the button says that, in words (not a branch, so not in code type); the
@@ -28355,7 +28463,7 @@ index 5dd524f..2adf28a 100644
{stacked && worktrees.length > 1 &&
{worktrees.length}}
-
+ {chin
-+ ?
++ ?
+ :
}
)}
@@ -28397,15 +28505,15 @@ index 29d1cd9..a9c4a7b 100644
display: "inline-flex",
alignItems: "center",
diff --git a/components/ProviderUsageSummary.tsx b/components/ProviderUsageSummary.tsx
-index cf38be6..c08aaef 100644
+index cf38be6..442bef1 100644
--- a/components/ProviderUsageSummary.tsx
+++ b/components/ProviderUsageSummary.tsx
@@ -4,6 +4,8 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { useI18n } from "@/hooks/useI18n";
import { formatUpdatedTime } from "@/lib/i18n/format";
import { isProviderUsageId } from "@/lib/provider-usage-ids";
-+import { CarbonIcon } from "./CarbonIcon";
-+import * as Carbon from "./carbon/icons";
++import { LucideIcon } from "./LucideIcon";
++import * as Lucide from "./lucide/icons";
type UsageBucket = {
id: string;
@@ -28420,13 +28528,13 @@ index cf38be6..c08aaef 100644
-
-+
++
) : (
-
-+
++
)}
{report && (
@@ -28464,7 +28572,7 @@ index 0000000..5b40b0f
+});
diff --git a/components/SearchCommandBar.tsx b/components/SearchCommandBar.tsx
new file mode 100644
-index 0000000..759983d
+index 0000000..a3c06d4
--- /dev/null
+++ b/components/SearchCommandBar.tsx
@@ -0,0 +1,210 @@
@@ -28484,8 +28592,8 @@ index 0000000..759983d
+import { formatShortRelativeTime } from "@/lib/i18n/format";
+import type { SessionInfo } from "@/lib/types";
+import type { SessionSearchResponse, SessionSearchResult } from "@/lib/session-search";
-+import { CarbonIcon } from "./CarbonIcon";
-+import * as Carbon from "./carbon/icons";
++import { LucideIcon } from "./LucideIcon";
++import * as Lucide from "./lucide/icons";
+
+const RECENT_LIMIT = 8;
+
@@ -28605,7 +28713,7 @@ index 0000000..759983d
+
+
+
-+
++
+
-
-
-+
++
);
}
@@ -28772,7 +28880,7 @@ index 555da8f..0b5228b 100644
- {children}
+ {media &&
{media}}
+
{children}
-+
{active && }
++
{active && }
{star?.isDefault && (
-
= {
-+ extensions: { icon: Carbon.Extensions, labelKey: "pane.extensions" },
-+ terminal: { icon: Carbon.Terminal, labelKey: "pane.terminal", shortcut: "terminal" },
-+ changes: { icon: Carbon.FileDiff, labelKey: "pane.changes", shortcut: "changes" },
-+ browser: { icon: Carbon.Earth, labelKey: "pane.browser", shortcut: "browser" },
-+ files: { icon: Carbon.Folder, labelKey: "pane.files", shortcut: "files" },
++export const PANES: Record = {
++ extensions: { icon: Lucide.Blocks, labelKey: "pane.extensions" },
++ terminal: { icon: Lucide.Terminal, labelKey: "pane.terminal", shortcut: "terminal" },
++ changes: { icon: Lucide.FileDiff, labelKey: "pane.changes", shortcut: "changes" },
++ browser: { icon: Lucide.Globe, labelKey: "pane.browser", shortcut: "browser" },
++ files: { icon: Lucide.Folder, labelKey: "pane.files", shortcut: "files" },
+};
+
+/** The title keeps at least this much before the pane buttons fold. */
@@ -28956,7 +29064,7 @@ index 0000000..05731f2
+export interface SessionMenuAction {
+ id: string;
+ label: string;
-+ icon: Carbon.CarbonIconData;
++ icon: Lucide.IconData;
+ onSelect: () => void;
+ disabled?: boolean;
+ hint?: string;
@@ -29069,7 +29177,7 @@ index 0000000..05731f2
+ data-updated={id === "extensions" && extensionsUpdated ? "" : undefined}
+ onClick={() => onTogglePane(id)}
+ >
-+
++
+ {showStat && }
+
+
@@ -29087,7 +29195,7 @@ index 0000000..05731f2
+ aria-expanded={sidebarOpen}
+ aria-controls="session-sidebar"
+ >
-+
++
+
+
+ {leading}
@@ -29095,7 +29203,7 @@ index 0000000..05731f2
+
+
+ {title}
-+ {sessionActions.length > 0 && }
++ {sessionActions.length > 0 && }
+
+
+ {sessionActions.map((action, index) => (
@@ -29118,7 +29226,7 @@ index 0000000..05731f2
+
+
+
-+
++
+
+
+
@@ -30066,7 +30174,7 @@ index f96a924..a2a7011 100644
type="button"
className={`session-tree-action session-tree-more-action${menuOpen ? " is-active" : ""}`}
diff --git a/components/SettingsPanel.tsx b/components/SettingsPanel.tsx
-index c5f4676..d54a296 100644
+index c5f4676..c65472f 100644
--- a/components/SettingsPanel.tsx
+++ b/components/SettingsPanel.tsx
@@ -3,7 +3,7 @@
@@ -30086,8 +30194,8 @@ index c5f4676..d54a296 100644
+import { ConfigButton, ConfigGroup, ConfigRow, ConfigSegmented, ConfigSwitch } from "./SettingsUi";
import { FontSettings } from "./FontSettings";
+import { keepTabInside, rangeFill } from "@/lib/focus";
-+import { CarbonIcon } from "./CarbonIcon";
-+import * as Carbon from "./carbon/icons";
++import { LucideIcon } from "./LucideIcon";
++import * as Lucide from "./lucide/icons";
interface Props {
cwd: string | null;
@@ -30101,7 +30209,7 @@ index c5f4676..d54a296 100644
/** The page's trust status for `cwd`; Settings › MCP reloads when it changes, as after trusting. */
projectTrust?: ProjectTrustStatus | null;
/** Opens the page's trust dialog for `cwd`, above Settings; Settings › MCP's trust notice offers it. */
-@@ -52,29 +58,21 @@ interface Props {
+@@ -52,29 +58,20 @@ interface Props {
onProjectTrustChanged?: (cwd: string, status: ProjectTrustStatus) => void;
}
@@ -30125,18 +30233,17 @@ index c5f4676..d54a296 100644
- if (section === "agents") return ;
- if (section === "mcp") return ;
- return ;
-+export function SettingsSectionIcon({ section, size = 16, strokeWidth: _strokeWidth }: { section: SettingsSection; size?: number; strokeWidth?: number }) {
-+ // IBM Carbon icons; the stroke width of the old line icons no longer applies.
++export function SettingsSectionIcon({ section, size = 16, strokeWidth }: { section: SettingsSection; size?: number; strokeWidth?: number }) {
+ const icon = {
-+ general: Carbon.SettingsAdjust,
-+ models: Carbon.Chip,
-+ skills: Carbon.Layers,
-+ agents: Carbon.Bot,
-+ mcp: Carbon.ServerDns,
-+ plugins: Carbon.Plug,
-+ }[section as string] ?? Carbon.Plug;
++ general: Lucide.SlidersHorizontal,
++ models: Lucide.Cpu,
++ skills: Lucide.Layers,
++ agents: Lucide.Bot,
++ mcp: Lucide.Server,
++ plugins: Lucide.Plug,
++ }[section as string] ?? Lucide.Plug;
+ // One size for all: every glyph's ink is then 14px tall (measured); the Bot was once scaled 1.25x and stood out.
-+ return ;
++ return ;
}
-function GeneralSettings({ sessionId, onSessionReloaded, quoteSelectionEnabled, onQuoteSelectionChange }: Pick) {
@@ -30144,7 +30251,7 @@ index c5f4676..d54a296 100644
const { locale, setLocale, supportedLocales, t } = useI18n();
const { preference, setThemePreference } = useTheme();
const { width: chatContentWidth, setWidth: setChatContentWidth, fontSize, setFontSize } = useChatAppearance();
-@@ -209,299 +207,273 @@ function GeneralSettings({ sessionId, onSessionReloaded, quoteSelectionEnabled,
+@@ -209,299 +206,273 @@ function GeneralSettings({ sessionId, onSessionReloaded, quoteSelectionEnabled,
}
};
@@ -30588,7 +30695,7 @@ index c5f4676..d54a296 100644
+
+
+ void logOut()}>
-+
++
+ {loggingOut ? t("auth.loggingOut") : t("auth.logOut")}
+
+
@@ -30639,7 +30746,7 @@ index c5f4676..d54a296 100644
+ disabled={value === defaultValue}
+ onClick={() => onChange(defaultValue)}
+ >
-+
++
+
+
+ );
@@ -30673,7 +30780,7 @@ index c5f4676..d54a296 100644
export function SettingsPanel({
cwd,
sessionId,
-@@ -510,12 +482,26 @@ export function SettingsPanel({
+@@ -510,12 +481,26 @@ export function SettingsPanel({
onSessionReloaded,
quoteSelectionEnabled,
onQuoteSelectionChange,
@@ -30700,7 +30807,7 @@ index c5f4676..d54a296 100644
const [mountedSections, setMountedSections] = useState>(
() => new Set([section]),
);
-@@ -569,6 +555,8 @@ export function SettingsPanel({
+@@ -569,6 +554,8 @@ export function SettingsPanel({
) : null;
@@ -30709,7 +30816,7 @@ index c5f4676..d54a296 100644
return (
{ if (event.target === event.currentTarget) onClose(); }}
@@ -30738,7 +30845,7 @@ index c5f4676..d54a296 100644
+
+
{t("settings.title")}
+
+
+
@@ -31593,7 +31699,7 @@ index be44655..019eaff 100644
- }
-});
diff --git a/components/TabBar.tsx b/components/TabBar.tsx
-index fbb4e5a..6962dc0 100644
+index fbb4e5a..6abeb9e 100644
--- a/components/TabBar.tsx
+++ b/components/TabBar.tsx
@@ -1,15 +1,24 @@
@@ -31611,8 +31717,8 @@ index fbb4e5a..6962dc0 100644
import { getFileIcon } from "./FileIcons";
import { useI18n } from "@/hooks/useI18n";
import type { FileViewerDisplayMode, FileViewerState } from "@/lib/file-viewer-state";
-+import { CarbonIcon } from "./CarbonIcon";
-+import * as Carbon from "./carbon/icons";
++import { LucideIcon } from "./LucideIcon";
++import * as Lucide from "./lucide/icons";
export interface Tab {
id: string;
@@ -31813,7 +31919,7 @@ index fbb4e5a..6962dc0 100644
- );
- })}
+
-+ {tab.kind === "agent" ? : getFileIcon(tab.label, 14)}
++ {tab.kind === "agent" ? : getFileIcon(tab.label, 14)}
+
+
+ {tab.label}
@@ -31827,7 +31933,7 @@ index fbb4e5a..6962dc0 100644
+ aria-label={`${t("i18n.close")} ${tab.label}`}
+ onClick={(event) => { event.stopPropagation(); onCloseTab(tab.id); }}
+ >
-+
++
+
+
+ );
@@ -32574,7 +32680,7 @@ index 0000000..609a2e2
+});
diff --git a/components/TerminalTabs.tsx b/components/TerminalTabs.tsx
new file mode 100644
-index 0000000..0e3aab1
+index 0000000..9c88cb2
--- /dev/null
+++ b/components/TerminalTabs.tsx
@@ -0,0 +1,451 @@
@@ -32602,8 +32708,8 @@ index 0000000..0e3aab1
+ TERMINAL_SCROLLBACK_OPTIONS,
+ type TerminalCursorStyle,
+} from "@/lib/terminal-settings";
-+import { CarbonIcon } from "./CarbonIcon";
-+import * as Carbon from "./carbon/icons";
++import { LucideIcon } from "./LucideIcon";
++import * as Lucide from "./lucide/icons";
+import { MenuCheckboxItem, MenuItem, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuRoot, MenuSeparator, MenuSubmenu, MenuTrigger, PointMenu } from "./ui/menu";
+import { Tip } from "./ui/tooltip";
+
@@ -32895,7 +33001,7 @@ index 0000000..0e3aab1
+ onClose(tab.id);
+ }}
+ >
-+