diff --git a/src/main/lib/trpc/routers/claude.ts b/src/main/lib/trpc/routers/claude.ts
index 9e5eadffe..a987b06eb 100644
--- a/src/main/lib/trpc/routers/claude.ts
+++ b/src/main/lib/trpc/routers/claude.ts
@@ -810,7 +810,9 @@ export const claudeRouter = router({
baseUrl: z.string().min(1),
})
.optional(),
- maxThinkingTokens: z.number().optional(), // Enable extended thinking
+ effort: z
+ .enum(["low", "medium", "high", "xhigh", "max"])
+ .optional(), // Thinking/reasoning effort level
images: z.array(imageAttachmentSchema).optional(), // Image attachments
historyEnabled: z.boolean().optional(),
offlineModeEnabled: z.boolean().optional(), // Whether offline mode (Ollama) is enabled in settings
@@ -1994,9 +1996,7 @@ ${prompt}
...(!resumeSessionId && { continue: true }),
...(resolvedModel && { model: resolvedModel }),
// fallbackModel: "claude-opus-4-5-20251101",
- ...(input.maxThinkingTokens && {
- maxThinkingTokens: input.maxThinkingTokens,
- }),
+ ...(input.effort && { effort: input.effort }),
},
}
diff --git a/src/renderer/components/dialogs/settings-tabs/agents-preferences-tab.tsx b/src/renderer/components/dialogs/settings-tabs/agents-preferences-tab.tsx
index 7d5af6e64..bd39e8ed8 100644
--- a/src/renderer/components/dialogs/settings-tabs/agents-preferences-tab.tsx
+++ b/src/renderer/components/dialogs/settings-tabs/agents-preferences-tab.tsx
@@ -6,7 +6,6 @@ import {
ctrlTabTargetAtom,
defaultAgentModeAtom,
desktopNotificationsEnabledAtom,
- extendedThinkingEnabledAtom,
notifyWhenFocusedAtom,
soundNotificationsEnabledAtom,
preferredEditorAtom,
@@ -14,6 +13,11 @@ import {
type AutoAdvanceTarget,
type CtrlTabTarget,
} from "../../../lib/atoms"
+import { lastSelectedClaudeThinkingAtom } from "../../../features/agents/atoms"
+import {
+ formatClaudeThinkingLabel,
+ type ClaudeThinkingLevel,
+} from "../../../features/agents/lib/models"
import { APP_META, type ExternalApp } from "../../../../shared/external-apps"
// Editor icon imports
@@ -142,8 +146,8 @@ function useIsNarrowScreen(): boolean {
}
export function AgentsPreferencesTab() {
- const [thinkingEnabled, setThinkingEnabled] = useAtom(
- extendedThinkingEnabledAtom,
+ const [claudeThinking, setClaudeThinking] = useAtom(
+ lastSelectedClaudeThinkingAtom,
)
const [soundEnabled, setSoundEnabled] = useAtom(soundNotificationsEnabledAtom)
const [desktopNotificationsEnabled, setDesktopNotificationsEnabled] = useAtom(desktopNotificationsEnabledAtom)
@@ -197,18 +201,34 @@ export function AgentsPreferencesTab() {
- Extended Thinking
+ Thinking Effort
- Enable deeper reasoning with more thinking tokens (uses more
- credits).{" "}
- Disables response streaming.
+ Default effort level for Claude's reasoning. Higher levels think
+ longer and use more credits.
-
+
diff --git a/src/renderer/features/agents/atoms/index.ts b/src/renderer/features/agents/atoms/index.ts
index 666975a20..ada0526e3 100644
--- a/src/renderer/features/agents/atoms/index.ts
+++ b/src/renderer/features/agents/atoms/index.ts
@@ -234,6 +234,34 @@ export const lastSelectedCodexThinkingAtom = atomWithStorage(
+ "agents:lastSelectedClaudeThinking",
+ readInitialClaudeThinking(),
+ undefined,
+ { getOnInit: true },
+)
+
// Storage for per-subChat Claude model selection.
// Falls back to lastSelectedModelIdAtom when sub-chat has no explicit selection yet.
const subChatModelIdsStorageAtom = atomWithStorage>(
@@ -323,6 +351,38 @@ export const subChatCodexThinkingAtomFamily = atomFamily((subChatId: string) =>
),
)
+// Storage for per-subChat Claude thinking level.
+// Falls back to lastSelectedClaudeThinkingAtom when sub-chat has no explicit selection yet.
+const subChatClaudeThinkingStorageAtom = atomWithStorage<
+ Record
+>(
+ "agents:subChatClaudeThinking",
+ {},
+ undefined,
+ { getOnInit: true },
+)
+
+export const subChatClaudeThinkingAtomFamily = atomFamily((subChatId: string) =>
+ atom(
+ (get) => {
+ if (!subChatId) return get(lastSelectedClaudeThinkingAtom)
+ return (
+ get(subChatClaudeThinkingStorageAtom)[subChatId] ??
+ get(lastSelectedClaudeThinkingAtom)
+ )
+ },
+ (get, set, newThinking: ClaudeThinkingPreference) => {
+ if (!subChatId) {
+ set(lastSelectedClaudeThinkingAtom, newThinking)
+ return
+ }
+ const current = get(subChatClaudeThinkingStorageAtom)
+ if (current[subChatId] === newThinking) return
+ set(subChatClaudeThinkingStorageAtom, { ...current, [subChatId]: newThinking })
+ },
+ ),
+)
+
// Storage for all sub-chat modes (persisted per subChatId)
const subChatModesStorageAtom = atomWithStorage>(
"agents:subChatModes",
diff --git a/src/renderer/features/agents/components/agent-model-selector.tsx b/src/renderer/features/agents/components/agent-model-selector.tsx
index 56cc4333c..035cfd53c 100644
--- a/src/renderer/features/agents/components/agent-model-selector.tsx
+++ b/src/renderer/features/agents/components/agent-model-selector.tsx
@@ -13,8 +13,7 @@ import {
CommandList,
CommandSeparator,
} from "../../../components/ui/command"
-import { CheckIcon, ClaudeCodeIcon, IconChevronDown, ThinkingIcon } from "../../../components/ui/icons"
-import { Switch } from "../../../components/ui/switch"
+import { CheckIcon, ClaudeCodeIcon, IconChevronDown } from "../../../components/ui/icons"
import { Checkbox } from "../../../components/ui/checkbox"
import { Button } from "../../../components/ui/button"
import {
@@ -23,8 +22,11 @@ import {
PopoverTrigger,
} from "../../../components/ui/popover"
import { cn } from "../../../lib/utils"
-import type { CodexThinkingLevel } from "../lib/models"
-import { formatCodexThinkingLabel } from "../lib/models"
+import type { ClaudeThinkingLevel, CodexThinkingLevel } from "../lib/models"
+import {
+ formatClaudeThinkingLabel,
+ formatCodexThinkingLabel,
+} from "../lib/models"
const CROSS_PROVIDER_DIALOG_DISMISSED_KEY = "agent-model-selector:skip-cross-provider-dialog"
@@ -40,6 +42,7 @@ type ClaudeModelOption = {
id: string
name: string
version: string
+ thinkings: ClaudeThinkingLevel[]
}
type CodexModelOption = {
@@ -70,8 +73,8 @@ interface AgentModelSelectorProps {
recommendedOllamaModel?: string
onSelectOllamaModel: (modelId: string) => void
isConnected: boolean
- thinkingEnabled: boolean
- onThinkingChange: (enabled: boolean) => void
+ selectedThinking: ClaudeThinkingLevel
+ onSelectThinking: (thinking: ClaudeThinkingLevel) => void
}
codex: {
models: CodexModelOption[]
@@ -89,14 +92,16 @@ type FlatModelItem =
| { type: "ollama"; modelName: string; isRecommended: boolean }
| { type: "custom" }
-function CodexThinkingSubMenu({
- thinkings,
- selectedThinking,
- onSelectThinking,
+function ThinkingSubMenu({
+ levels,
+ selected,
+ onSelect,
+ formatLabel,
}: {
- thinkings: CodexThinkingLevel[]
- selectedThinking: CodexThinkingLevel
- onSelectThinking: (thinking: CodexThinkingLevel) => void
+ levels: T[]
+ selected: T
+ onSelect: (level: T) => void
+ formatLabel: (level: T) => string
}) {
const triggerRef = useRef(null)
const subMenuRef = useRef(null)
@@ -167,9 +172,7 @@ function CodexThinkingSubMenu({
Thinking
-
- {formatCodexThinkingLabel(selectedThinking)}
-
+ {formatLabel(selected)}
@@ -183,15 +186,15 @@ function CodexThinkingSubMenu({
className="fixed z-50 min-w-[180px] overflow-auto rounded-[10px] border border-border bg-popover text-sm text-popover-foreground shadow-lg py-1 animate-in fade-in-0 zoom-in-95 slide-in-from-left-2"
style={{ top: subPos.top, left: subPos.left }}
>
- {thinkings.map((thinking) => {
- const isSelected = selectedThinking === thinking
+ {levels.map((level) => {
+ const isSelected = selected === level
return (