diff --git a/src/ClaudeDo.Worker/CLAUDE.md b/src/ClaudeDo.Worker/CLAUDE.md index adcbb43..6ced993 100644 --- a/src/ClaudeDo.Worker/CLAUDE.md +++ b/src/ClaudeDo.Worker/CLAUDE.md @@ -24,7 +24,7 @@ ASP.NET Core hosted service that executes tasks via Claude CLI in isolated envir ## Key Components -- **ClaudeProcess** — spawns `claude -p --output-format stream-json --verbose --dangerously-skip-permissions`. Writes prompt to stdin, reads NDJSON from stdout. Supports CancellationToken (kills process tree). +- **ClaudeProcess** — spawns `claude -p --output-format stream-json --verbose --permission-mode auto` (or whatever permission mode the app settings specify). Writes prompt to stdin, reads NDJSON from stdout. Supports CancellationToken (kills process tree). - **ClaudeArgsBuilder** — dynamically constructs CLI args; supports `--model`, `--append-system-prompt`, `--agents`, `--json-schema`, `--resume` - **StreamAnalyzer** — parses rich NDJSON output; extracts session_id, token counts, turn counts, result text, structured output. Replaces MessageParser. - **TaskResetService** — discards a failed task's worktree and resets the task row to Manual; preserves run history. @@ -64,5 +64,5 @@ Per-list config (`list_config` in DB) provides defaults for `model`, `system_pro - The worker runs standalone — start it separately from the UI - Only listens on loopback (127.0.0.1) -- ClaudeProcess uses `--dangerously-skip-permissions` — tasks run with full filesystem access +- ClaudeProcess uses `--permission-mode auto` by default; legacy "bypassPermissions" settings are mapped to `auto` at dispatch time. `acceptEdits`, `plan`, and `default` pass through unchanged. - Worktree branches follow `claudedo/{id}` naming convention diff --git a/src/ClaudeDo.Worker/Runner/ClaudeArgsBuilder.cs b/src/ClaudeDo.Worker/Runner/ClaudeArgsBuilder.cs index 15a649f..e1a2017 100644 --- a/src/ClaudeDo.Worker/Runner/ClaudeArgsBuilder.cs +++ b/src/ClaudeDo.Worker/Runner/ClaudeArgsBuilder.cs @@ -34,11 +34,11 @@ public sealed class ClaudeArgsBuilder "--verbose", }; - var permissionMode = string.IsNullOrWhiteSpace(config.PermissionMode) ? "bypassPermissions" : config.PermissionMode; - if (permissionMode.Equals("bypassPermissions", StringComparison.OrdinalIgnoreCase)) - args.Add("--dangerously-skip-permissions"); - else - args.Add($"--permission-mode {permissionMode}"); + var permissionMode = string.IsNullOrWhiteSpace(config.PermissionMode) + || config.PermissionMode.Equals("bypassPermissions", StringComparison.OrdinalIgnoreCase) + ? "auto" + : config.PermissionMode; + args.Add($"--permission-mode {permissionMode}"); if (config.Model is not null) args.Add($"--model {config.Model}"); diff --git a/tests/ClaudeDo.Worker.Tests/Runner/ClaudeArgsBuilderTests.cs b/tests/ClaudeDo.Worker.Tests/Runner/ClaudeArgsBuilderTests.cs index a0e585d..68f4c8e 100644 --- a/tests/ClaudeDo.Worker.Tests/Runner/ClaudeArgsBuilderTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Runner/ClaudeArgsBuilderTests.cs @@ -13,7 +13,8 @@ public sealed class ClaudeArgsBuilderTests Assert.Contains("-p", args); Assert.Contains("--output-format stream-json", args); Assert.Contains("--verbose", args); - Assert.Contains("--dangerously-skip-permissions", args); + Assert.Contains("--permission-mode auto", args); + Assert.DoesNotContain("--dangerously-skip-permissions", args); Assert.Contains("--json-schema", args); Assert.DoesNotContain("--model", args); Assert.DoesNotContain("--append-system-prompt", args); @@ -110,11 +111,11 @@ public sealed class ClaudeArgsBuilderTests } [Fact] - public void PermissionMode_bypass_Keeps_DangerousFlag() + public void PermissionMode_bypass_Maps_To_Auto() { var args = _builder.Build(new ClaudeRunConfig(null, null, null, null, PermissionMode: "bypassPermissions")); - Assert.Contains("--dangerously-skip-permissions", args); - Assert.DoesNotContain("--permission-mode", args); + Assert.Contains("--permission-mode auto", args); + Assert.DoesNotContain("--dangerously-skip-permissions", args); } [Fact] @@ -126,10 +127,11 @@ public sealed class ClaudeArgsBuilderTests } [Fact] - public void PermissionMode_Null_Defaults_To_BypassPermissions() + public void PermissionMode_Null_Defaults_To_Auto() { var args = _builder.Build(new ClaudeRunConfig(null, null, null, null)); - Assert.Contains("--dangerously-skip-permissions", args); + Assert.Contains("--permission-mode auto", args); + Assert.DoesNotContain("--dangerously-skip-permissions", args); } }