diff --git a/claudetool/bash.go b/claudetool/bash.go index 9f998ea58a7888a351613be04f25da7e48883009..7e3bfd5bc6800388ac644da5ea6d35c18c9febb1 100644 --- a/claudetool/bash.go +++ b/claudetool/bash.go @@ -96,6 +96,15 @@ func (b *BashTool) getWorkingDir() string { return b.WorkingDir.Get() } +// isNoTrailerSet checks if user has disabled co-author trailer via git config. +func (b *BashTool) isNoTrailerSet() bool { + out, err := exec.Command("git", "config", "--get", "shelley.no-trailer").Output() + if err != nil { + return false + } + return strings.TrimSpace(string(out)) == "true" +} + const ( bashName = "bash" bashDescription = `Executes shell commands via bash -c, returning combined stdout/stderr. @@ -207,8 +216,10 @@ func (b *BashTool) Run(ctx context.Context, m json.RawMessage) llm.ToolOut { } } - // Add co-author trailer to git commits - req.Command = bashkit.AddCoauthorTrailer(req.Command, "Co-authored-by: Shelley ") + // Add co-author trailer to git commits unless user has disabled it + if !b.isNoTrailerSet() { + req.Command = bashkit.AddCoauthorTrailer(req.Command, "Co-authored-by: Shelley ") + } timeout := req.timeout(b.Timeouts) diff --git a/claudetool/bash_test.go b/claudetool/bash_test.go index 4346a1b5b990a0201ca95702b165ecd5c3c0b36a..3b44122c1e3f05d32e4bf034d0a7c479ed950fd4 100644 --- a/claudetool/bash_test.go +++ b/claudetool/bash_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "os" + "os/exec" "path/filepath" "strings" "syscall" @@ -721,3 +722,41 @@ func waitForProcessDeath(t *testing.T, pid int) { } } } + +func TestIsNoTrailerSet(t *testing.T) { + bashTool := &BashTool{WorkingDir: NewMutableWorkingDir("/")} + + // Test when config is not set (default) + t.Run("Default No Config", func(t *testing.T) { + if bashTool.isNoTrailerSet() { + t.Error("Expected isNoTrailerSet() to be false when not configured") + } + }) + + // Test when config is set to true + t.Run("Config Set True", func(t *testing.T) { + // Set the global config + cmd := exec.Command("git", "config", "--global", "shelley.no-trailer", "true") + if err := cmd.Run(); err != nil { + t.Skipf("Could not set git config: %v", err) + } + defer exec.Command("git", "config", "--global", "--unset", "shelley.no-trailer").Run() + + if !bashTool.isNoTrailerSet() { + t.Error("Expected isNoTrailerSet() to be true when shelley.no-trailer=true") + } + }) + + // Test when config is set to false + t.Run("Config Set False", func(t *testing.T) { + cmd := exec.Command("git", "config", "--global", "shelley.no-trailer", "false") + if err := cmd.Run(); err != nil { + t.Skipf("Could not set git config: %v", err) + } + defer exec.Command("git", "config", "--global", "--unset", "shelley.no-trailer").Run() + + if bashTool.isNoTrailerSet() { + t.Error("Expected isNoTrailerSet() to be false when shelley.no-trailer=false") + } + }) +}