diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx index 9b4991ac..83bf8f35 100644 --- a/frontend/src/components/Settings.tsx +++ b/frontend/src/components/Settings.tsx @@ -16,7 +16,8 @@ import { RefreshCw, FileText, Eye, - BarChart3 + BarChart3, + Activity } from 'lucide-react'; import { Input, Textarea, Checkbox } from './ui/Input'; import { Button } from './ui/Button'; @@ -42,6 +43,7 @@ export function Settings({ isOpen, onClose }: SettingsProps) { const [additionalPathsText, setAdditionalPathsText] = useState(''); const [platform, setPlatform] = useState('darwin'); const [enableCrystalFooter, setEnableCrystalFooter] = useState(true); + const [disableAutoContext, setDisableAutoContext] = useState(false); const [notificationSettings, setNotificationSettings] = useState({ enabled: true, playSound: true, @@ -80,6 +82,7 @@ export function Settings({ isOpen, onClose }: SettingsProps) { setAutoCheckUpdates(data.autoCheckUpdates !== false); // Default to true setDevMode(data.devMode || false); setEnableCrystalFooter(data.enableCrystalFooter !== false); // Default to true + setDisableAutoContext(data.disableAutoContext || false); // Load additional paths const paths = data.additionalPaths || []; @@ -142,6 +145,7 @@ export function Settings({ isOpen, onClose }: SettingsProps) { devMode, enableCrystalFooter, additionalPaths: parsedPaths, + disableAutoContext, notifications: notificationSettings, analytics: { enabled: analyticsEnabled @@ -359,6 +363,21 @@ export function Settings({ isOpen, onClose }: SettingsProps) { When enabled, commits made through Crystal will include a footer crediting Crystal. This helps others know you're using Crystal for AI-powered development.

+ + } + > + setDisableAutoContext(e.target.checked)} + /> +

+ When checked, Crystal will not automatically run /context after each Claude response. This reduces wait time and Claude quota usage. +

+
{/* System Updates */} diff --git a/frontend/src/components/panels/claude/ClaudePanel.tsx b/frontend/src/components/panels/claude/ClaudePanel.tsx index 4161ae55..41e862b8 100644 --- a/frontend/src/components/panels/claude/ClaudePanel.tsx +++ b/frontend/src/components/panels/claude/ClaudePanel.tsx @@ -31,13 +31,16 @@ export const ClaudePanel: React.FC = React.memo(({ panel, isActive const transformer = React.useMemo(() => new ClaudeMessageTransformer(), []); const activeSession = hook.activeSession; const devModeEnabled = useConfigStore((state) => state.config?.devMode ?? false); + const autoContextDisabled = useConfigStore((state) => state.config?.disableAutoContext ?? false); const showDebugTabs = devModeEnabled; const claudePanelState = (panel.state.customState as ClaudePanelState | undefined) ?? {}; const contextUsage = claudePanelState.contextUsage ?? null; const autoContextRunState = claudePanelState.autoContextRunState ?? 'idle'; const isContextUpdating = autoContextRunState === 'running'; - const contextDisplay = contextUsage ?? '-- tokens (--%)'; + const contextDisplay = autoContextDisabled + ? 'auto-context disabled' + : (contextUsage ?? '-- tokens (--%)'); // Extract and store slash commands when we get JSON messages with init useEffect(() => { diff --git a/frontend/src/types/config.ts b/frontend/src/types/config.ts index d373c1a1..f22a8982 100644 --- a/frontend/src/types/config.ts +++ b/frontend/src/types/config.ts @@ -52,4 +52,6 @@ export interface AppConfig { posthogApiKey?: string; posthogHost?: string; }; + // Auto-context tracking setting (enabled by default) + disableAutoContext?: boolean; } diff --git a/main/src/events.ts b/main/src/events.ts index 14095bff..899c0fe7 100644 --- a/main/src/events.ts +++ b/main/src/events.ts @@ -22,6 +22,7 @@ import type { GitStatus } from './types/session'; export function setupEventListeners(services: AppServices, getMainWindow: () => BrowserWindow | null): void { const { + configManager, sessionManager, claudeCodeManager, executionTracker, @@ -997,8 +998,12 @@ export function setupEventListeners(services: AppServices, getMainWindow: () => skipSessionSummary = true; await finalizeAutoContextRun(panelId); } else if (exitCode === 0) { + if (configManager.isAutoContextDisabled()) { + console.log(`[auto-context-debug] Auto-context disabled in settings - skipping`); + } else { console.log(`[auto-context-debug] Starting auto context run for panel ${panelId}`); await startAutoContextRun(panelId, sessionId); + } } else { console.log(`[auto-context-debug] Skipping auto context - exitCode is ${exitCode}, not 0`); } diff --git a/main/src/services/configManager.ts b/main/src/services/configManager.ts index c5a9b936..216c552e 100644 --- a/main/src/services/configManager.ts +++ b/main/src/services/configManager.ts @@ -215,6 +215,10 @@ export class ConfigManager extends EventEmitter { return this.config.analytics?.distinctId; } + + isAutoContextDisabled(): boolean { + return this.config.disableAutoContext === true; + } async setAnalyticsDistinctId(distinctId: string): Promise { if (!this.config.analytics) { this.config.analytics = { diff --git a/main/src/types/config.ts b/main/src/types/config.ts index 3b5732b6..8900c0fa 100644 --- a/main/src/types/config.ts +++ b/main/src/types/config.ts @@ -16,6 +16,8 @@ export interface AppConfig { defaultModel?: string; // Auto-check for updates autoCheckUpdates?: boolean; + // Disable automatic context tracking after Claude responses + disableAutoContext?: boolean; // Stravu MCP integration stravuApiKey?: string; stravuServerUrl?: string; @@ -81,6 +83,7 @@ export interface UpdateConfigRequest { defaultPermissionMode?: 'approve' | 'ignore'; defaultModel?: string; autoCheckUpdates?: boolean; + disableAutoContext?: boolean; stravuApiKey?: string; stravuServerUrl?: string; theme?: 'light' | 'dark';