feat: allow to disable indeterminate progress bar (#2048)

Carlos Alexandro Becker created

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

Change summary

internal/app/app.go       | 7 +++++--
internal/config/config.go | 3 ++-
internal/ui/model/ui.go   | 8 ++++++--
3 files changed, 13 insertions(+), 5 deletions(-)

Detailed changes

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)

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

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))