What to build
Extend shipnode logs from a one-shot PM2 tail into a proper live-debugging tool that covers every log source shipnode already sets up on the server.
New flags:
-f, --follow — stream logs continuously until Ctrl-C
--source pm2|caddy|system|all — pick the log source (default: pm2, current behavior); all multiplexes them into a single stream with a per-line prefix like [pm2] / [caddy] / [system]
--grep <pattern> — server-side filter (piped through grep on the remote so we don't drag the full stream over SSH)
--lines n — keeps working, backfills the last n lines before entering follow mode
Sources map to concrete remote commands:
pm2 → pm2 logs <app> --lines n [--raw]
caddy → tail Caddy access + error logs (paths taken from the eject template so they stay in sync)
system → journalctl -u <unit> -n n [-f]
all → run each subcommand and interleave stdout with a source prefix
Acceptance criteria
Blocked by
None - can start immediately
What to build
Extend
shipnode logsfrom a one-shot PM2 tail into a proper live-debugging tool that covers every log source shipnode already sets up on the server.New flags:
-f, --follow— stream logs continuously until Ctrl-C--source pm2|caddy|system|all— pick the log source (default:pm2, current behavior);allmultiplexes them into a single stream with a per-line prefix like[pm2]/[caddy]/[system]--grep <pattern>— server-side filter (piped throughgrepon the remote so we don't drag the full stream over SSH)--lines n— keeps working, backfills the last n lines before entering follow modeSources map to concrete remote commands:
pm2→pm2 logs <app> --lines n [--raw]caddy→ tail Caddy access + error logs (paths taken from the eject template so they stay in sync)system→journalctl -u <unit> -n n [-f]all→ run each subcommand and interleave stdout with a source prefixAcceptance criteria
shipnode logs -fstreams new lines until interrupted, then exits cleanly (SSH channel closed, no orphan remote process)shipnode logs --source caddyreturns non-empty output on a server that has been serving trafficshipnode logs --source all -fshows interleaved lines with a[source]prefixshipnode logs --grep 500filters on the remote (verify withset -xthat grep runs there, not locally)--lines nstill works, and combines with-f(backfill then follow)tail/pm2 logs/journalctl -fprocess on the serverBlocked by
None - can start immediately