on main help sign in
feat(tui): progress bar (#1162)

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

commitd0724b16aa37057635896d04d0032413cf7923c7 authorCarlos Alexandro Becker <caarlos0@users.noreply.github.com> dateWed 1 Oct 2025, 15:15 (1 year ago) parentf7ffd8a
4 files changed+24−10
go.mod+3−3 go.sum+8−4 internal/app/app.go+6−3 internal/tui/tui.go+7
go.mod+3−3
@@ -13,13 +13,13 @@ require (
1313 github.com/bmatcuk/doublestar/v4 v4.9.1
1414 github.com/charlievieth/fastwalk v1.0.14
1515 github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2
16− github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250910155747-997384b0b35e
16+ github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250930175933-4cafc092c5e7
1717 github.com/charmbracelet/catwalk v0.6.1
1818 github.com/charmbracelet/fang v0.4.2
1919 github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018
2020 github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea
2121 github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706
22− github.com/charmbracelet/x/ansi v0.10.1
22+ github.com/charmbracelet/x/ansi v0.10.2
2323 github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3
2424 github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a
2525 github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec
@@ -104,7 +104,7 @@ require (
104104 github.com/lucasb-eyer/go-colorful v1.3.0
105105 github.com/mailru/easyjson v0.7.7 // indirect
106106 github.com/mattn/go-isatty v0.0.20 // indirect
107− github.com/mattn/go-runewidth v0.0.16 // indirect
107+ github.com/mattn/go-runewidth v0.0.17 // indirect
108108 github.com/mfridman/interpolate v0.0.2 // indirect
109109 github.com/microcosm-cc/bluemonday v1.0.27 // indirect
110110 github.com/mitchellh/mapstructure v1.5.0 // indirect
go.sum+8−4
@@ -80,6 +80,8 @@ github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2
8080github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2/go.mod h1:6HamsBKWqEC/FVHuQMHgQL+knPyvHH55HwJDHl/adMw=
8181github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250910155747-997384b0b35e h1:4BBnKWFwJ5FLyhw/ijFxKE04i9rubr8WIPR1kjO57iA=
8282github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250910155747-997384b0b35e/go.mod h1:F7AfLKYQqpM3NNBVs7ctW417tavhvoh9SBjsgtwpzbY=
83+github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250930175933-4cafc092c5e7 h1:wH4F+UvxcZSDOxy8j45tghiRo8amrYHejbE9+1C6xv0=
84+github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250930175933-4cafc092c5e7/go.mod h1:5IzIGXU1n0foRc8bRAherC8ZuQCQURPlwx3ANLq1138=
8385github.com/charmbracelet/catwalk v0.6.1 h1:2rRqUlwo+fdyIty8jEvUufRTgqBl0aea21LV6YQPqb0=
8486github.com/charmbracelet/catwalk v0.6.1/go.mod h1:ReU4SdrLfe63jkEjWMdX2wlZMV3k9r11oQAmzN0m+KY=
8587github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
@@ -94,8 +96,10 @@ github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706 h1:WkwO6Ks3mS
9496github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706/go.mod h1:mjJGp00cxcfvD5xdCa+bso251Jt4owrQvuimJtVmEmM=
9597github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef h1:VrWaUi2LXYLjfjCHowdSOEc6dQ9Ro14KY7Bw4IWd19M=
9698github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef/go.mod h1:AThRsQH1t+dfyOKIwXRoJBniYFQUkUpQq4paheHMc2o=
97−github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
98−github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
99+github.com/charmbracelet/x/ansi v0.10.2-0.20250929231137-76218bae042e h1:aN905mmYvQsT4xKUZTdM+lCcuxTrubM3DGVTPxk0ArM=
100+github.com/charmbracelet/x/ansi v0.10.2-0.20250929231137-76218bae042e/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
101+github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=
102+github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
99103github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a h1:zYSNtEJM9jwHbJts2k+Hroj+xQwsW1yxc4Wopdv7KaI=
100104github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a/go.mod h1:rc2bsPC6MWae3LdOxNO1mOb443NlMrrDL0xEya48NNc=
101105github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 h1:1xwHZg6eMZ9Wv5TE1UGub6ARubyOd1Lo5kPUI/6VL50=
@@ -198,8 +202,8 @@ github.com/mark3labs/mcp-go v0.41.0 h1:IFfJaovCet65F3av00bE1HzSnmHpMRWM1kz96R98I
198202github.com/mark3labs/mcp-go v0.41.0/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g=
199203github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
200204github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
201−github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
202−github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
205+github.com/mattn/go-runewidth v0.0.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkENfrjQ=
206+github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
203207github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
204208github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
205209github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
internal/app/app.go+6−3
@@ -17,12 +17,12 @@ import (
1717 "github.com/charmbracelet/crush/internal/history"
1818 "github.com/charmbracelet/crush/internal/llm/agent"
1919 "github.com/charmbracelet/crush/internal/log"
20− "github.com/charmbracelet/crush/internal/pubsub"
21−
2220 "github.com/charmbracelet/crush/internal/lsp"
2321 "github.com/charmbracelet/crush/internal/message"
2422 "github.com/charmbracelet/crush/internal/permission"
23+ "github.com/charmbracelet/crush/internal/pubsub"
2524 "github.com/charmbracelet/crush/internal/session"
25+ "github.com/charmbracelet/x/ansi"
2626)
2727
2828type App struct {
@@ -107,7 +107,10 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool
107107 ctx, cancel := context.WithCancel(ctx)
108108 defer cancel()
109109
110− // Start spinner if not in quiet mode.
110+ // Start progress bar and spinner
111+ fmt.Printf(ansi.SetIndeterminateProgressBar)
112+ defer fmt.Printf(ansi.ResetProgressBar)
113+
111114 var spinner *format.Spinner
112115 if !quiet {
113116 spinner = format.NewSpinner(ctx, cancel, "Generating")
internal/tui/tui.go+7
@@ -3,6 +3,7 @@ package tui
33import (
44 "context"
55 "fmt"
6+ "math/rand"
67 "strings"
78 "time"
89
@@ -601,6 +602,12 @@ func (a *appModel) View() tea.View {
601602
602603 view.Layer = canvas
603604 view.Cursor = cursor
605+ view.ProgressBar = tea.NewProgressBar(tea.ProgressBarNone, 0)
606+ if a.app.CoderAgent.IsBusy() {
607+ // use a random percentage to prevent the ghostty from hiding it after
608+ // a timeout.
609+ view.ProgressBar = tea.NewProgressBar(tea.ProgressBarIndeterminate, rand.Intn(100))
610+ }
604611 return view
605612}
606613