Skip to content

Commit 0340ee6

Browse files
committed
fix: /fast uses native Opus 4.6 fast mode via settings file, not model switch
- Fast mode is speed-optimized API config for Opus 4.6 (2.5x faster, same quality) - Writes fastMode to .claude/settings.local.json for CLI to pick up - Adds 'local' to settingSources so CLI reads local settings - Removes incorrect fastModel/Sonnet-switch logic - Updates help text with accurate fast mode description
1 parent 5381a9e commit 0340ee6

File tree

5 files changed

+59
-38
lines changed

5 files changed

+59
-38
lines changed

claude/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ export async function sendToClaudeCode(
191191
// Use Claude Code's system prompt + optional append
192192
systemPrompt: systemPromptConfig,
193193
// Load project CLAUDE.md files
194-
settingSources: ['project' as const],
194+
settingSources: ['project' as const, 'local' as const],
195195
// Native thinking config (replaces MAX_THINKING_TOKENS env var hack)
196196
...(modelOptions?.thinking && { thinking: modelOptions.thinking }),
197197
// Effort level

claude/info-commands.ts

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export const infoCommands = [
7575

7676
new SlashCommandBuilder()
7777
.setName('fast')
78-
.setDescription('Toggle fast mode — switch between default model and a fast/cheap model (Sonnet)'),
78+
.setDescription('Toggle fast mode — 2.5x faster Opus 4.6 responses (higher cost, same quality)'),
7979
];
8080

8181
// ================================
@@ -437,7 +437,7 @@ export function createInfoCommandHandlers(deps: InfoCommandHandlerDeps) {
437437
},
438438

439439
// ================================
440-
// /fast — Toggle fast mode
440+
// /fast — Toggle fast mode (Opus 4.6 speed-optimized API config)
441441
// ================================
442442
// deno-lint-ignore no-explicit-any
443443
async onFast(ctx: any): Promise<void> {
@@ -450,36 +450,26 @@ export function createInfoCommandHandlers(deps: InfoCommandHandlerDeps) {
450450
const newFastMode = !current.fastMode;
451451
deps.updateUnifiedSettings({ fastMode: newFastMode });
452452

453-
// If there's an active query, switch the model mid-session
454-
const activeQuery = getActiveQuery();
455-
if (activeQuery) {
456-
try {
457-
if (newFastMode) {
458-
await setActiveModel(current.fastModel || 'claude-sonnet-4-6');
459-
} else {
460-
// Revert to default model (undefined = SDK default)
461-
await setActiveModel(current.defaultModel || undefined);
462-
}
463-
} catch {
464-
// Mid-session switch failed — setting still applies to next query
465-
}
453+
// Write fastMode to .claude/settings.local.json so the CLI subprocess picks it up
454+
try {
455+
await writeFastModeToLocalSettings(workDir, newFastMode);
456+
} catch (err) {
457+
console.error('[/fast] Failed to write local settings:', err);
466458
}
467459

468-
const modelName = newFastMode
469-
? (current.fastModel || 'claude-sonnet-4-6')
470-
: (current.defaultModel || 'default (Opus)');
471-
const midSessionNote = activeQuery
472-
? '\nModel switched on active session.'
460+
const activeQuery = getActiveQuery();
461+
const sessionNote = activeQuery
462+
? '\n⚠️ Takes effect on **next query** (cannot toggle mid-session via SDK).'
473463
: '';
474464

475465
await ctx.reply({
476466
embeds: [{
477467
color: newFastMode ? 0xffaa00 : 0x5865f2,
478468
title: newFastMode ? '⚡ Fast Mode ON' : '🧠 Fast Mode OFF',
479469
description: newFastMode
480-
? `Switched to **${modelName}** — faster responses, lower cost.${midSessionNote}`
481-
: `Switched to **${modelName}** — full reasoning power.${midSessionNote}`,
482-
footer: { text: 'Use /fast again to toggle back' },
470+
? `Opus 4.6 fast mode enabled — **2.5x faster** responses, higher per-token cost, same quality.${sessionNote}`
471+
: `Standard Opus 4.6 mode — normal speed and pricing.${sessionNote}`,
472+
footer: { text: 'Use /fast again to toggle' },
483473
timestamp: new Date().toISOString()
484474
}]
485475
});
@@ -491,6 +481,41 @@ export function createInfoCommandHandlers(deps: InfoCommandHandlerDeps) {
491481
// Helper Functions
492482
// ================================
493483

484+
import * as path from "https://deno.land/std@0.208.0/path/mod.ts";
485+
486+
/**
487+
* Writes fastMode to .claude/settings.local.json in workDir.
488+
* The SDK loads this file via settingSources: ['local'].
489+
* Merges with existing settings to avoid clobbering other local config.
490+
*/
491+
async function writeFastModeToLocalSettings(workDir: string, fastMode: boolean): Promise<void> {
492+
const settingsDir = path.join(workDir, ".claude");
493+
const settingsPath = path.join(settingsDir, "settings.local.json");
494+
495+
// Read existing settings (if any)
496+
// deno-lint-ignore no-explicit-any
497+
let existing: Record<string, any> = {};
498+
try {
499+
const raw = await Deno.readTextFile(settingsPath);
500+
existing = JSON.parse(raw);
501+
} catch {
502+
// File doesn't exist or is invalid — start fresh
503+
}
504+
505+
// Merge fastMode
506+
existing.fastMode = fastMode;
507+
508+
// Ensure .claude/ directory exists
509+
try {
510+
await Deno.mkdir(settingsDir, { recursive: true });
511+
} catch {
512+
// Already exists
513+
}
514+
515+
await Deno.writeTextFile(settingsPath, JSON.stringify(existing, null, 2) + "\n");
516+
console.log(`[/fast] Wrote fastMode=${fastMode} to ${settingsPath}`);
517+
}
518+
494519
// deno-lint-ignore no-explicit-any
495520
async function sendFullInfoEmbed(ctx: any, account: any, models: any[], mcpServers: any[]): Promise<void> {
496521
const modelList = models.slice(0, 15).map(m => `• **${m.value}** — ${m.displayName}`).join('\n');

core/handler-registry.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,8 @@ export function createAllHandlers(
383383
const s = settings.getSettings().unified;
384384
const opts: ClaudeModelOptions = {};
385385

386-
// Model — fast mode overrides default model
387-
if (s.fastMode && s.fastModel) {
388-
opts.model = s.fastModel;
389-
} else if (s.defaultModel) {
386+
// Model — fast mode is handled by CLI via .claude/settings.local.json (not a model switch)
387+
if (s.defaultModel) {
390388
opts.model = s.defaultModel;
391389
}
392390

help/commands.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -786,18 +786,18 @@ export const COMMAND_HELP = {
786786
},
787787
"fast": {
788788
title: "⚡ Fast Mode Toggle",
789-
description: "Toggle between the default model (Opus) and a fast/cheap model (Sonnet)",
789+
description: "Toggle Opus 4.6 fast mode — 2.5x faster responses at higher per-token cost, same quality",
790790
usage: "/fast",
791791
examples: [
792792
"/fast"
793793
],
794794
parameters: [],
795795
notes: [
796796
"Toggles fast mode on/off",
797-
"Fast mode uses Sonnet for faster, cheaper responses",
798-
"Works mid-session — switches model on an active query",
799-
"Configure the fast model via /settings",
800-
"Use /fast again to toggle back to your default model"
797+
"Fast mode uses the same Opus 4.6 with a speed-optimized API config",
798+
"2.5x faster responses, higher per-token cost ($30/$150 MTok)",
799+
"Takes effect on the next query (persists across sessions)",
800+
"Use /fast again to toggle back to standard mode"
801801
]
802802
}
803803
};
@@ -877,7 +877,7 @@ export function createHelpHandlers(deps: HelpHandlerDeps) {
877877
fields: [
878878
{
879879
name: "🤖 Claude Code Commands",
880-
value: "`/claude` - Send prompts to Claude Code\n`/claude-enhanced` - Advanced Claude with options\n`/resume` - Resume conversation\n`/claude-cancel` - Cancel running operation\n`/fast` - Toggle fast mode (Opus ↔ Sonnet)",
880+
value: "`/claude` - Send prompts to Claude Code\n`/claude-enhanced` - Advanced Claude with options\n`/resume` - Resume conversation\n`/claude-cancel` - Cancel running operation\n`/fast` - Toggle fast mode (2.5x speed)",
881881
inline: false
882882
},
883883
{

settings/unified-settings.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ export interface UnifiedBotSettings {
2323
// Mode settings
2424
operationMode: 'normal' | 'plan' | 'auto-accept' | 'danger' | 'dont-ask';
2525

26-
// Fast mode — toggles between default model and a fast/cheap model
26+
// Fast mode — Opus 4.6 speed-optimized API config (2.5x faster, higher cost, same quality)
2727
fastMode: boolean;
28-
fastModel: string;
2928

3029
// Budget settings
3130
maxBudgetUsd: number | null;
@@ -87,9 +86,8 @@ export const UNIFIED_DEFAULT_SETTINGS: UnifiedBotSettings = {
8786
// Operation mode
8887
operationMode: 'normal',
8988

90-
// Fast mode — off by default, uses Sonnet as fast model
89+
// Fast mode — off by default (Opus 4.6 speed-optimized API config)
9190
fastMode: false,
92-
fastModel: 'claude-sonnet-4-6',
9391

9492
// Budget
9593
maxBudgetUsd: null,

0 commit comments

Comments
 (0)