feat: expose disableSkillShellExecution setting in config UI (closes #259)

This commit is contained in:
2026-04-13 10:19:50 -07:00
committed by Naomi Carrigan
parent 54b3a524c4
commit edea33310b
6 changed files with 49 additions and 2 deletions
+11
View File
@@ -54,6 +54,9 @@ pub struct ClaudeStartOptions {
#[serde(default)] #[serde(default)]
pub session_name: Option<String>, pub session_name: Option<String>,
#[serde(default)]
pub disable_skill_shell_execution: bool,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -203,6 +206,11 @@ pub struct HikariConfig {
#[serde(default)] #[serde(default)]
pub model_overrides: Option<HashMap<String, String>>, pub model_overrides: Option<HashMap<String, String>>,
/// Prevents skill scripts from executing shell commands (Claude Code v2.1.91+).
/// Passes `"disableSkillShellExecution": true` via the `--settings` flag.
#[serde(default)]
pub disable_skill_shell_execution: bool,
} }
impl Default for HikariConfig { impl Default for HikariConfig {
@@ -254,6 +262,7 @@ impl Default for HikariConfig {
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: None, auto_memory_directory: None,
model_overrides: None, model_overrides: None,
disable_skill_shell_execution: false,
} }
} }
} }
@@ -405,6 +414,7 @@ mod tests {
assert!(config.enable_claudeai_mcp_servers); assert!(config.enable_claudeai_mcp_servers);
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);
} }
#[test] #[test]
@@ -459,6 +469,7 @@ mod tests {
"claude-opus-4-6".to_string(), "claude-opus-4-6".to_string(),
"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,
}; };
let json = serde_json::to_string(&config).unwrap(); let json = serde_json::to_string(&config).unwrap();
+14 -2
View File
@@ -316,7 +316,7 @@ impl WslBridge {
.map(|m| !m.is_empty()) .map(|m| !m.is_empty())
.unwrap_or(false); .unwrap_or(false);
if has_memory_dir || has_overrides { if has_memory_dir || has_overrides || options.disable_skill_shell_execution {
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() {
@@ -333,6 +333,12 @@ impl WslBridge {
} }
} }
} }
if options.disable_skill_shell_execution {
settings.insert(
"disableSkillShellExecution".to_string(),
serde_json::Value::Bool(true),
);
}
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]);
} }
@@ -503,7 +509,7 @@ impl WslBridge {
.map(|m| !m.is_empty()) .map(|m| !m.is_empty())
.unwrap_or(false); .unwrap_or(false);
if has_memory_dir || has_overrides { if has_memory_dir || has_overrides || options.disable_skill_shell_execution {
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() {
@@ -520,6 +526,12 @@ impl WslBridge {
} }
} }
} }
if options.disable_skill_shell_execution {
settings.insert(
"disableSkillShellExecution".to_string(),
serde_json::Value::Bool(true),
);
}
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));
+17
View File
@@ -63,6 +63,7 @@
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: null, auto_memory_directory: null,
model_overrides: null, model_overrides: null,
disable_skill_shell_execution: false,
max_output_tokens: null, max_output_tokens: null,
trusted_workspaces: [], trusted_workspaces: [],
background_image_path: null, background_image_path: null,
@@ -585,6 +586,22 @@
</p> </p>
</div> </div>
<!-- Disable Skill Shell Execution -->
<div class="mb-4">
<label class="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
bind:checked={config.disable_skill_shell_execution}
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)]">Disable skill shell execution</span>
</label>
<p class="text-xs text-[var(--text-tertiary)] mt-1 ml-7">
Passes <code class="font-mono">disableSkillShellExecution: true</code> to prevent skill scripts
from executing shell commands (requires Claude Code v2.1.91+)
</p>
</div>
<!-- Include Git Instructions --> <!-- Include Git Instructions -->
<div class="mb-4"> <div class="mb-4">
<label class="flex items-center gap-3 cursor-pointer"> <label class="flex items-center gap-3 cursor-pointer">
+1
View File
@@ -93,6 +93,7 @@
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: null, auto_memory_directory: null,
model_overrides: null, model_overrides: null,
disable_skill_shell_execution: false,
}); });
let streamerModeActive = $state(false); let streamerModeActive = $state(false);
+3
View File
@@ -225,6 +225,7 @@ describe("config store", () => {
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: null, auto_memory_directory: null,
model_overrides: null, model_overrides: null,
disable_skill_shell_execution: false,
}; };
expect(config.model).toBe("claude-sonnet-4"); expect(config.model).toBe("claude-sonnet-4");
@@ -289,6 +290,7 @@ describe("config store", () => {
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: null, auto_memory_directory: null,
model_overrides: null, model_overrides: null,
disable_skill_shell_execution: false,
}; };
expect(config.model).toBeNull(); expect(config.model).toBeNull();
@@ -908,6 +910,7 @@ describe("config store", () => {
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: null, auto_memory_directory: null,
model_overrides: null, model_overrides: null,
disable_skill_shell_execution: false,
}; };
const mockInvokeImpl = vi.mocked(invoke); const mockInvokeImpl = vi.mocked(invoke);
+3
View File
@@ -91,6 +91,8 @@ export interface HikariConfig {
auto_memory_directory: string | null; auto_memory_directory: string | null;
// Model overrides for provider-specific model IDs (AWS Bedrock, Google Vertex, etc.) // Model overrides for provider-specific model IDs (AWS Bedrock, Google Vertex, etc.)
model_overrides: Record<string, string> | null; model_overrides: Record<string, string> | null;
// Prevents skill scripts from executing shell commands (Claude Code v2.1.91+)
disable_skill_shell_execution: boolean;
} }
const defaultConfig: HikariConfig = { const defaultConfig: HikariConfig = {
@@ -149,6 +151,7 @@ const defaultConfig: HikariConfig = {
enable_claudeai_mcp_servers: true, enable_claudeai_mcp_servers: true,
auto_memory_directory: null, auto_memory_directory: null,
model_overrides: null, model_overrides: null,
disable_skill_shell_execution: false,
}; };
function createConfigStore() { function createConfigStore() {