Skip to content

Commit b86de28

Browse files
rgarciaclaude
andcommitted
Disable color output when stdout is not a TTY
pterm v0.12.80 forces color on regardless of the output target, so the CLI emitted raw ANSI escape codes when stdout was piped or captured (e.g. in a headless/programmatic environment), garbling the output. Gate pterm styling in initConfig on an interactive-terminal check and honor the NO_COLOR convention, so non-TTY output is plain text. Interactive terminals are unaffected and the --no-color flag still works. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent dd043f9 commit b86de28

2 files changed

Lines changed: 40 additions & 2 deletions

File tree

cmd/color_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package cmd
2+
3+
import "testing"
4+
5+
func TestShouldEnableColor(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
noColorEnv string
9+
isTTY bool
10+
want bool
11+
}{
12+
{"tty, no env", "", true, true},
13+
{"not tty, no env", "", false, false},
14+
{"tty, NO_COLOR set", "1", true, false},
15+
{"not tty, NO_COLOR set", "1", false, false},
16+
}
17+
for _, tt := range tests {
18+
t.Run(tt.name, func(t *testing.T) {
19+
if got := shouldEnableColor(tt.noColorEnv, tt.isTTY); got != tt.want {
20+
t.Errorf("shouldEnableColor(%q, %v) = %v, want %v", tt.noColorEnv, tt.isTTY, got, tt.want)
21+
}
22+
})
23+
}
24+
}

cmd/root.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/kernel/cli/cmd/mcp"
1616
"github.com/kernel/cli/cmd/proxies"
1717
"github.com/kernel/cli/pkg/auth"
18+
"github.com/kernel/cli/pkg/table"
1819
"github.com/kernel/cli/pkg/update"
1920
"github.com/kernel/cli/pkg/util"
2021
"github.com/kernel/kernel-go-sdk"
@@ -177,9 +178,22 @@ func init() {
177178
}
178179
}
179180

181+
// shouldEnableColor decides whether pterm color styling should be on.
182+
// NO_COLOR (any non-empty value) always wins per https://no-color.org.
183+
// Otherwise color is enabled only when stdout is an interactive terminal.
184+
func shouldEnableColor(noColorEnv string, isTTY bool) bool {
185+
if noColorEnv != "" {
186+
return false
187+
}
188+
return isTTY
189+
}
190+
180191
func initConfig() {
181-
// Placeholder for future configuration (env vars, config files, etc.)
182-
pterm.EnableStyling() // ensure pterm is initialised in case env disables it
192+
if shouldEnableColor(os.Getenv("NO_COLOR"), table.IsStdoutTTY()) {
193+
pterm.EnableStyling()
194+
} else {
195+
pterm.DisableStyling()
196+
}
183197
}
184198

185199
// Execute executes the root command.

0 commit comments

Comments
 (0)