diff --git a/pkg/cmd/build.go b/pkg/cmd/build.go index d6f61267..9678365c 100644 --- a/pkg/cmd/build.go +++ b/pkg/cmd/build.go @@ -434,7 +434,7 @@ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error { Build: cbuild.NewModel(client, ctx, *build, cmd.String("branch"), downloadPaths), WaitMode: waitMode, }) - model, err = tea.NewProgram(model).Run() + model, err = console.NewProgram(model).Run() if err != nil { console.Warn("%s", err.Error()) } diff --git a/pkg/cmd/dev.go b/pkg/cmd/dev.go index b6071fd0..a42653cb 100644 --- a/pkg/cmd/dev.go +++ b/pkg/cmd/dev.go @@ -13,7 +13,6 @@ import ( "strings" "time" - tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/huh" "github.com/stainless-api/stainless-api-cli/pkg/components/build" "github.com/stainless-api/stainless-api-cli/pkg/components/dev" @@ -255,7 +254,7 @@ func runDevBuild(ctx context.Context, client stainless.Client, wc workspace.Conf cmd.Bool("watch"), ) - p := tea.NewProgram(model) + p := console.NewProgram(model) finalModel, err := p.Run() if err != nil { diff --git a/pkg/cmd/init.go b/pkg/cmd/init.go index 09f35370..58154e26 100644 --- a/pkg/cmd/init.go +++ b/pkg/cmd/init.go @@ -19,7 +19,6 @@ import ( "github.com/stainless-api/stainless-api-cli/pkg/workspace" "github.com/stainless-api/stainless-api-go/option" - tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/huh" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/x/term" @@ -426,7 +425,7 @@ func initializeWorkspace(ctx context.Context, cmd *cli.Command, client stainless Build: cbuild.NewModel(client, ctx, *build, "main", downloadPaths), } - _, err = tea.NewProgram(model).Run() + _, err = console.NewProgram(model).Run() if err != nil { console.Warn("%s", err.Error()) } diff --git a/pkg/cmd/lint.go b/pkg/cmd/lint.go index 840e5aa6..cc351dc1 100644 --- a/pkg/cmd/lint.go +++ b/pkg/cmd/lint.go @@ -13,6 +13,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/stainless-api/stainless-api-cli/pkg/components/build" + "github.com/stainless-api/stainless-api-cli/pkg/console" "github.com/stainless-api/stainless-api-cli/pkg/workspace" "github.com/stainless-api/stainless-api-go" "github.com/urfave/cli/v3" @@ -211,7 +212,7 @@ func runLinter(ctx context.Context, cmd *cli.Command, canSkip bool) error { help: help.New(), } - p := tea.NewProgram(m, tea.WithContext(ctx)) + p := console.NewProgram(m, tea.WithContext(ctx)) // Start the diagnostics process go func() { diff --git a/pkg/console/print.go b/pkg/console/print.go index 699187d7..a278bb63 100644 --- a/pkg/console/print.go +++ b/pkg/console/print.go @@ -12,8 +12,25 @@ import ( "github.com/charmbracelet/x/ansi" "github.com/logrusorgru/aurora/v4" "github.com/urfave/cli/v3" + "golang.org/x/term" ) +// NewProgram wraps tea.NewProgram with better handling for tty environments +func NewProgram(model tea.Model, opts ...tea.ProgramOption) *tea.Program { + // Always output to stderr, in case we want to also output JSON so that the json is redirectable e.g. to jq. + opts = append(opts, tea.WithOutput(os.Stderr)) + + // If not a TTY, use stdin and disable renderer + if !term.IsTerminal(int(os.Stderr.Fd())) { + opts = append(opts, + tea.WithInput(os.Stdin), + tea.WithoutRenderer(), + ) + } + + return tea.NewProgram(model, opts...) +} + // Group represents a nested logging group type Group struct { prefix string @@ -255,7 +272,7 @@ func spinnerWithIndent(indent int, message string, operation func() error) error execute: operation, } - finalModel, err := tea.NewProgram(model).Run() + finalModel, err := NewProgram(model).Run() if err != nil { return err }