mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-10 03:14:32 +08:00
feat(codeagent-wrapper): default to skip-permissions and bypass-sandbox
- Claude: enable --dangerously-skip-permissions by default (set CODEAGENT_SKIP_PERMISSIONS=false to disable) - Codex: enable --dangerously-bypass-approvals-and-sandbox by default (set CODEX_BYPASS_SANDBOX=false to disable) - Gemini: use positional argument instead of deprecated -p flag (except for stdin mode) - Add envFlagDefaultTrue helper for default-true env flags Generated with SWE-Agent.ai Co-Authored-By: SWE-Agent.ai <noreply@swe-agent.ai>
This commit is contained in:
@@ -111,7 +111,8 @@ func buildClaudeArgs(cfg *Config, targetArg string) []string {
|
||||
return nil
|
||||
}
|
||||
args := []string{"-p"}
|
||||
if cfg.SkipPermissions || cfg.Yolo {
|
||||
// Default to skip permissions unless CODEAGENT_SKIP_PERMISSIONS=false
|
||||
if cfg.SkipPermissions || cfg.Yolo || envFlagDefaultTrue("CODEAGENT_SKIP_PERMISSIONS") {
|
||||
args = append(args, "--dangerously-skip-permissions")
|
||||
}
|
||||
|
||||
@@ -179,7 +180,13 @@ func buildGeminiArgs(cfg *Config, targetArg string) []string {
|
||||
}
|
||||
// Note: gemini CLI doesn't support -C flag; workdir set via cmd.Dir
|
||||
|
||||
args = append(args, "-p", targetArg)
|
||||
// Use positional argument instead of deprecated -p flag
|
||||
// For stdin mode ("-"), use -p to read from stdin
|
||||
if targetArg == "-" {
|
||||
args = append(args, "-p", targetArg)
|
||||
} else {
|
||||
args = append(args, targetArg)
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
|
||||
backend := ClaudeBackend{}
|
||||
|
||||
t.Run("new mode omits skip-permissions by default", func(t *testing.T) {
|
||||
t.Run("new mode omits skip-permissions when env disabled", func(t *testing.T) {
|
||||
t.Setenv("CODEAGENT_SKIP_PERMISSIONS", "false")
|
||||
cfg := &Config{Mode: "new", WorkDir: "/repo"}
|
||||
got := backend.BuildArgs(cfg, "todo")
|
||||
want := []string{"-p", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "todo"}
|
||||
@@ -20,8 +21,8 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("new mode can opt-in skip-permissions", func(t *testing.T) {
|
||||
cfg := &Config{Mode: "new", SkipPermissions: true}
|
||||
t.Run("new mode includes skip-permissions by default", func(t *testing.T) {
|
||||
cfg := &Config{Mode: "new", SkipPermissions: false}
|
||||
got := backend.BuildArgs(cfg, "-")
|
||||
want := []string{"-p", "--dangerously-skip-permissions", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "-"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
@@ -30,6 +31,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("resume mode includes session id", func(t *testing.T) {
|
||||
t.Setenv("CODEAGENT_SKIP_PERMISSIONS", "false")
|
||||
cfg := &Config{Mode: "resume", SessionID: "sid-123", WorkDir: "/ignored"}
|
||||
got := backend.BuildArgs(cfg, "resume-task")
|
||||
want := []string{"-p", "--setting-sources", "", "-r", "sid-123", "--output-format", "stream-json", "--verbose", "resume-task"}
|
||||
@@ -39,6 +41,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("resume mode without session still returns base flags", func(t *testing.T) {
|
||||
t.Setenv("CODEAGENT_SKIP_PERMISSIONS", "false")
|
||||
cfg := &Config{Mode: "resume", WorkDir: "/ignored"}
|
||||
got := backend.BuildArgs(cfg, "follow-up")
|
||||
want := []string{"-p", "--setting-sources", "", "--output-format", "stream-json", "--verbose", "follow-up"}
|
||||
@@ -65,6 +68,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
|
||||
|
||||
func TestBackendBuildArgs_Model(t *testing.T) {
|
||||
t.Run("claude includes --model when set", func(t *testing.T) {
|
||||
t.Setenv("CODEAGENT_SKIP_PERMISSIONS", "false")
|
||||
backend := ClaudeBackend{}
|
||||
cfg := &Config{Mode: "new", Model: "opus"}
|
||||
got := backend.BuildArgs(cfg, "todo")
|
||||
@@ -78,7 +82,7 @@ func TestBackendBuildArgs_Model(t *testing.T) {
|
||||
backend := GeminiBackend{}
|
||||
cfg := &Config{Mode: "new", Model: "gemini-3-pro-preview"}
|
||||
got := backend.BuildArgs(cfg, "task")
|
||||
want := []string{"-o", "stream-json", "-y", "-m", "gemini-3-pro-preview", "-p", "task"}
|
||||
want := []string{"-o", "stream-json", "-y", "-m", "gemini-3-pro-preview", "task"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
@@ -103,7 +107,7 @@ func TestClaudeBuildArgs_GeminiAndCodexModes(t *testing.T) {
|
||||
backend := GeminiBackend{}
|
||||
cfg := &Config{Mode: "new", WorkDir: "/workspace"}
|
||||
got := backend.BuildArgs(cfg, "task")
|
||||
want := []string{"-o", "stream-json", "-y", "-p", "task"}
|
||||
want := []string{"-o", "stream-json", "-y", "task"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
@@ -113,7 +117,7 @@ func TestClaudeBuildArgs_GeminiAndCodexModes(t *testing.T) {
|
||||
backend := GeminiBackend{}
|
||||
cfg := &Config{Mode: "resume", SessionID: "sid-999"}
|
||||
got := backend.BuildArgs(cfg, "resume")
|
||||
want := []string{"-o", "stream-json", "-y", "-r", "sid-999", "-p", "resume"}
|
||||
want := []string{"-o", "stream-json", "-y", "-r", "sid-999", "resume"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
@@ -123,7 +127,7 @@ func TestClaudeBuildArgs_GeminiAndCodexModes(t *testing.T) {
|
||||
backend := GeminiBackend{}
|
||||
cfg := &Config{Mode: "resume"}
|
||||
got := backend.BuildArgs(cfg, "resume")
|
||||
want := []string{"-o", "stream-json", "-y", "-p", "resume"}
|
||||
want := []string{"-o", "stream-json", "-y", "resume"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
@@ -136,6 +140,16 @@ func TestClaudeBuildArgs_GeminiAndCodexModes(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("gemini stdin mode uses -p flag", func(t *testing.T) {
|
||||
backend := GeminiBackend{}
|
||||
cfg := &Config{Mode: "new"}
|
||||
got := backend.BuildArgs(cfg, "-")
|
||||
want := []string{"-o", "stream-json", "-y", "-p", "-"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("codex build args omits bypass flag by default", func(t *testing.T) {
|
||||
const key = "CODEX_BYPASS_SANDBOX"
|
||||
t.Setenv(key, "false")
|
||||
|
||||
@@ -112,6 +112,15 @@ func parseBoolFlag(val string, defaultValue bool) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// envFlagDefaultTrue returns true unless the env var is explicitly set to false/0/no/off.
|
||||
func envFlagDefaultTrue(key string) bool {
|
||||
val, ok := os.LookupEnv(key)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
return parseBoolFlag(val, true)
|
||||
}
|
||||
|
||||
func validateAgentName(name string) error {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return fmt.Errorf("agent name is empty")
|
||||
|
||||
@@ -754,8 +754,9 @@ func buildCodexArgs(cfg *Config, targetArg string) []string {
|
||||
|
||||
args := []string{"e"}
|
||||
|
||||
if cfg.Yolo || envFlagEnabled("CODEX_BYPASS_SANDBOX") {
|
||||
logWarn("YOLO mode or CODEX_BYPASS_SANDBOX=true: running without approval/sandbox protection")
|
||||
// Default to bypass sandbox unless CODEX_BYPASS_SANDBOX=false
|
||||
if cfg.Yolo || envFlagDefaultTrue("CODEX_BYPASS_SANDBOX") {
|
||||
logWarn("YOLO mode or CODEX_BYPASS_SANDBOX enabled: running without approval/sandbox protection")
|
||||
args = append(args, "--dangerously-bypass-approvals-and-sandbox")
|
||||
}
|
||||
|
||||
|
||||
@@ -1925,7 +1925,7 @@ func TestRunBuildCodexArgs_BypassSandboxEnvTrue(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read log file: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(data), "CODEX_BYPASS_SANDBOX=true") {
|
||||
if !strings.Contains(string(data), "CODEX_BYPASS_SANDBOX enabled") {
|
||||
t.Fatalf("expected bypass warning log, got: %s", string(data))
|
||||
}
|
||||
}
|
||||
@@ -1982,6 +1982,7 @@ func TestBackendSelectBackend_DefaultOnEmpty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBackendBuildArgs_CodexBackend(t *testing.T) {
|
||||
t.Setenv("CODEX_BYPASS_SANDBOX", "false")
|
||||
backend := CodexBackend{}
|
||||
cfg := &Config{Mode: "new", WorkDir: "/test/dir"}
|
||||
got := backend.BuildArgs(cfg, "task")
|
||||
@@ -2003,6 +2004,7 @@ func TestBackendBuildArgs_CodexBackend(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBackendBuildArgs_ClaudeBackend(t *testing.T) {
|
||||
t.Setenv("CODEAGENT_SKIP_PERMISSIONS", "false")
|
||||
backend := ClaudeBackend{}
|
||||
cfg := &Config{Mode: "new", WorkDir: defaultWorkdir}
|
||||
got := backend.BuildArgs(cfg, "todo")
|
||||
@@ -2022,6 +2024,7 @@ func TestBackendBuildArgs_ClaudeBackend(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClaudeBackendBuildArgs_OutputValidation(t *testing.T) {
|
||||
t.Setenv("CODEAGENT_SKIP_PERMISSIONS", "false")
|
||||
backend := ClaudeBackend{}
|
||||
cfg := &Config{Mode: "resume"}
|
||||
target := "ensure-flags"
|
||||
@@ -2042,7 +2045,7 @@ func TestBackendBuildArgs_GeminiBackend(t *testing.T) {
|
||||
backend := GeminiBackend{}
|
||||
cfg := &Config{Mode: "new"}
|
||||
got := backend.BuildArgs(cfg, "task")
|
||||
want := []string{"-o", "stream-json", "-y", "-p", "task"}
|
||||
want := []string{"-o", "stream-json", "-y", "task"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("length mismatch")
|
||||
}
|
||||
@@ -2063,7 +2066,7 @@ func TestGeminiBackendBuildArgs_OutputValidation(t *testing.T) {
|
||||
target := "prompt-data"
|
||||
|
||||
args := backend.BuildArgs(cfg, target)
|
||||
expected := []string{"-o", "stream-json", "-y", "-p"}
|
||||
expected := []string{"-o", "stream-json", "-y"}
|
||||
|
||||
if len(args) != len(expected)+1 {
|
||||
t.Fatalf("args length=%d, want %d", len(args), len(expected)+1)
|
||||
|
||||
Reference in New Issue
Block a user