From f5d093b7cb2b1bf3f16ae8f7ef31ad374c7e8314 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 10 Oct 2026 00:17:53 +0200 Subject: [PATCH 1/3] Add animated Claude-style starburst icon to blink progress bar --- blink/internal/reporter/progress.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/blink/internal/reporter/progress.go b/blink/internal/reporter/progress.go index 5ce6e6e483..830b65c991 100644 --- a/blink/internal/reporter/progress.go +++ b/blink/internal/reporter/progress.go @@ -15,9 +15,13 @@ type Progress struct { active bool total int cur int + frame int mu sync.Mutex } +// claudeFrames is the Claude-style twinkling starburst, advanced one step per render. +var claudeFrames = []string{"✶", "✷", "✸", "✹", "✺", "✹", "✸", "✷"} + // NewProgress returns a progress bar; it only draws when w is a terminal. func NewProgress(w *os.File) *Progress { p := &Progress{w: w, width: 28} @@ -64,7 +68,7 @@ func (p *Progress) Finish() { if p == nil || !p.active { return } - _, _ = fmt.Fprintf(p.w, "\r%s\r", strings.Repeat(" ", p.width+20)) + _, _ = fmt.Fprintf(p.w, "\r%s\r", strings.Repeat(" ", p.width+24)) } func (p *Progress) render() { @@ -82,5 +86,7 @@ func (p *Progress) render() { default: bar = strings.Repeat("=", filled-1) + ">" + strings.Repeat(" ", p.width-filled) } - _, _ = fmt.Fprintf(p.w, "\r %d/%d [%s] %3d%%", p.cur, p.total, bar, pct) + icon := claudeFrames[p.frame%len(claudeFrames)] + p.frame++ + _, _ = fmt.Fprintf(p.w, "\r %s %d/%d [%s] %3d%%", icon, p.cur, p.total, bar, pct) } From f15eee3380a9da9255592dfd7730510967840e35 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 10 Oct 2026 00:34:01 +0200 Subject: [PATCH 2/3] Show only the animated icon in blink progress, drop bar and percent --- blink/internal/reporter/progress.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/blink/internal/reporter/progress.go b/blink/internal/reporter/progress.go index 830b65c991..c89b3257bc 100644 --- a/blink/internal/reporter/progress.go +++ b/blink/internal/reporter/progress.go @@ -75,18 +75,7 @@ func (p *Progress) render() { if p.total <= 0 { return } - pct := p.cur * 100 / p.total - filled := p.cur * p.width / p.total - var bar string - switch { - case filled >= p.width: - bar = strings.Repeat("=", p.width) - case filled == 0: - bar = ">" + strings.Repeat(" ", p.width-1) - default: - bar = strings.Repeat("=", filled-1) + ">" + strings.Repeat(" ", p.width-filled) - } icon := claudeFrames[p.frame%len(claudeFrames)] p.frame++ - _, _ = fmt.Fprintf(p.w, "\r %s %d/%d [%s] %3d%%", icon, p.cur, p.total, bar, pct) + _, _ = fmt.Fprintf(p.w, "\r %s", icon) } From 3487dc7401a84879d1230594b3875f73a091ebb4 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 10 Oct 2026 09:04:01 +0200 Subject: [PATCH 3/3] Swap progress icon frames to a pulsing bloom --- blink/internal/reporter/progress.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blink/internal/reporter/progress.go b/blink/internal/reporter/progress.go index c89b3257bc..010067d9f7 100644 --- a/blink/internal/reporter/progress.go +++ b/blink/internal/reporter/progress.go @@ -19,8 +19,8 @@ type Progress struct { mu sync.Mutex } -// claudeFrames is the Claude-style twinkling starburst, advanced one step per render. -var claudeFrames = []string{"✶", "✷", "✸", "✹", "✺", "✹", "✸", "✷"} +// iconFrames is a pulsing bloom that grows from a dot to a star and back, advanced one step per render. +var iconFrames = []string{"·", "∘", "○", "◯", "✦", "✧", "✦", "◯", "○", "∘"} // NewProgress returns a progress bar; it only draws when w is a terminal. func NewProgress(w *os.File) *Progress { @@ -75,7 +75,7 @@ func (p *Progress) render() { if p.total <= 0 { return } - icon := claudeFrames[p.frame%len(claudeFrames)] + icon := iconFrames[p.frame%len(iconFrames)] p.frame++ _, _ = fmt.Fprintf(p.w, "\r %s", icon) }