stackbone logs

stackbone logs targets a running agent installation. With no --agent it runs against the local-dev installation linked to the current project, so stackbone dev must be running. See target resolution. This is a stream: --json prints one envelope per log line.

Live-tail the targeted installation's logs over a server-sent stream.

Command Purpose
stackbone logs tail Stream log lines. Server-side filters: --run <id>, --level <info|warn|error…>, --q <text>, --trace-id <id>. Client-side: --since, --until, --limit, --follow.

The stream opens with the lines the box still holds in memory, then goes live, so a tail started after the fact still shows what just happened. That buffer is bounded: a line old enough to have rolled out of it never reaches the tail.

The server applies --level, --q and --trace-id. The CLI applies --since and --until (a duration like 15m/2h or an ISO timestamp) and --limit (default 100) locally as lines arrive: this stream has no server-side time range or pagination. Without --follow the tail stops once --limit lines have printed; with --follow it streams until you hit Ctrl-C.

--level sets a minimum severity. The server keeps every record whose level is at or above the one you name, so --level warn keeps warn and error, while --level error keeps error alone. The six names are trace, debug, info, warn, error and fatal. The box refuses any other value before the stream opens, so a misspelt level fails instead of tailing everything.

logs tail does not paginate. It takes no --cursor, and no page cursor comes back, so the pagination contract the list verbs follow does not apply here. --limit caps how many lines one tail prints.

Scope the tail to a single run with --run <id> to read only that run's lifecycle: the same id you see in stackbone runs list. An id the box holds no lines for is not an error, so a typo reads as an empty stream. A failed run also carries its own error object (a message, plus a stack when the runtime captured one) on the run record, so read stackbone runs get <id> for why it failed.

Human mode prints four fields per line: the ISO timestamp, the level name, the run id (- for a line emitted outside any run), then the message.

JSON payload: one envelope per line (not a paged list). The payload is the log record itself, Pino-shaped. It carries the run, the step it came from (inside a workflow step), and a source naming where the box read it:

{
  "schema_version": 1,
  "level": 30,
  "time": 1717236000000,
  "msg": "agent booted",
  "stream": "stdout",
  "run_id": null,
  "source": { "run_id": "-", "path": "<agent:stdout>" },
}

level is the Pino number (10 trace … 60 fatal). run_id is null for a line emitted outside any run, such as a boot line or a lifecycle event. A line from inside a workflow step also carries trace_id (the run's trace) and step_id.

Exit codes: 0 ok (including a clean Ctrl-C stop) · 3 no target (no project and no --agent, or stackbone dev is not running) · 4 not found (a targeted box with no registered deployment) · 1 generic (an invalid --limit/--since, or a --level the box refuses). Full table: Conventions → exit codes.

BUILT WITH ❤️ FROM CANADA AND SPAIN