generated from nhcarrigan/template
feat: CLI v2.1.81 features + global CLAUDE.md editor (#263)
## Summary Implements support for Claude Code CLI v2.1.81 features and adds a global CLAUDE.md editor, closing issues #237, #239, #244, #245, #246, #247, #248, and #262. ### Stream-JSON forward-compatibility (#245, #246, #247, #248) - **#248** — `output_style` field added to `System` init message; silently accepted for forward-compat - **#245** — `fast_mode_state` field added to `Result` message; logged at debug level - **#246** — `model_usage` field added to `Result` message; per-model breakdown logged at debug level - **#247** — `total_cost_usd` field added to `Result` message; authoritative cost logged at debug level ### New config options (#237, #239, #244) - **#237** — `bare_mode` config toggle: passes `--bare` to Claude Code, suppressing UI chrome for scripted headless `-p` calls - **#239** — `show_clear_context_on_plan_accept` toggle: passes `showClearContextOnPlanAccept: false` in `--settings` when disabled - **#244** — `custom_model_option` text field: sets `ANTHROPIC_CUSTOM_MODEL_OPTION` env var for custom model providers ### Global CLAUDE.md editor (#262) - New Tauri commands `get_global_claude_md` / `save_global_claude_md` read/write `~/.claude/CLAUDE.md` (creates file + directory if absent) - New "Global Instructions" section in the Config Sidebar with a textarea and Save button ### Bug fix (pre-existing) `disable_cron` and `disable_skill_shell_execution` were saved to `HikariConfig` but never passed to `start_claude` invocations — fixed in all 9 call sites. All 3 new config fields are also wired through all 9 call sites. All changes pass `check-all.sh` (ESLint → Prettier → svelte-check → Vitest → Clippy → cargo test with llvm-cov). ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #263 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #263.
This commit is contained in:
@@ -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<String, String> {
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -3367,4 +3400,22 @@ gitea: gitea-mcp -t stdio (STDIO) - ✓ Connected"#;
|
|||||||
let (_, args) = build_wslpath_command(path);
|
let (_, args) = build_wslpath_command(path);
|
||||||
assert_eq!(args[2], 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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,19 @@ pub struct ClaudeStartOptions {
|
|||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub disable_skill_shell_execution: bool,
|
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<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -211,6 +224,18 @@ pub struct HikariConfig {
|
|||||||
/// Passes `"disableSkillShellExecution": true` via the `--settings` flag.
|
/// Passes `"disableSkillShellExecution": true` via the `--settings` flag.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub disable_skill_shell_execution: bool,
|
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<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HikariConfig {
|
impl Default for HikariConfig {
|
||||||
@@ -263,6 +288,9 @@ impl Default for HikariConfig {
|
|||||||
auto_memory_directory: None,
|
auto_memory_directory: None,
|
||||||
model_overrides: None,
|
model_overrides: None,
|
||||||
disable_skill_shell_execution: false,
|
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
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_show_clear_context() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum BudgetAction {
|
pub enum BudgetAction {
|
||||||
@@ -415,6 +447,9 @@ mod tests {
|
|||||||
assert!(config.auto_memory_directory.is_none());
|
assert!(config.auto_memory_directory.is_none());
|
||||||
assert!(config.model_overrides.is_none());
|
assert!(config.model_overrides.is_none());
|
||||||
assert!(!config.disable_skill_shell_execution);
|
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]
|
#[test]
|
||||||
@@ -470,6 +505,9 @@ mod tests {
|
|||||||
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-6-v1".to_string(),
|
"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-6-v1".to_string(),
|
||||||
)])),
|
)])),
|
||||||
disable_skill_shell_execution: true,
|
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();
|
let json = serde_json::to_string(&config).unwrap();
|
||||||
|
|||||||
@@ -224,6 +224,8 @@ pub fn run() {
|
|||||||
delete_all_drafts,
|
delete_all_drafts,
|
||||||
scan_project,
|
scan_project,
|
||||||
open_binary_file,
|
open_binary_file,
|
||||||
|
get_global_claude_md,
|
||||||
|
save_global_claude_md,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ pub enum ClaudeMessage {
|
|||||||
cwd: Option<String>,
|
cwd: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
tools: Option<Vec<String>>,
|
tools: Option<Vec<String>>,
|
||||||
|
/// Output style hint from Claude Code (v2.1.81+). Informational only.
|
||||||
|
#[serde(default)]
|
||||||
|
output_style: Option<String>,
|
||||||
},
|
},
|
||||||
#[serde(rename = "assistant")]
|
#[serde(rename = "assistant")]
|
||||||
Assistant {
|
Assistant {
|
||||||
@@ -119,6 +122,15 @@ pub enum ClaudeMessage {
|
|||||||
permission_denials: Option<Vec<PermissionDenial>>,
|
permission_denials: Option<Vec<PermissionDenial>>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
usage: Option<UsageInfo>,
|
usage: Option<UsageInfo>,
|
||||||
|
/// Fast mode state from Claude Code v2.1.81+. Values: "default" | "enabled" | "disabled".
|
||||||
|
#[serde(default)]
|
||||||
|
fast_mode_state: Option<String>,
|
||||||
|
/// Per-model usage breakdown from Claude Code v2.1.81+.
|
||||||
|
#[serde(default)]
|
||||||
|
model_usage: Option<serde_json::Value>,
|
||||||
|
/// Authoritative total cost in USD reported by Claude Code v2.1.81+.
|
||||||
|
#[serde(default)]
|
||||||
|
total_cost_usd: Option<f64>,
|
||||||
},
|
},
|
||||||
#[serde(rename = "rate_limit_event")]
|
#[serde(rename = "rate_limit_event")]
|
||||||
RateLimitEvent {
|
RateLimitEvent {
|
||||||
@@ -910,4 +922,67 @@ mod tests {
|
|||||||
assert!(!serialized.contains("reason"));
|
assert!(!serialized.contains("reason"));
|
||||||
assert!(!serialized.contains("conversation_id"));
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -303,6 +303,11 @@ impl WslBridge {
|
|||||||
cmd.arg("--worktree");
|
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
|
// Pass combined settings via --settings flag if any settings are specified
|
||||||
{
|
{
|
||||||
let has_memory_dir = options
|
let has_memory_dir = options
|
||||||
@@ -315,8 +320,13 @@ impl WslBridge {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|m| !m.is_empty())
|
.map(|m| !m.is_empty())
|
||||||
.unwrap_or(false);
|
.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();
|
let mut settings = serde_json::Map::new();
|
||||||
if let Some(ref dir) = options.auto_memory_directory {
|
if let Some(ref dir) = options.auto_memory_directory {
|
||||||
if !dir.is_empty() {
|
if !dir.is_empty() {
|
||||||
@@ -339,6 +349,12 @@ impl WslBridge {
|
|||||||
serde_json::Value::Bool(true),
|
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) {
|
if let Ok(settings_json) = serde_json::to_string(&settings) {
|
||||||
cmd.args(["--settings", &settings_json]);
|
cmd.args(["--settings", &settings_json]);
|
||||||
}
|
}
|
||||||
@@ -379,6 +395,13 @@ impl WslBridge {
|
|||||||
cmd.env("ENABLE_CLAUDEAI_MCP_SERVERS", "false");
|
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
|
cmd
|
||||||
} else {
|
} else {
|
||||||
// Running on Windows - use wsl with bash login shell to ensure PATH is loaded
|
// 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 ");
|
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_cmd.push_str(
|
||||||
"claude --output-format stream-json --input-format stream-json --verbose",
|
"claude --output-format stream-json --input-format stream-json --verbose",
|
||||||
);
|
);
|
||||||
@@ -496,6 +527,11 @@ impl WslBridge {
|
|||||||
claude_cmd.push_str(" --worktree");
|
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
|
// Pass combined settings via --settings flag if any settings are specified
|
||||||
{
|
{
|
||||||
let has_memory_dir = options
|
let has_memory_dir = options
|
||||||
@@ -508,8 +544,13 @@ impl WslBridge {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|m| !m.is_empty())
|
.map(|m| !m.is_empty())
|
||||||
.unwrap_or(false);
|
.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();
|
let mut settings = serde_json::Map::new();
|
||||||
if let Some(ref dir) = options.auto_memory_directory {
|
if let Some(ref dir) = options.auto_memory_directory {
|
||||||
if !dir.is_empty() {
|
if !dir.is_empty() {
|
||||||
@@ -532,6 +573,12 @@ impl WslBridge {
|
|||||||
serde_json::Value::Bool(true),
|
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) {
|
if let Ok(settings_json) = serde_json::to_string(&settings) {
|
||||||
let escaped = settings_json.replace('\'', "'\\''");
|
let escaped = settings_json.replace('\'', "'\\''");
|
||||||
claude_cmd.push_str(&format!(" --settings '{}'", escaped));
|
claude_cmd.push_str(&format!(" --settings '{}'", escaped));
|
||||||
@@ -2122,6 +2169,9 @@ fn process_json_line(
|
|||||||
usage,
|
usage,
|
||||||
duration_ms,
|
duration_ms,
|
||||||
num_turns,
|
num_turns,
|
||||||
|
fast_mode_state,
|
||||||
|
model_usage,
|
||||||
|
total_cost_usd,
|
||||||
} => {
|
} => {
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"Received Result message: subtype={}, has_denials={}, denial_count={:?}",
|
"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
|
// Clear tracking fields since request completed successfully
|
||||||
{
|
{
|
||||||
let mut stats_guard = stats.write();
|
let mut stats_guard = stats.write();
|
||||||
|
|||||||
@@ -67,11 +67,16 @@ async function changeDirectory(path: string): Promise<void> {
|
|||||||
use_worktree: config.use_worktree ?? false,
|
use_worktree: config.use_worktree ?? false,
|
||||||
disable_1m_context: config.disable_1m_context ?? false,
|
disable_1m_context: config.disable_1m_context ?? false,
|
||||||
max_output_tokens: config.max_output_tokens ?? null,
|
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,
|
include_git_instructions: config.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: config.auto_memory_directory || null,
|
auto_memory_directory: config.auto_memory_directory || null,
|
||||||
model_overrides: config.model_overrides || null,
|
model_overrides: config.model_overrides || null,
|
||||||
session_name: 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<void> {
|
|||||||
use_worktree: config.use_worktree ?? false,
|
use_worktree: config.use_worktree ?? false,
|
||||||
disable_1m_context: config.disable_1m_context ?? false,
|
disable_1m_context: config.disable_1m_context ?? false,
|
||||||
max_output_tokens: config.max_output_tokens ?? null,
|
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,
|
include_git_instructions: config.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: config.auto_memory_directory || null,
|
auto_memory_directory: config.auto_memory_directory || null,
|
||||||
model_overrides: config.model_overrides || null,
|
model_overrides: config.model_overrides || null,
|
||||||
session_name: 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,9 @@
|
|||||||
auto_memory_directory: null,
|
auto_memory_directory: null,
|
||||||
model_overrides: null,
|
model_overrides: null,
|
||||||
disable_skill_shell_execution: false,
|
disable_skill_shell_execution: false,
|
||||||
|
bare_mode: false,
|
||||||
|
show_clear_context_on_plan_accept: true,
|
||||||
|
custom_model_option: null,
|
||||||
max_output_tokens: null,
|
max_output_tokens: null,
|
||||||
trusted_workspaces: [],
|
trusted_workspaces: [],
|
||||||
background_image_path: null,
|
background_image_path: null,
|
||||||
@@ -86,6 +89,9 @@
|
|||||||
let customUiFontStatus: string | null = $state(null);
|
let customUiFontStatus: string | null = $state(null);
|
||||||
let modelOverridesJson = $state("");
|
let modelOverridesJson = $state("");
|
||||||
let modelOverridesError: string | null = $state(null);
|
let modelOverridesError: string | null = $state(null);
|
||||||
|
let globalClaudeMd = $state("");
|
||||||
|
let globalClaudeMdSaving = $state(false);
|
||||||
|
let globalClaudeMdSaveStatus: string | null = $state(null);
|
||||||
|
|
||||||
interface AuthStatus {
|
interface AuthStatus {
|
||||||
is_logged_in: boolean;
|
is_logged_in: boolean;
|
||||||
@@ -123,6 +129,9 @@
|
|||||||
if (open && authStatus === null) {
|
if (open && authStatus === null) {
|
||||||
void refreshAuthStatus();
|
void refreshAuthStatus();
|
||||||
}
|
}
|
||||||
|
if (open) {
|
||||||
|
void loadGlobalClaudeMd();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
configStore.saveError.subscribe((error) => {
|
configStore.saveError.subscribe((error) => {
|
||||||
@@ -198,6 +207,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadGlobalClaudeMd() {
|
||||||
|
try {
|
||||||
|
globalClaudeMd = await invoke<string>("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() {
|
async function handleSave() {
|
||||||
isSaving = true;
|
isSaving = true;
|
||||||
saveError = null;
|
saveError = null;
|
||||||
@@ -679,6 +712,59 @@
|
|||||||
defaults.
|
defaults.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Bare Mode -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={config.bare_mode}
|
||||||
|
class="w-4 h-4 rounded border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--accent-primary)] focus:ring-[var(--accent-primary)]"
|
||||||
|
/>
|
||||||
|
<span class="text-sm text-[var(--text-primary)]">Bare mode</span>
|
||||||
|
</label>
|
||||||
|
<p class="text-xs text-[var(--text-tertiary)] mt-1 ml-7">
|
||||||
|
Passes <code class="font-mono">--bare</code> to suppress UI chrome — useful for scripted
|
||||||
|
headless <code class="font-mono">-p</code> calls (requires Claude Code v2.1.81+)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Show Clear Context on Plan Accept -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={config.show_clear_context_on_plan_accept}
|
||||||
|
class="w-4 h-4 rounded border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--accent-primary)] focus:ring-[var(--accent-primary)]"
|
||||||
|
/>
|
||||||
|
<span class="text-sm text-[var(--text-primary)]"
|
||||||
|
>Show clear context prompt on plan accept</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<p class="text-xs text-[var(--text-tertiary)] mt-1 ml-7">
|
||||||
|
When enabled, prompts to clear context when accepting a plan. Passes
|
||||||
|
<code class="font-mono">showClearContextOnPlanAccept: false</code> in
|
||||||
|
<code class="font-mono">--settings</code> when disabled (requires Claude Code v2.1.81+)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Custom Model Option -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="custom-model-option" class="block text-sm text-[var(--text-primary)] mb-1">
|
||||||
|
Custom model option <span class="text-[var(--text-tertiary)]">(optional)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="custom-model-option"
|
||||||
|
type="text"
|
||||||
|
placeholder="Leave blank to use default"
|
||||||
|
bind:value={config.custom_model_option}
|
||||||
|
class="w-full px-3 py-2 text-sm bg-[var(--bg-primary)] border border-[var(--border-color)] rounded text-[var(--text-primary)] placeholder-[var(--text-tertiary)] focus:outline-none focus:border-[var(--accent-primary)]"
|
||||||
|
/>
|
||||||
|
<p class="text-xs text-[var(--text-tertiary)] mt-1">
|
||||||
|
Sets <code class="font-mono">ANTHROPIC_CUSTOM_MODEL_OPTION</code> environment variable for custom
|
||||||
|
model providers (requires Claude Code v2.1.81+)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Greeting Section -->
|
<!-- Greeting Section -->
|
||||||
@@ -719,6 +805,47 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- Global Instructions Section -->
|
||||||
|
<section class="mb-6">
|
||||||
|
<h3 class="text-sm font-medium text-[var(--accent-primary)] uppercase tracking-wider mb-3">
|
||||||
|
Global Instructions
|
||||||
|
</h3>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label for="global-claude-md" class="block text-sm text-[var(--text-secondary)] mb-1">
|
||||||
|
~/.claude/CLAUDE.md
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="global-claude-md"
|
||||||
|
bind:value={globalClaudeMd}
|
||||||
|
rows="12"
|
||||||
|
placeholder="Add persistent instructions for all Claude Code sessions..."
|
||||||
|
class="w-full px-3 py-2 bg-[var(--bg-primary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] font-mono text-sm focus:outline-none focus:border-[var(--accent-primary)] resize-y"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onclick={saveGlobalClaudeMd}
|
||||||
|
disabled={globalClaudeMdSaving}
|
||||||
|
class="px-3 py-1.5 text-sm bg-[var(--accent-primary)] text-white rounded hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{globalClaudeMdSaving ? "Saving..." : "Save"}
|
||||||
|
</button>
|
||||||
|
{#if globalClaudeMdSaveStatus}
|
||||||
|
<span
|
||||||
|
class="text-xs {globalClaudeMdSaveStatus.startsWith('Error')
|
||||||
|
? 'text-red-500'
|
||||||
|
: 'text-green-500'}"
|
||||||
|
>
|
||||||
|
{globalClaudeMdSaveStatus}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-[var(--text-tertiary)] mt-2">
|
||||||
|
Persistent instructions applied to all Claude Code sessions. Changes take effect on the next
|
||||||
|
session start.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- MCP Servers Section -->
|
<!-- MCP Servers Section -->
|
||||||
<section class="mb-6">
|
<section class="mb-6">
|
||||||
<h3 class="text-sm font-medium text-[var(--accent-primary)] uppercase tracking-wider mb-3">
|
<h3 class="text-sm font-medium text-[var(--accent-primary)] uppercase tracking-wider mb-3">
|
||||||
|
|||||||
@@ -68,11 +68,16 @@
|
|||||||
allowed_tools: grantedToolsList,
|
allowed_tools: grantedToolsList,
|
||||||
use_worktree: config.use_worktree ?? false,
|
use_worktree: config.use_worktree ?? false,
|
||||||
disable_1m_context: config.disable_1m_context ?? 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,
|
include_git_instructions: config.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: config.auto_memory_directory || null,
|
auto_memory_directory: config.auto_memory_directory || null,
|
||||||
model_overrides: config.model_overrides || null,
|
model_overrides: config.model_overrides || null,
|
||||||
session_name: 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -402,11 +402,16 @@ User: ${formattedMessage}`;
|
|||||||
allowed_tools: allAllowedTools,
|
allowed_tools: allAllowedTools,
|
||||||
use_worktree: config.use_worktree ?? false,
|
use_worktree: config.use_worktree ?? false,
|
||||||
disable_1m_context: config.disable_1m_context ?? 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,
|
include_git_instructions: config.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: config.auto_memory_directory || null,
|
auto_memory_directory: config.auto_memory_directory || null,
|
||||||
model_overrides: config.model_overrides || null,
|
model_overrides: config.model_overrides || null,
|
||||||
session_name: 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -89,11 +89,16 @@
|
|||||||
allowed_tools: [...new Set([...newGrantedTools, ...config.auto_granted_tools])],
|
allowed_tools: [...new Set([...newGrantedTools, ...config.auto_granted_tools])],
|
||||||
use_worktree: config.use_worktree ?? false,
|
use_worktree: config.use_worktree ?? false,
|
||||||
disable_1m_context: config.disable_1m_context ?? 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,
|
include_git_instructions: config.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: config.auto_memory_directory || null,
|
auto_memory_directory: config.auto_memory_directory || null,
|
||||||
model_overrides: config.model_overrides || null,
|
model_overrides: config.model_overrides || null,
|
||||||
session_name: 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,9 @@
|
|||||||
auto_memory_directory: null,
|
auto_memory_directory: null,
|
||||||
model_overrides: null,
|
model_overrides: null,
|
||||||
disable_skill_shell_execution: false,
|
disable_skill_shell_execution: false,
|
||||||
|
bare_mode: false,
|
||||||
|
show_clear_context_on_plan_accept: true,
|
||||||
|
custom_model_option: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
let streamerModeActive = $state(false);
|
let streamerModeActive = $state(false);
|
||||||
@@ -175,11 +178,17 @@
|
|||||||
use_worktree: currentConfig.use_worktree ?? false,
|
use_worktree: currentConfig.use_worktree ?? false,
|
||||||
disable_1m_context: currentConfig.disable_1m_context ?? false,
|
disable_1m_context: currentConfig.disable_1m_context ?? false,
|
||||||
max_output_tokens: currentConfig.max_output_tokens ?? null,
|
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,
|
include_git_instructions: currentConfig.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: currentConfig.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: currentConfig.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: currentConfig.auto_memory_directory || null,
|
auto_memory_directory: currentConfig.auto_memory_directory || null,
|
||||||
model_overrides: currentConfig.model_overrides || null,
|
model_overrides: currentConfig.model_overrides || null,
|
||||||
session_name: activeConversationForName?.name || 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,
|
use_worktree: currentConfig.use_worktree ?? false,
|
||||||
disable_1m_context: currentConfig.disable_1m_context ?? false,
|
disable_1m_context: currentConfig.disable_1m_context ?? false,
|
||||||
max_output_tokens: currentConfig.max_output_tokens ?? null,
|
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,
|
include_git_instructions: currentConfig.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: currentConfig.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: currentConfig.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: currentConfig.auto_memory_directory || null,
|
auto_memory_directory: currentConfig.auto_memory_directory || null,
|
||||||
model_overrides: currentConfig.model_overrides || null,
|
model_overrides: currentConfig.model_overrides || null,
|
||||||
session_name: 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -218,11 +218,16 @@
|
|||||||
use_worktree: cfg.use_worktree ?? false,
|
use_worktree: cfg.use_worktree ?? false,
|
||||||
disable_1m_context: cfg.disable_1m_context ?? false,
|
disable_1m_context: cfg.disable_1m_context ?? false,
|
||||||
max_output_tokens: cfg.max_output_tokens ?? null,
|
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,
|
include_git_instructions: cfg.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: cfg.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: cfg.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: cfg.auto_memory_directory || null,
|
auto_memory_directory: cfg.auto_memory_directory || null,
|
||||||
model_overrides: cfg.model_overrides || null,
|
model_overrides: cfg.model_overrides || null,
|
||||||
session_name: 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) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -108,11 +108,16 @@
|
|||||||
allowed_tools: grantedToolsList,
|
allowed_tools: grantedToolsList,
|
||||||
use_worktree: config.use_worktree ?? false,
|
use_worktree: config.use_worktree ?? false,
|
||||||
disable_1m_context: config.disable_1m_context ?? 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,
|
include_git_instructions: config.include_git_instructions ?? true,
|
||||||
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
enable_claudeai_mcp_servers: config.enable_claudeai_mcp_servers ?? true,
|
||||||
auto_memory_directory: config.auto_memory_directory || null,
|
auto_memory_directory: config.auto_memory_directory || null,
|
||||||
model_overrides: config.model_overrides || null,
|
model_overrides: config.model_overrides || null,
|
||||||
session_name: 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,9 @@ describe("config store", () => {
|
|||||||
auto_memory_directory: null,
|
auto_memory_directory: null,
|
||||||
model_overrides: null,
|
model_overrides: null,
|
||||||
disable_skill_shell_execution: false,
|
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");
|
expect(config.model).toBe("claude-sonnet-4");
|
||||||
@@ -291,6 +294,9 @@ describe("config store", () => {
|
|||||||
auto_memory_directory: null,
|
auto_memory_directory: null,
|
||||||
model_overrides: null,
|
model_overrides: null,
|
||||||
disable_skill_shell_execution: false,
|
disable_skill_shell_execution: false,
|
||||||
|
bare_mode: false,
|
||||||
|
show_clear_context_on_plan_accept: true,
|
||||||
|
custom_model_option: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(config.model).toBeNull();
|
expect(config.model).toBeNull();
|
||||||
@@ -911,6 +917,9 @@ describe("config store", () => {
|
|||||||
auto_memory_directory: null,
|
auto_memory_directory: null,
|
||||||
model_overrides: null,
|
model_overrides: null,
|
||||||
disable_skill_shell_execution: false,
|
disable_skill_shell_execution: false,
|
||||||
|
bare_mode: false,
|
||||||
|
show_clear_context_on_plan_accept: true,
|
||||||
|
custom_model_option: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockInvokeImpl = vi.mocked(invoke);
|
const mockInvokeImpl = vi.mocked(invoke);
|
||||||
|
|||||||
@@ -93,6 +93,12 @@ export interface HikariConfig {
|
|||||||
model_overrides: Record<string, string> | null;
|
model_overrides: Record<string, string> | null;
|
||||||
// Prevents skill scripts from executing shell commands (Claude Code v2.1.91+)
|
// Prevents skill scripts from executing shell commands (Claude Code v2.1.91+)
|
||||||
disable_skill_shell_execution: boolean;
|
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 = {
|
const defaultConfig: HikariConfig = {
|
||||||
@@ -152,6 +158,9 @@ const defaultConfig: HikariConfig = {
|
|||||||
auto_memory_directory: null,
|
auto_memory_directory: null,
|
||||||
model_overrides: null,
|
model_overrides: null,
|
||||||
disable_skill_shell_execution: false,
|
disable_skill_shell_execution: false,
|
||||||
|
bare_mode: false,
|
||||||
|
show_clear_context_on_plan_accept: true,
|
||||||
|
custom_model_option: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
function createConfigStore() {
|
function createConfigStore() {
|
||||||
|
|||||||
Reference in New Issue
Block a user