Repository navigation
fix: replace bubbletea-based spinner with a plain ANSI spinner - #1116
Merged
Merged
Conversation
bubbletea's package init() unconditionally calls lipgloss.HasDarkBackground(), which queries the terminal for its background color (OSC 11 + CSI 6n) and blocks for up to termenv's 5s OSCTimeout if nothing answers. Since Go runs every imported package's init() before main() regardless of which subcommand is invoked, this cost was paid on every onctl invocation -- including `version`/`help` -- once a real terminal wasn't attached to answer the query (non-interactive ssh -tt, some pty relays/proxies). Replace the bubbletea/bubbles/lipgloss-based Spinner with a minimal implementation that writes the same dot-spinner frames directly via ANSI escapes, with no terminal capability probing. This also drops the need to put stdin into raw mode (and the associated pristine-state/restore-on-timeout logic), since the new spinner never reads terminal input. Fixes #1115. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116eShGQZYddF8G43ysmVnP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1115.
internal/ui/spinner.gowas the only file in the repo importingcharmbracelet/bubbletea(and transitivelybubbles,lipgloss,muesli/termenv). Bubble Tea ships a package-levelinit()that callslipgloss.HasDarkBackground(), which queries the terminal for its background color (OSC 11 + CSI 6n) and blocks for up totermenv's hardcoded 5sOSCTimeoutif nothing answers.Because Go runs every imported package's
init()beforemain()regardless of which subcommand is actually invoked, this cost was paid on everyonctlinvocation — includingversion/help/anything — whenever a real terminal wasn't attached to answer the query (non-interactivessh -tt, some pty relays/proxies, per the issue's repro).Since this happens in a third-party package's
init(), no runtime check inside onctl can intercept it in time, and no combination of import restructuring avoids it either — theonctlbinary is a single statically linked binary, so any package it imports anywhere has itsinit()run on every invocation. The only way to actually eliminate the cost is to stop linking in the dependency that causes it.Change
Replaced the Bubble Tea/Lip Gloss-backed
Spinnerwith a small hand-rolled implementation that renders the same dot-spinner frames (⣾⣽⣻⢿⡿⣟⣯⣷, same color, same 10fps) directly via ANSI escape codes written to stderr. No terminal capability probing is performed at all, so nothing can block on an unresponsive pty. The public API (New,Start,Stop,Restart,SetSuffix,Active,Suffix) is unchanged, so all callers (cmd/create.go,cmd/deploy.go,cmd/destroy.go,cmd/ssh.go) needed no changes.As a side benefit, the new spinner never reads terminal input, so it no longer needs to put stdin into raw mode — this also removes the pristine-terminal-state-capture/forced-restore-on-timeout logic that existed solely to work around Bubble Tea leaving the pty in raw mode if its own cleanup didn't finish in time (see #1086).
go mod tidydropscharmbracelet/bubbletea,charmbracelet/bubbles,charmbracelet/lipgloss,muesli/termenv, and their other transitive-only dependencies fromgo.mod/go.sum.Verification
go build ./...andgo vet ./...pass.go test ./...passes (one pre-existing, unrelated failure incmd.TestPopulateOnctlEnv_ErrorWritingFilereproduces identically onmainbefore this change).go list -deps .no longer contains anycharmbracelet/*ormuesli/termenvpackage.time ./onctl version— before: paid the 5s hang in the issue's repro environment; after: unaffected regardless of pty responsiveness, since the dependency causing the query is no longer linked in at all.Test plan
internal/ui/spinner_test.goupdated for the new internal representation and passingStart/SetSuffix/Stoplifecyclecreate/deploy/destroy(not verified here — no interactive tty available in this sandbox)🤖 Generated with Claude Code
https://claude.ai/code/session_0116eShGQZYddF8G43ysmVnP
Generated by Claude Code