From b86de28a062fdeabb5da55b36e6f0bcc69428835 Mon Sep 17 00:00:00 2001 From: rgarcia <72655+rgarcia@users.noreply.github.com> Date: Fri, 5 Jun 2026 21:03:02 +0000 Subject: [PATCH] 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 --- cmd/color_test.go | 24 ++++++++++++++++++++++++ cmd/root.go | 18 ++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 cmd/color_test.go diff --git a/cmd/color_test.go b/cmd/color_test.go new file mode 100644 index 0000000..56b1ce8 --- /dev/null +++ b/cmd/color_test.go @@ -0,0 +1,24 @@ +package cmd + +import "testing" + +func TestShouldEnableColor(t *testing.T) { + tests := []struct { + name string + noColorEnv string + isTTY bool + want bool + }{ + {"tty, no env", "", true, true}, + {"not tty, no env", "", false, false}, + {"tty, NO_COLOR set", "1", true, false}, + {"not tty, NO_COLOR set", "1", false, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := shouldEnableColor(tt.noColorEnv, tt.isTTY); got != tt.want { + t.Errorf("shouldEnableColor(%q, %v) = %v, want %v", tt.noColorEnv, tt.isTTY, got, tt.want) + } + }) + } +} diff --git a/cmd/root.go b/cmd/root.go index 88d6d87..ac9f18b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,6 +15,7 @@ import ( "github.com/kernel/cli/cmd/mcp" "github.com/kernel/cli/cmd/proxies" "github.com/kernel/cli/pkg/auth" + "github.com/kernel/cli/pkg/table" "github.com/kernel/cli/pkg/update" "github.com/kernel/cli/pkg/util" "github.com/kernel/kernel-go-sdk" @@ -177,9 +178,22 @@ func init() { } } +// shouldEnableColor decides whether pterm color styling should be on. +// NO_COLOR (any non-empty value) always wins per https://no-color.org. +// Otherwise color is enabled only when stdout is an interactive terminal. +func shouldEnableColor(noColorEnv string, isTTY bool) bool { + if noColorEnv != "" { + return false + } + return isTTY +} + func initConfig() { - // Placeholder for future configuration (env vars, config files, etc.) - pterm.EnableStyling() // ensure pterm is initialised in case env disables it + if shouldEnableColor(os.Getenv("NO_COLOR"), table.IsStdoutTTY()) { + pterm.EnableStyling() + } else { + pterm.DisableStyling() + } } // Execute executes the root command.