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
Audio.start should support silent failure without writing ALSA diagnostics to stderr #1358
Audio.start() writes a large ALSA diagnostics block directly to the host process stderr when Linux has libasound2 but no playback device. The method then correctly returns false and emits a structured error event, but TUI hosts cannot prevent the native stderr from overwriting their terminal UI.
Please add an explicit silent startup option, such as Audio.start({ silent: true }) or an equivalent setup option. Silent mode should suppress native backend diagnostics while preserving the existing false result and structured error event.
each start() call emits another 35-line ALSA diagnostics block for default, dmix, dmix:0, and dmix:0,0
Representative output:
ALSA lib confmisc.c:767:(parse_card) cannot find card '0'
ALSA lib conf.c:4568:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory
...
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM dmix:0,0
AUDIO_ERROR start -5 Audio start failed: -5
Expected behavior
A host application should be able to opt into silent audio initialization so an unavailable optional playback device does not corrupt a terminal UI. Failure should remain observable through the return value and error event.
Additional context
OpenCode currently mitigates repeated output by disabling attention audio for the remainder of the TUI lifecycle after the first failed startup: anomalyco/opencode#41770. That bounds the output to one diagnostics block but cannot suppress the first native block without support at this boundary.
Same root cause from another direction, in case it helps scope this: hosts can't contain JavaScript-level writes either, not just native ones.
Verified against @opentui/core 0.5.3 (and 0.4.5, which opencode pins):
consoleMode: "console-overlay" monkey-patches global.console, so console.*is contained.
process.stdout.write / process.stderr.write are not. externalOutputMode only ever swaps stdout.write (renderer.ts:1262, :1790), and its one capturing value is rejected outside screenMode: "split-footer" (renderer.ts:367).
stderr never appears as a process.stderr hook in core — only the synthetic CapturedWritableStream used to build the replacement Console, plus an internal capture-buffer type label.
So any dependency logging via process.stderr.write paints over the alternate screen. In opencode that surfaces as a plugin logger destroying the TUI frame (anomalyco/opencode#43064); we're working around it host-side by patching both wrappers for the renderer's lifetime (anomalyco/opencode#43065).
A host-level containment option covering both JS and native writes would subsume the Audio.start({ silent: true }) ask here.
Current main has two distinct containment gaps: the renderer can replace console.* and, in split-footer mode, stdout.write, but it does not contain process.stderr.write; native ALSA diagnostics also write directly to fd 2, beyond a JavaScript stream wrapper.
Could a maintainer choose the intended scope here?
A narrow Audio.start({ silent: true })-style option implemented at the native audio backend/log-callback boundary, suppressing expected initialization diagnostics, or
Renderer-level stdout/stderr containment for alternate-screen applications, which would need to cover both JavaScript streams and native fd writes and is a substantially broader behavior change.
If the narrow route is preferred, it would also help to specify whether silent suppresses only backend initialization diagnostics or every native audio log. The two designs have different public APIs and cannot be safely inferred from the current issue discussion.
Activity
spiatrenka commentedon Aug 17, 2026
Same root cause from another direction, in case it helps scope this: hosts can't contain JavaScript-level writes either, not just native ones.
Verified against
@opentui/core0.5.3 (and 0.4.5, which opencode pins):consoleMode: "console-overlay"monkey-patchesglobal.console, soconsole.*is contained.process.stdout.write/process.stderr.writeare not.externalOutputModeonly ever swapsstdout.write(renderer.ts:1262,:1790), and its one capturing value is rejected outsidescreenMode: "split-footer"(renderer.ts:367).stderrnever appears as aprocess.stderrhook in core — only the syntheticCapturedWritableStreamused to build the replacementConsole, plus an internal capture-buffer type label.So any dependency logging via
process.stderr.writepaints over the alternate screen. In opencode that surfaces as a plugin logger destroying the TUI frame (anomalyco/opencode#43064); we're working around it host-side by patching both wrappers for the renderer's lifetime (anomalyco/opencode#43065).A host-level containment option covering both JS and native writes would subsume the
Audio.start({ silent: true })ask here.dajiaohuang commentedon Aug 18, 2026
Current
mainhas two distinct containment gaps: the renderer can replaceconsole.*and, in split-footer mode,stdout.write, but it does not containprocess.stderr.write; native ALSA diagnostics also write directly to fd 2, beyond a JavaScript stream wrapper.Could a maintainer choose the intended scope here?
Audio.start({ silent: true })-style option implemented at the native audio backend/log-callback boundary, suppressing expected initialization diagnostics, orIf the narrow route is preferred, it would also help to specify whether
silentsuppresses only backend initialization diagnostics or every native audio log. The two designs have different public APIs and cannot be safely inferred from the current issue discussion.