Skip to content

feat(board): live-stream stdout/stderr in the logs pane during a press#149

Merged
bobakemamian merged 1 commit into
mainfrom
feat/board-live-stream
Apr 20, 2026
Merged

feat(board): live-stream stdout/stderr in the logs pane during a press#149
bobakemamian merged 1 commit into
mainfrom
feat/board-live-stream

Conversation

@bobakemamian
Copy link
Copy Markdown
Contributor

Answers "how do I press a button and follow the logs at the same time" inside the board — the natural home.

Before: pressing a button from the board ran silently. The logs pane only showed past run summaries. No way to watch output as it happened.

Now:

  • Press any button → logs pane auto-opens → stdout/stderr lines appear with timestamps as they arrive
  • stderr lines in red, stdout in primary, `● live` badge in the header
  • When the press finishes, the badge flips to `· done` and the lines stay so you can scroll the just-completed output
  • Capped at 200 lines per button so runaway scripts can't OOM the TUI
  • Buffer resets on the next press of the same button

How it works

runPress now passes a LineSink channel into engine.Execute (the existing streaming hook). A Bubble Tea pub/sub loop (`readFromSink` Cmd) emits one liveLineMsg per line; the Update handler appends to m.liveLines and re-schedules. The channel is closed by runPress after Execute returns, which terminates the loop via liveStreamDoneMsg.

No engine changes — LineSink was already there for this exact purpose.

Test plan

  • `go build ./...`, `go vet ./...`, `go test ./...` all green
  • Smoke tested in real TUI: pressed a multi-second button, lines streamed in as expected, badge flipped on done

🤖 Generated with Claude Code

Before: pressing a button from the board executed it silently —
the logs pane only showed PAST run summaries, not the current
press's output as it happened.

Now: when a press fires, the board
1. creates a LineSink channel and passes it into engine.Execute
2. auto-opens the logs pane so the live feed is visible
3. reads lines via a readFromSink tea.Cmd pub/sub loop
4. renders the last ~8 lines in the pane with stderr in red,
   stdout in primary, timestamps muted, a "● live" badge in the
   header flipping to "· done" when the stream closes

Lines are capped at 200 per button so runaway scripts don't OOM
the TUI; the tail is always freshest. The live buffer survives
past press completion so the user can see what just ran — it's
reset to empty only on the next press of that same button.

runPress now accepts (and closes) the sink channel. Execute's
existing LineSink interface did all the heavy lifting — this is
a consumer, not a new engine feature.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bobakemamian bobakemamian merged commit d3abe4a into main Apr 20, 2026
16 checks passed
@bobakemamian bobakemamian deleted the feat/board-live-stream branch April 27, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant