diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 32c96ea..bbc1ef0 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -2618,6 +2618,39 @@ pub async fn open_binary_file(app: AppHandle, path: String) -> Result<(), String } } +/// Read the contents of `~/.claude/CLAUDE.md`. +/// Returns an empty string if the file does not exist. +#[tauri::command] +pub async fn get_global_claude_md() -> Result { + let path = dirs::home_dir() + .ok_or_else(|| "Could not determine home directory".to_string())? + .join(".claude") + .join("CLAUDE.md"); + + if !path.exists() { + return Ok(String::new()); + } + + std::fs::read_to_string(&path).map_err(|e| format!("Failed to read CLAUDE.md: {}", e)) +} + +/// Write content to `~/.claude/CLAUDE.md`. +/// Creates the file (and `~/.claude/` directory) if they do not exist. +#[tauri::command] +pub async fn save_global_claude_md(content: String) -> Result<(), String> { + let claude_dir = dirs::home_dir() + .ok_or_else(|| "Could not determine home directory".to_string())? + .join(".claude"); + + if !claude_dir.exists() { + std::fs::create_dir_all(&claude_dir) + .map_err(|e| format!("Failed to create ~/.claude directory: {}", e))?; + } + + let path = claude_dir.join("CLAUDE.md"); + std::fs::write(&path, content).map_err(|e| format!("Failed to write CLAUDE.md: {}", e)) +} + #[cfg(test)] mod tests { use super::*; @@ -3367,4 +3400,22 @@ gitea: gitea-mcp -t stdio (STDIO) - ✓ Connected"#; let (_, args) = build_wslpath_command(path); assert_eq!(args[2], path); } + + #[test] + fn test_get_global_claude_md_path_construction() { + // Verify that home_dir() resolves successfully on the test platform + let home = dirs::home_dir(); + assert!(home.is_some(), "home_dir() should be available in test environment"); + let expected = home.unwrap().join(".claude").join("CLAUDE.md"); + assert!(expected.to_string_lossy().contains(".claude")); + assert!(expected.to_string_lossy().ends_with("CLAUDE.md")); + } + + #[test] + fn test_save_global_claude_md_dir_path_construction() { + let home = dirs::home_dir(); + assert!(home.is_some()); + let dir = home.unwrap().join(".claude"); + assert!(dir.to_string_lossy().contains(".claude")); + } } diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index fc89406..9ca2af7 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -57,6 +57,19 @@ pub struct ClaudeStartOptions { #[serde(default)] pub disable_skill_shell_execution: bool, + + /// Pass `--bare` flag to suppress UI chrome, useful for scripted headless `-p` calls (v2.1.81+). + #[serde(default)] + pub bare_mode: bool, + + /// Controls `showClearContextOnPlanAccept` in `--settings` (v2.1.81+). + /// Defaults to true (matching CLI default). Set to false to suppress the dialog. + #[serde(default = "default_show_clear_context")] + pub show_clear_context_on_plan_accept: bool, + + /// Sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers (v2.1.81+). + #[serde(default)] + pub custom_model_option: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -211,6 +224,18 @@ pub struct HikariConfig { /// Passes `"disableSkillShellExecution": true` via the `--settings` flag. #[serde(default)] pub disable_skill_shell_execution: bool, + + /// Pass `--bare` flag to suppress UI chrome, useful for scripted headless `-p` calls (v2.1.81+). + #[serde(default)] + pub bare_mode: bool, + + /// Controls `showClearContextOnPlanAccept` in `--settings` (v2.1.81+). + #[serde(default = "default_show_clear_context")] + pub show_clear_context_on_plan_accept: bool, + + /// Sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers (v2.1.81+). + #[serde(default)] + pub custom_model_option: Option, } impl Default for HikariConfig { @@ -263,6 +288,9 @@ impl Default for HikariConfig { auto_memory_directory: None, model_overrides: None, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: None, } } } @@ -315,6 +343,10 @@ fn default_enable_claudeai_mcp_servers() -> bool { true } +fn default_show_clear_context() -> bool { + true +} + #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] #[serde(rename_all = "lowercase")] pub enum BudgetAction { @@ -415,6 +447,9 @@ mod tests { assert!(config.auto_memory_directory.is_none()); assert!(config.model_overrides.is_none()); assert!(!config.disable_skill_shell_execution); + assert!(!config.bare_mode); + assert!(config.show_clear_context_on_plan_accept); + assert!(config.custom_model_option.is_none()); } #[test] @@ -470,6 +505,9 @@ mod tests { "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-6-v1".to_string(), )])), disable_skill_shell_execution: true, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: None, }; let json = serde_json::to_string(&config).unwrap(); diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 0e1ec59..b81b434 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -224,6 +224,8 @@ pub fn run() { delete_all_drafts, scan_project, open_binary_file, + get_global_claude_md, + save_global_claude_md, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/types.rs b/src-tauri/src/types.rs index 097b67f..44cdf77 100644 --- a/src-tauri/src/types.rs +++ b/src-tauri/src/types.rs @@ -95,6 +95,9 @@ pub enum ClaudeMessage { cwd: Option, #[serde(default)] tools: Option>, + /// Output style hint from Claude Code (v2.1.81+). Informational only. + #[serde(default)] + output_style: Option, }, #[serde(rename = "assistant")] Assistant { @@ -119,6 +122,15 @@ pub enum ClaudeMessage { permission_denials: Option>, #[serde(default)] usage: Option, + /// Fast mode state from Claude Code v2.1.81+. Values: "default" | "enabled" | "disabled". + #[serde(default)] + fast_mode_state: Option, + /// Per-model usage breakdown from Claude Code v2.1.81+. + #[serde(default)] + model_usage: Option, + /// Authoritative total cost in USD reported by Claude Code v2.1.81+. + #[serde(default)] + total_cost_usd: Option, }, #[serde(rename = "rate_limit_event")] RateLimitEvent { @@ -910,4 +922,67 @@ mod tests { assert!(!serialized.contains("reason")); assert!(!serialized.contains("conversation_id")); } + + #[test] + fn test_system_init_with_output_style() { + let json = r#"{"type":"system","subtype":"init","session_id":"sess-1","output_style":"auto"}"#; + let msg: ClaudeMessage = serde_json::from_str(json).unwrap(); + if let ClaudeMessage::System { output_style, .. } = msg { + assert_eq!(output_style, Some("auto".to_string())); + } else { + panic!("Expected System variant"); + } + } + + #[test] + fn test_system_init_without_output_style() { + let json = r#"{"type":"system","subtype":"init","session_id":"sess-1"}"#; + let msg: ClaudeMessage = serde_json::from_str(json).unwrap(); + if let ClaudeMessage::System { output_style, .. } = msg { + assert!(output_style.is_none()); + } else { + panic!("Expected System variant"); + } + } + + #[test] + fn test_result_message_with_fast_mode_state() { + let json = r#"{"type":"result","subtype":"success","fast_mode_state":"enabled"}"#; + let msg: ClaudeMessage = serde_json::from_str(json).unwrap(); + if let ClaudeMessage::Result { fast_mode_state, .. } = msg { + assert_eq!(fast_mode_state, Some("enabled".to_string())); + } else { + panic!("Expected Result variant"); + } + } + + #[test] + fn test_result_message_with_total_cost_usd() { + let json = r#"{"type":"result","subtype":"success","total_cost_usd":0.05}"#; + let msg: ClaudeMessage = serde_json::from_str(json).unwrap(); + if let ClaudeMessage::Result { total_cost_usd, .. } = msg { + assert!((total_cost_usd.unwrap() - 0.05).abs() < f64::EPSILON); + } else { + panic!("Expected Result variant"); + } + } + + #[test] + fn test_result_message_without_new_fields() { + let json = r#"{"type":"result","subtype":"success"}"#; + let msg: ClaudeMessage = serde_json::from_str(json).unwrap(); + if let ClaudeMessage::Result { + fast_mode_state, + model_usage, + total_cost_usd, + .. + } = msg + { + assert!(fast_mode_state.is_none()); + assert!(model_usage.is_none()); + assert!(total_cost_usd.is_none()); + } else { + panic!("Expected Result variant"); + } + } } diff --git a/src-tauri/src/wsl_bridge.rs b/src-tauri/src/wsl_bridge.rs index 6a8f9a6..4197fdf 100644 --- a/src-tauri/src/wsl_bridge.rs +++ b/src-tauri/src/wsl_bridge.rs @@ -303,6 +303,11 @@ impl WslBridge { cmd.arg("--worktree"); } + // Add bare flag if requested (v2.1.81+) + if options.bare_mode { + cmd.arg("--bare"); + } + // Pass combined settings via --settings flag if any settings are specified { let has_memory_dir = options @@ -315,8 +320,13 @@ impl WslBridge { .as_ref() .map(|m| !m.is_empty()) .unwrap_or(false); + let suppress_clear_context = !options.show_clear_context_on_plan_accept; - if has_memory_dir || has_overrides || options.disable_skill_shell_execution { + if has_memory_dir + || has_overrides + || options.disable_skill_shell_execution + || suppress_clear_context + { let mut settings = serde_json::Map::new(); if let Some(ref dir) = options.auto_memory_directory { if !dir.is_empty() { @@ -339,6 +349,12 @@ impl WslBridge { serde_json::Value::Bool(true), ); } + if suppress_clear_context { + settings.insert( + "showClearContextOnPlanAccept".to_string(), + serde_json::Value::Bool(false), + ); + } if let Ok(settings_json) = serde_json::to_string(&settings) { cmd.args(["--settings", &settings_json]); } @@ -379,6 +395,13 @@ impl WslBridge { cmd.env("ENABLE_CLAUDEAI_MCP_SERVERS", "false"); } + // Set custom model option if specified (v2.1.81+) + if let Some(ref custom_opt) = options.custom_model_option { + if !custom_opt.is_empty() { + cmd.env("ANTHROPIC_CUSTOM_MODEL_OPTION", custom_opt); + } + } + cmd } else { // Running on Windows - use wsl with bash login shell to ensure PATH is loaded @@ -446,6 +469,14 @@ impl WslBridge { claude_cmd.push_str("ENABLE_CLAUDEAI_MCP_SERVERS=false "); } + // Set custom model option if specified (v2.1.81+) + if let Some(ref custom_opt) = options.custom_model_option { + if !custom_opt.is_empty() { + let escaped = custom_opt.replace('\'', "'\\''"); + claude_cmd.push_str(&format!("ANTHROPIC_CUSTOM_MODEL_OPTION='{}' ", escaped)); + } + } + claude_cmd.push_str( "claude --output-format stream-json --input-format stream-json --verbose", ); @@ -496,6 +527,11 @@ impl WslBridge { claude_cmd.push_str(" --worktree"); } + // Add bare flag if requested (v2.1.81+) + if options.bare_mode { + claude_cmd.push_str(" --bare"); + } + // Pass combined settings via --settings flag if any settings are specified { let has_memory_dir = options @@ -508,8 +544,13 @@ impl WslBridge { .as_ref() .map(|m| !m.is_empty()) .unwrap_or(false); + let suppress_clear_context = !options.show_clear_context_on_plan_accept; - if has_memory_dir || has_overrides || options.disable_skill_shell_execution { + if has_memory_dir + || has_overrides + || options.disable_skill_shell_execution + || suppress_clear_context + { let mut settings = serde_json::Map::new(); if let Some(ref dir) = options.auto_memory_directory { if !dir.is_empty() { @@ -532,6 +573,12 @@ impl WslBridge { serde_json::Value::Bool(true), ); } + if suppress_clear_context { + settings.insert( + "showClearContextOnPlanAccept".to_string(), + serde_json::Value::Bool(false), + ); + } if let Ok(settings_json) = serde_json::to_string(&settings) { let escaped = settings_json.replace('\'', "'\\''"); claude_cmd.push_str(&format!(" --settings '{}'", escaped)); @@ -2122,6 +2169,9 @@ fn process_json_line( usage, duration_ms, num_turns, + fast_mode_state, + model_usage, + total_cost_usd, } => { tracing::info!( "Received Result message: subtype={}, has_denials={}, denial_count={:?}", @@ -2206,6 +2256,25 @@ fn process_json_line( }); } + // Log fast mode state if present (v2.1.81+) + if let Some(ref state) = fast_mode_state { + tracing::debug!("Fast mode state: {}", state); + } + + // Log per-model usage if available (v2.1.81+) + if let Some(ref model_usage_val) = model_usage { + if let Some(map) = model_usage_val.as_object() { + for (model_name, _usage_val) in map { + tracing::debug!("Per-model usage logged for: {}", model_name); + } + } + } + + // Log authoritative cost from Claude Code if available (v2.1.81+) + if let Some(auth_cost) = total_cost_usd { + tracing::debug!("Authoritative total cost from Claude Code: ${:.6}", auth_cost); + } + // Clear tracking fields since request completed successfully { let mut stats_guard = stats.write(); diff --git a/src/lib/commands/slashCommands.ts b/src/lib/commands/slashCommands.ts index d19e871..4bef72e 100644 --- a/src/lib/commands/slashCommands.ts +++ b/src/lib/commands/slashCommands.ts @@ -67,11 +67,16 @@ async function changeDirectory(path: string): Promise { use_worktree: config.use_worktree ?? false, disable_1m_context: config.disable_1m_context ?? false, max_output_tokens: config.max_output_tokens ?? null, + disable_cron: config.disable_cron ?? false, + disable_skill_shell_execution: config.disable_skill_shell_execution ?? false, include_git_instructions: config.include_git_instructions ?? true, enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true, auto_memory_directory: config.auto_memory_directory || null, model_overrides: config.model_overrides || null, session_name: null, + bare_mode: config.bare_mode ?? false, + show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true, + custom_model_option: config.custom_model_option || null, }, }); @@ -149,11 +154,16 @@ async function startNewConversation(): Promise { use_worktree: config.use_worktree ?? false, disable_1m_context: config.disable_1m_context ?? false, max_output_tokens: config.max_output_tokens ?? null, + disable_cron: config.disable_cron ?? false, + disable_skill_shell_execution: config.disable_skill_shell_execution ?? false, include_git_instructions: config.include_git_instructions ?? true, enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true, auto_memory_directory: config.auto_memory_directory || null, model_overrides: config.model_overrides || null, session_name: null, + bare_mode: config.bare_mode ?? false, + show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true, + custom_model_option: config.custom_model_option || null, }, }); diff --git a/src/lib/components/ConfigSidebar.svelte b/src/lib/components/ConfigSidebar.svelte index b9ccb1b..9b2877e 100644 --- a/src/lib/components/ConfigSidebar.svelte +++ b/src/lib/components/ConfigSidebar.svelte @@ -64,6 +64,9 @@ auto_memory_directory: null, model_overrides: null, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: null, max_output_tokens: null, trusted_workspaces: [], background_image_path: null, @@ -86,6 +89,9 @@ let customUiFontStatus: string | null = $state(null); let modelOverridesJson = $state(""); let modelOverridesError: string | null = $state(null); + let globalClaudeMd = $state(""); + let globalClaudeMdSaving = $state(false); + let globalClaudeMdSaveStatus: string | null = $state(null); interface AuthStatus { is_logged_in: boolean; @@ -123,6 +129,9 @@ if (open && authStatus === null) { void refreshAuthStatus(); } + if (open) { + void loadGlobalClaudeMd(); + } }); configStore.saveError.subscribe((error) => { @@ -198,6 +207,30 @@ } } + async function loadGlobalClaudeMd() { + try { + globalClaudeMd = await invoke("get_global_claude_md"); + } catch (error) { + console.error("Failed to load global CLAUDE.md:", error); + } + } + + async function saveGlobalClaudeMd() { + globalClaudeMdSaving = true; + globalClaudeMdSaveStatus = null; + try { + await invoke("save_global_claude_md", { content: globalClaudeMd }); + globalClaudeMdSaveStatus = "Saved!"; + setTimeout(() => { + globalClaudeMdSaveStatus = null; + }, 2000); + } catch (error) { + globalClaudeMdSaveStatus = `Error: ${error}`; + } finally { + globalClaudeMdSaving = false; + } + } + async function handleSave() { isSaving = true; saveError = null; @@ -679,6 +712,59 @@ defaults.

