You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TUI: main thread burns ~100% CPU continuously redrawing a spinner (~15fps writev to tty) with no active output #42306
Observed (confirmed via strace + per-thread /proc sampling)
The TUI main thread holds ~1 full core (~94-100%) even when the user is not interacting.
strace shows the main thread repeatedly calling writev(1, ...) writing a ~106-byte spinner frame (~15 fps) to the tty, e.g. \x1b[?2026h\x1b[?25l\x1b[60;4H\x1b[38;2;42;67;101m ... \u2b1d\u2b1d\u2b1d ....
In the same window there are no network / disk / log syscalls — the CPU time is spent between the writes.
Behavior varies by process: in some instances the burn is entirely on the main thread (HeapHelper threads idle), in others HeapHelper threads also show elevated GC activity.
Why this looks like a bug
Writing a 106-byte frame 15x/s should cost <1% CPU. The ~100% burn is in the rendering/layout work before each writev, and the spinner appears to keep animating even with no visible active turn, so the render loop never idles.
Not yet determined (needs a perf profile)
Whether the spinner is "stuck" because a background task (e.g. title generation or a hung turn) never completes, vs. the render loop simply not being throttled. We did not capture a perf profile, so the exact hot function is unconfirmed. Filing this as a bug report rather than a definitive root cause.
Impact
Each such session burns ~1 core and makes the terminal feel frozen/hung. We killed several opencode -c processes assuming a deadlock before tracing the actual CPU usage.
Notes
app_toggle_animations keybind defaults to none, and there is no persistent config option to disable animations.
npm latest is 1.18.18, so there is no newer version to try as a workaround.
Happy to provide full strace output or a perf profile if that helps narrow it down.
changed the title [-]TUI: idle spinner redraws at full framerate (~15fps) causing ~100% CPU busy-spin; UI feels frozen[/-][+]TUI: main thread burns ~100% CPU continuously redrawing a spinner (~15fps writev to tty) with no active output[/+]on Aug 13, 2026
This is really annoying and even relatively expensive (elevated CPU power consumption, extra 10-30W on high-end CPUs), if one is running few interactive sessions simultaneously...
@simonklee if you're already mid-fix, ignore me — otherwise here's what I found digging into this:
The burn isn't a stuck task, it's the status-bar spinner itself. packages/tui/src/component/prompt/index.tsx renders <spinner interval={40} /> whenever status().type !== "idle", and each tick fires requestRender() (opentui-spinner's _advanceFrame), which makes the opentui renderer re-render the entire scene graph. So a one-cell spinner drives 25 full-frame renders/sec, and each frame costs more than its 40ms budget on a long timeline — consistent with the ~15fps writev cadence and the CPU sitting between writes in the strace above.
It also keeps running while the timeline is static (long tool run, retry backoff), which matches the "no visible active output" observation.
I have a small fix ready (one file, ~20 lines in the prompt component): throttle the spinner to 400ms when no message.updated / message.part.* event has landed for 1.5s, keeping 100ms while streaming. Happy to open a PR against this issue — or if you'd rather keep it, the diagnosis is yours to use.
Activity
github-actions commentedon Aug 13, 2026
This issue might be a duplicate of existing issues. Please check:
Since you mentioned
app_toggle_animations, please also check our pinned keybinds documentation: #4997[-]TUI: idle spinner redraws at full framerate (~15fps) causing ~100% CPU busy-spin; UI feels frozen[/-][+]TUI: main thread burns ~100% CPU continuously redrawing a spinner (~15fps writev to tty) with no active output[/+]aldem commentedon Sep 6, 2026
This is really annoying and even relatively expensive (elevated CPU power consumption, extra 10-30W on high-end CPUs), if one is running few interactive sessions simultaneously...
ghwinter commentedon Sep 8, 2026
@simonklee if you're already mid-fix, ignore me — otherwise here's what I found digging into this:
The burn isn't a stuck task, it's the status-bar spinner itself.
packages/tui/src/component/prompt/index.tsxrenders<spinner interval={40} />wheneverstatus().type !== "idle", and each tick firesrequestRender()(opentui-spinner's_advanceFrame), which makes the opentui renderer re-render the entire scene graph. So a one-cell spinner drives 25 full-frame renders/sec, and each frame costs more than its 40ms budget on a long timeline — consistent with the ~15fpswritevcadence and the CPU sitting between writes in the strace above.It also keeps running while the timeline is static (long tool run, retry backoff), which matches the "no visible active output" observation.
I have a small fix ready (one file, ~20 lines in the prompt component): throttle the spinner to 400ms when no
message.updated/message.part.*event has landed for 1.5s, keeping 100ms while streaming. Happy to open a PR against this issue — or if you'd rather keep it, the diagnosis is yours to use.thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