Skip to content

feat(cli): logs list/tail work against a remote/separate daemon#82

Merged
steve-krisjanovs merged 1 commit into
mainfrom
feat/remote-logs
Jul 1, 2026
Merged

feat(cli): logs list/tail work against a remote/separate daemon#82
steve-krisjanovs merged 1 commit into
mainfrom
feat/remote-logs

Conversation

@steve-krisjanovs

Copy link
Copy Markdown
Contributor

Summary

The last open finding from the multi-pass sweep: llmux logs list/logs tail in local mode read an in-process ring buffer that's empty in a fresh CLI invocation whenever the daemon runs as a separate process (the normal deployment). A code comment claimed remote tailing already worked via an SSE client — it didn't; that client was never built.

  • --server <url> now actually works for both verbs, using the backend's existing (already auth-gated) GET /api/logs and GET /api/logs/stream.
  • Local mode, when the buffer is empty: detects a separately-running daemon via a /health probe and points at --server instead of printing nothing or (for tail) hanging forever waiting for entries that can't arrive.

Test plan

  • npm run typecheck / npm run build clean
  • Local logs list/logs tail with an empty buffer + daemon running separately → correct hint; tail exits immediately instead of hanging
  • logs list --server ... --token ... → real entries from the daemon's actual buffer
  • logs tail --server ...: printed buffered entries, then a live-triggered log line streamed through correctly (verified the trigger request was a true no-op — same overlay file, unchanged content, before/after)
  • Cleaned up all test tokens

🤖 Generated with Claude Code

https://claude.ai/code/session_01Au8T9RPCb6wbgiEecQrBfZ

`llmux logs list`/`logs tail` (local mode) read log-buffer.ts's in-process
ring buffer — populated only by console.* calls made within the SAME
process. Since a fresh CLI invocation is always a separate process from
an already-running daemon (the normal deployment shape), these commands
silently showed nothing against a live daemon, with zero indication why.
The existing code comment claiming "remote tailing goes through the SSE
client in client.ts" was aspirational — that client command never
existed.

Two parts:

1. `--server <url>` now actually works for `logs list`/`logs tail`,
   mirroring how every other noun already routes remote calls. The
   backend already had everything needed: GET /api/logs (one-shot) and
   GET /api/logs/stream (SSE) were implemented and auth-gated but had no
   CLI client. Added `logs`/`logstail` ClientCommands: `logs list` does a
   plain authenticated GET; `logs tail` prints the buffered entries then
   opens a hand-rolled SSE reader (not EventSource — same reason the WS
   client is hand-rolled: EventSource can't set the Authorization header
   this endpoint requires).

2. Local mode, when the buffer is empty: a quick /health probe on the
   configured port detects whether a daemon is already running
   separately, and if so, points at the now-working --server path instead
   of printing nothing (`logs list`) or hanging forever waiting for
   entries that structurally cannot arrive (`logs tail` — now exits
   immediately with the same pointer instead of hanging).

## Verification

typecheck + build clean. Live against the running daemon:
- local `logs list`/`logs tail` (buffer empty, daemon running separately)
  -> correct hint, `tail` exits immediately instead of hanging
- `logs list --server ... --token ...` -> real startup-banner entries
  from the daemon's actual buffer
- `logs tail --server ... --token ...`: printed the buffered entries,
  then an intentionally-triggered request (idempotent no-op write to
  /api/settings/init-prompts, verified beforehand + after that it didn't
  change the on-disk overlay) produced a real live log line that
  streamed through correctly
- cleaned up all test tokens created during verification

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Au8T9RPCb6wbgiEecQrBfZ
@steve-krisjanovs steve-krisjanovs merged commit 57238b7 into main Jul 1, 2026
1 check passed
@steve-krisjanovs steve-krisjanovs deleted the feat/remote-logs branch July 1, 2026 16:09
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