+ + +
+ +

+ Passes --bare to suppress UI chrome — useful for scripted + headless -p calls (requires Claude Code v2.1.81+) +

+
+ + +
+ +

+ When enabled, prompts to clear context when accepting a plan. Passes + showClearContextOnPlanAccept: false in + --settings when disabled (requires Claude Code v2.1.81+) +

+
+ + +
+ + +

+ Sets ANTHROPIC_CUSTOM_MODEL_OPTION environment variable for custom + model providers (requires Claude Code v2.1.81+) +

+
@@ -719,6 +805,47 @@ {/if} + +
+

+ Global Instructions +

+
+ + +
+
+ + {#if globalClaudeMdSaveStatus} + + {globalClaudeMdSaveStatus} + + {/if} +
+

+ Persistent instructions applied to all Claude Code sessions. Changes take effect on the next + session start. +

+
+

diff --git a/src/lib/components/ElicitationModal.svelte b/src/lib/components/ElicitationModal.svelte index 0b3a4ca..fa23141 100644 --- a/src/lib/components/ElicitationModal.svelte +++ b/src/lib/components/ElicitationModal.svelte @@ -68,11 +68,16 @@ allowed_tools: grantedToolsList, use_worktree: config.use_worktree ?? false, disable_1m_context: config.disable_1m_context ?? false, + disable_cron: config.disable_cron ?? false, + disable_skill_shell_execution: config.disable_skill_shell_execution ?? false, include_git_instructions: config.include_git_instructions ?? true, enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true, auto_memory_directory: config.auto_memory_directory || null, model_overrides: config.model_overrides || null, session_name: null, + bare_mode: config.bare_mode ?? false, + show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true, + custom_model_option: config.custom_model_option || null, }, }); diff --git a/src/lib/components/InputBar.svelte b/src/lib/components/InputBar.svelte index 718ebc2..a36ce84 100644 --- a/src/lib/components/InputBar.svelte +++ b/src/lib/components/InputBar.svelte @@ -402,11 +402,16 @@ User: ${formattedMessage}`; allowed_tools: allAllowedTools, use_worktree: config.use_worktree ?? false, disable_1m_context: config.disable_1m_context ?? false, + disable_cron: config.disable_cron ?? false, + disable_skill_shell_execution: config.disable_skill_shell_execution ?? false, include_git_instructions: config.include_git_instructions ?? true, enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true, auto_memory_directory: config.auto_memory_directory || null, model_overrides: config.model_overrides || null, session_name: null, + bare_mode: config.bare_mode ?? false, + show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true, + custom_model_option: config.custom_model_option || null, }, }); diff --git a/src/lib/components/PermissionModal.svelte b/src/lib/components/PermissionModal.svelte index 9f8f7e1..32b58f4 100644 --- a/src/lib/components/PermissionModal.svelte +++ b/src/lib/components/PermissionModal.svelte @@ -89,11 +89,16 @@ allowed_tools: [...new Set([...newGrantedTools, ...config.auto_granted_tools])], use_worktree: config.use_worktree ?? false, disable_1m_context: config.disable_1m_context ?? false, + disable_cron: config.disable_cron ?? false, + disable_skill_shell_execution: config.disable_skill_shell_execution ?? false, include_git_instructions: config.include_git_instructions ?? true, enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true, auto_memory_directory: config.auto_memory_directory || null, model_overrides: config.model_overrides || null, session_name: null, + bare_mode: config.bare_mode ?? false, + show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true, + custom_model_option: config.custom_model_option || null, }, }); diff --git a/src/lib/components/StatusBar.svelte b/src/lib/components/StatusBar.svelte index 46fc3c9..8177e72 100644 --- a/src/lib/components/StatusBar.svelte +++ b/src/lib/components/StatusBar.svelte @@ -94,6 +94,9 @@ auto_memory_directory: null, model_overrides: null, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: null, }); let streamerModeActive = $state(false); @@ -175,11 +178,17 @@ use_worktree: currentConfig.use_worktree ?? false, disable_1m_context: currentConfig.disable_1m_context ?? false, max_output_tokens: currentConfig.max_output_tokens ?? null, + disable_cron: currentConfig.disable_cron ?? false, + disable_skill_shell_execution: currentConfig.disable_skill_shell_execution ?? false, include_git_instructions: currentConfig.include_git_instructions ?? true, enable_claudeai_mcp_servers: currentConfig.enable_claudeai_mcp_servers ?? true, auto_memory_directory: currentConfig.auto_memory_directory || null, model_overrides: currentConfig.model_overrides || null, session_name: activeConversationForName?.name || null, + bare_mode: currentConfig.bare_mode ?? false, + show_clear_context_on_plan_accept: + currentConfig.show_clear_context_on_plan_accept ?? true, + custom_model_option: currentConfig.custom_model_option || null, }, }); @@ -337,11 +346,17 @@ use_worktree: currentConfig.use_worktree ?? false, disable_1m_context: currentConfig.disable_1m_context ?? false, max_output_tokens: currentConfig.max_output_tokens ?? null, + disable_cron: currentConfig.disable_cron ?? false, + disable_skill_shell_execution: currentConfig.disable_skill_shell_execution ?? false, include_git_instructions: currentConfig.include_git_instructions ?? true, enable_claudeai_mcp_servers: currentConfig.enable_claudeai_mcp_servers ?? true, auto_memory_directory: currentConfig.auto_memory_directory || null, model_overrides: currentConfig.model_overrides || null, session_name: null, + bare_mode: currentConfig.bare_mode ?? false, + show_clear_context_on_plan_accept: + currentConfig.show_clear_context_on_plan_accept ?? true, + custom_model_option: currentConfig.custom_model_option || null, }, }); diff --git a/src/lib/components/TaskLoopPanel.svelte b/src/lib/components/TaskLoopPanel.svelte index 82daaba..fb046b5 100644 --- a/src/lib/components/TaskLoopPanel.svelte +++ b/src/lib/components/TaskLoopPanel.svelte @@ -218,11 +218,16 @@ use_worktree: cfg.use_worktree ?? false, disable_1m_context: cfg.disable_1m_context ?? false, max_output_tokens: cfg.max_output_tokens ?? null, + disable_cron: cfg.disable_cron ?? false, + disable_skill_shell_execution: cfg.disable_skill_shell_execution ?? false, include_git_instructions: cfg.include_git_instructions ?? true, enable_claudeai_mcp_servers: cfg.enable_claudeai_mcp_servers ?? true, auto_memory_directory: cfg.auto_memory_directory || null, model_overrides: cfg.model_overrides || null, session_name: null, + bare_mode: cfg.bare_mode ?? false, + show_clear_context_on_plan_accept: cfg.show_clear_context_on_plan_accept ?? true, + custom_model_option: cfg.custom_model_option || null, }, }); } catch (error) { diff --git a/src/lib/components/UserQuestionModal.svelte b/src/lib/components/UserQuestionModal.svelte index e887b7f..4180d3f 100644 --- a/src/lib/components/UserQuestionModal.svelte +++ b/src/lib/components/UserQuestionModal.svelte @@ -108,11 +108,16 @@ allowed_tools: grantedToolsList, use_worktree: config.use_worktree ?? false, disable_1m_context: config.disable_1m_context ?? false, + disable_cron: config.disable_cron ?? false, + disable_skill_shell_execution: config.disable_skill_shell_execution ?? false, include_git_instructions: config.include_git_instructions ?? true, enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true, auto_memory_directory: config.auto_memory_directory || null, model_overrides: config.model_overrides || null, session_name: null, + bare_mode: config.bare_mode ?? false, + show_clear_context_on_plan_accept: config.show_clear_context_on_plan_accept ?? true, + custom_model_option: config.custom_model_option || null, }, }); diff --git a/src/lib/stores/config.test.ts b/src/lib/stores/config.test.ts index bd2dc8d..21afee2 100644 --- a/src/lib/stores/config.test.ts +++ b/src/lib/stores/config.test.ts @@ -226,6 +226,9 @@ describe("config store", () => { auto_memory_directory: null, model_overrides: null, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: null, }; expect(config.model).toBe("claude-sonnet-4"); @@ -291,6 +294,9 @@ describe("config store", () => { auto_memory_directory: null, model_overrides: null, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: null, }; expect(config.model).toBeNull(); @@ -911,6 +917,9 @@ describe("config store", () => { auto_memory_directory: null, model_overrides: null, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: null, }; const mockInvokeImpl = vi.mocked(invoke); diff --git a/src/lib/stores/config.ts b/src/lib/stores/config.ts index a988fae..fb22631 100644 --- a/src/lib/stores/config.ts +++ b/src/lib/stores/config.ts @@ -93,6 +93,12 @@ export interface HikariConfig { model_overrides: Record | null; // Prevents skill scripts from executing shell commands (Claude Code v2.1.91+) disable_skill_shell_execution: boolean; + // Bare mode — suppress UI chrome for scripted headless -p calls (v2.1.81+) + bare_mode: boolean; + // Show clear context dialog when accepting a plan (v2.1.81+) + show_clear_context_on_plan_accept: boolean; + // Custom model option env var (v2.1.81+) + custom_model_option: string | null; } const defaultConfig: HikariConfig = { @@ -152,6 +158,9 @@ const defaultConfig: HikariConfig = { auto_memory_directory: null, model_overrides: null, disable_skill_shell_execution: false, + bare_mode: false, + show_clear_context_on_plan_accept: true, + custom_model_option: null, }; function createConfigStore() {