diff --git a/internal/app/app.go b/internal/app/app.go index 647d90c9cfe29402b00ef5743f3a84f5e1b681ab..f914600457061056648cb23baa7901ca8d946f24 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -152,6 +152,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, stdoutTTY bool stderrTTY bool stdinTTY bool + progress bool ) if f, ok := output.(*os.File); ok { @@ -160,6 +161,8 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, stderrTTY = term.IsTerminal(os.Stderr.Fd()) stdinTTY = term.IsTerminal(os.Stdin.Fd()) + progress = app.config.Options.Progress == nil || *app.config.Options.Progress + if !quiet && stderrTTY { t := styles.CurrentTheme() @@ -244,7 +247,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, messageReadBytes := make(map[string]int) defer func() { - if stderrTTY { + if progress && stderrTTY { _, _ = fmt.Fprintf(os.Stderr, ansi.ResetProgressBar) } @@ -254,7 +257,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, }() for { - if stderrTTY { + if progress && stderrTTY { // HACK: Reinitialize the terminal progress bar on every iteration // so it doesn't get hidden by the terminal due to inactivity. _, _ = fmt.Fprintf(os.Stderr, ansi.SetIndeterminateProgressBar) diff --git a/internal/config/config.go b/internal/config/config.go index d18d2d9c61d2f791ab9c6f9a0b7cd41029b70e60..b9bc5259d36390d53aa21befd524ea7043261905 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -257,7 +257,8 @@ type Options struct { Attribution *Attribution `json:"attribution,omitempty" jsonschema:"description=Attribution settings for generated content"` DisableMetrics bool `json:"disable_metrics,omitempty" jsonschema:"description=Disable sending metrics,default=false"` InitializeAs string `json:"initialize_as,omitempty" jsonschema:"description=Name of the context file to create/update during project initialization,default=AGENTS.md,example=AGENTS.md,example=CRUSH.md,example=CLAUDE.md,example=docs/LLMs.md"` - AutoLSP *bool `json:"auto_lsp,omitempty" jsonschema:"description=Automatically setup LSPs based on root markers"` + AutoLSP *bool `json:"auto_lsp,omitempty" jsonschema:"description=Automatically setup LSPs based on root markers,default=true"` + Progress *bool `json:"progress,omitempty" jsonschema:"description=Show indeterminate progress updates during long operations,default=true"` } type MCPs map[string]MCPConfig diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index 9eb7f01f881e70ad82597820dac8e3161f4cd684..eca2cf80a343214babbcfbdb37916a61d07a1ced 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -144,7 +144,8 @@ type UI struct { // sendProgressBar instructs the TUI to send progress bar updates to the // terminal. - sendProgressBar bool + sendProgressBar bool + progressBarEnabled bool // caps hold different terminal capabilities that we query for. caps common.Capabilities @@ -295,6 +296,9 @@ func New(com *common.Common) *UI { // set initial state ui.setState(desiredState, desiredFocus) + // disable indeterminate progress bar + ui.progressBarEnabled = com.Config().Options.Progress == nil || *com.Config().Options.Progress + return ui } @@ -1854,7 +1858,7 @@ func (m *UI) View() tea.View { content = strings.Join(contentLines, "\n") v.Content = content - if m.sendProgressBar && m.isAgentBusy() { + if m.progressBarEnabled && m.sendProgressBar && m.isAgentBusy() { // HACK: use a random percentage to prevent ghostty from hiding it // after a timeout. v.ProgressBar = tea.NewProgressBar(tea.ProgressBarIndeterminate, rand.Intn(100))