diff --git a/codeagent-wrapper/backend.go b/codeagent-wrapper/backend.go index 3ae9653..55526a1 100644 --- a/codeagent-wrapper/backend.go +++ b/codeagent-wrapper/backend.go @@ -36,6 +36,10 @@ func (ClaudeBackend) BuildArgs(cfg *Config, targetArg string) []string { // args = append(args, "--dangerously-skip-permissions") // } + // Prevent infinite recursion: disable all setting sources (user, project, local) + // This ensures a clean execution environment without CLAUDE.md or skills that would trigger codeagent + args = append(args, "--setting-sources", "") + if cfg.Mode == "resume" { if cfg.SessionID != "" { // Claude CLI uses -r for resume. diff --git a/codeagent-wrapper/backend_test.go b/codeagent-wrapper/backend_test.go index dbe26f9..2509626 100644 --- a/codeagent-wrapper/backend_test.go +++ b/codeagent-wrapper/backend_test.go @@ -11,7 +11,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) { t.Run("new mode uses workdir without skip by default", func(t *testing.T) { cfg := &Config{Mode: "new", WorkDir: "/repo"} got := backend.BuildArgs(cfg, "todo") - want := []string{"-p", "--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose", "todo"} + want := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "todo"} if !reflect.DeepEqual(got, want) { t.Fatalf("got %v, want %v", got, want) } @@ -20,7 +20,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) { t.Run("new mode opt-in skip permissions with default workdir", func(t *testing.T) { cfg := &Config{Mode: "new", SkipPermissions: true} got := backend.BuildArgs(cfg, "-") - want := []string{"-p", "--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose", "-"} + want := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "-"} if !reflect.DeepEqual(got, want) { t.Fatalf("got %v, want %v", got, want) } @@ -29,7 +29,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) { t.Run("resume mode uses session id and omits workdir", func(t *testing.T) { cfg := &Config{Mode: "resume", SessionID: "sid-123", WorkDir: "/ignored"} got := backend.BuildArgs(cfg, "resume-task") - want := []string{"-p", "--dangerously-skip-permissions", "-r", "sid-123", "--output-format", "stream-json", "--verbose", "resume-task"} + want := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "-r", "sid-123", "--output-format", "stream-json", "--verbose", "resume-task"} if !reflect.DeepEqual(got, want) { t.Fatalf("got %v, want %v", got, want) } @@ -38,7 +38,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) { t.Run("resume mode without session still returns base flags", func(t *testing.T) { cfg := &Config{Mode: "resume", WorkDir: "/ignored"} got := backend.BuildArgs(cfg, "follow-up") - want := []string{"-p", "--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose", "follow-up"} + want := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "follow-up"} if !reflect.DeepEqual(got, want) { t.Fatalf("got %v, want %v", got, want) } diff --git a/codeagent-wrapper/main_test.go b/codeagent-wrapper/main_test.go index 0f41b65..85d4c42 100644 --- a/codeagent-wrapper/main_test.go +++ b/codeagent-wrapper/main_test.go @@ -1378,7 +1378,7 @@ func TestBackendBuildArgs_ClaudeBackend(t *testing.T) { backend := ClaudeBackend{} cfg := &Config{Mode: "new", WorkDir: defaultWorkdir} got := backend.BuildArgs(cfg, "todo") - want := []string{"-p", "--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose", "todo"} + want := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "todo"} if len(got) != len(want) { t.Fatalf("length mismatch") } @@ -1399,7 +1399,7 @@ func TestClaudeBackendBuildArgs_OutputValidation(t *testing.T) { target := "ensure-flags" args := backend.BuildArgs(cfg, target) - expectedPrefix := []string{"-p", "--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose"} + expectedPrefix := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "--output-format", "stream-json", "--verbose"} if len(args) != len(expectedPrefix)+1 { t.Fatalf("args length=%d, want %d", len(args), len(expectedPrefix)+1)