feat(logs): log streaming + Bubble Tea dashboard cockpit (spec 16) - #101
Merged
Conversation
Implements spec 16's read-only observation surface:
- `logs [service...]`: multiplexes container logs across the workspace's
project + shared stacks via the read-only Engine SDK, filtered on the
tool-owned label + an optional per-service filter (shared alias, bare
engine, service, or project name). Flags --follow/-f, --tail, --since,
--timestamps, --no-color, and a --json {ts,service,project,stream,
container,line} line contract. TTY gets a color-keyed gutter; a pipe gets
plain lines. Non-follow exits at EOF; -f is signal-aware for clean teardown.
- docker.Client gains ContainerLogStream: a demuxed (stdcopy for non-TTY,
raw for TTY), optionally-following/timestamped line channel with bounded
fan-in backpressure; TTY-ness learned via inspect; unreadable logging
drivers surface a one-liner. Mirrored in MockClient (Streams seam).
- `dashboard`: a Bubble Tea v2 cockpit (bubbles/v2 table + lipgloss/v2)
showing shared + project services with state/health + refs + URL and a
log tail pane, keybindings (q/esc/ctrl+c quit, r refresh), 2s safety poll.
Non-TTY / --json / --quiet refuses the TUI and prints a one-shot snapshot
reusing the shared-status + per-project projections.
Removes the logs + dashboard stubs. Tests: log stream demux/emitter/ctx,
target label-filter resolution, --json line shape, multiplex over the mock,
dashboard model Update/View transitions, and the non-TTY snapshot path. No
real daemon required.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
Implements spec 16 — the read-only log-aggregation + live TUI cockpit.
logs [service...]The non-interactive sibling. Multiplexes container logs across the workspace's project + shared stacks via the read-only Engine SDK, filtered on devstack's own
LabelManagedplus an optional per-service filter (matches shared DNS alias, bare engine, service, or owning project). Flags:--follow/-f,--tail,--since,--timestamps,--no-color, and a--jsonline contract{ts,service,project,stream,container,line}. A TTY gets the color-keyedservice │gutter; a pipe gets plain lines;--jsonimplies no color. Non-follow exits at EOF;-fwires a signal-aware context so Ctrl-C tears every SDK stream down cleanly.internal/dockerstreamingClientgainsContainerLogStream(ctx, id, LogOptions) (<-chan LogLine, error):stdcopy.StdCopy(stdout/stderr split + tagged); TTY streams read raw. TTY-ness is learned viaContainerInspect(.Config.Tty, now surfaced onContainerDetails).LogLine.TS.none/syslog) return a one-line remediation, not a stack trace.MockClientvia aStreamsseam so everything is testable without a daemon.dashboardA Bubble Tea v2 cockpit (
bubbles/v2table +lipgloss/v2) over the read-only client + ledger: shared instances (with ref counts + referencing projects) and per-project services with live state/health, a detail pane, and a log-tail pane. Keybindingsq/esc/ctrl+cquit,rrefreshes; a 2s safety poll keeps it live. It refuses to launch on a non-TTY (or under--json/--quiet) and instead prints a one-shot snapshot reusing thestatusshared + per-project projections (--jsonemits the machine-readable form).Removes only the
logs+dashboardstub lines fromstubs.go.Why
Spec 16: makes the shared-services graph directly observable. Pure observation over what v1 already produces — strictly read-only, no daemon, lock-free.
How tested
CGO_ENABLED=0 go build ./...,CGO_ENABLED=1 go test -race ./internal/...,gofmt -l(clean),go vet ./...(clean). New table-driven tests cover: the line emitter (split/buffer/flush/ctx-cancel), timestamp split, target label-filter resolution, the--jsonline shape, a full multiplex over the mock, the unreadable-driver notice, and the dashboard model'sUpdate/Viewtransitions + the non-TTY snapshot path. Also smoke-tested end-to-end against a live daemon (JSON + plain +--timestampsstreaming, and the piped-dashboard snapshot).🤖 Generated with Claude Code