stellaops findings runtime — CLI Reference
Audience: developers and operators who ingest runtime trace observations and read the resulting runtime score, aggregates, and timeline for a finding from the command line.
The stellaops findings runtime command group binds the Findings Ledger runtime instrumentation endpoints to the CLI. Use it to push runtime trace observations into the ledger and to query the per-finding runtime score, per-function aggregates, and event timeline. For the wire-level request/response contracts, see the runtime instrumentation API reference.
Source:
src/Cli/StellaOps.Cli/Commands/FindingsRuntime/.
Overview
stellaops findings runtime traces ingest --finding-id <guid> --trace-file <path>
stellaops findings runtime traces list --finding-id <guid> [--limit N] [--sort-by hits|recent]
stellaops findings runtime score get --finding-id <guid>
stellaops findings runtime timeline range --finding-id <guid> [--from] [--to] [--bucket-hours N]
All commands accept these shared flags:
| Flag | Description |
|---|---|
--tenant | Tenant context (overrides the saved profile from ~/.stellaops/profile.json). |
--output | Output format. human (default) is a human-readable table; json is the raw response. |
--verbose | Verbose logging. |
Tenant resolution
Tenant context resolves in this order:
--tenant <id>(CLI flag)- Active tenant in
~/.stellaops/profile.json(set viastellaops tenants use ...)
The resolved tenant is sent as X-StellaOps-TenantId on every request.
Authentication & scopes
The client attaches the configured CLI bearer token (ApiKey from StellaOpsCliOptions) as Authorization: Bearer <token> when one is present; if no token is configured the request is sent unauthenticated and the server will reject it. The Findings.Ledger WebService gates these endpoints with two scope policies (see Program.cs and the canonical scope catalog StellaOpsScopes.cs):
| Command(s) | Required scope |
|---|---|
traces list, score get, timeline range | findings:read |
traces ingest | findings:write |
A token missing the required scope yields 403 Forbidden (exit code 4). A read-only token is rejected by the write policy on ingest.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success (200 OK or 202 Accepted) |
| 2 | A required option resolved to an empty value (ingest only; e.g. --trace-file "") |
| 4 | Server returned 4xx (auth, validation, not-found) |
| 5 | Server returned 5xx |
| 8 | Trace file could not be read, or a generic (non-4xx/5xx) non-2xx response |
These codes are intended for CI / automation pipelines.
Notes (source:
FindingsRuntimeCommandGroup.cs,FindingsRuntimeRenderer.RenderError,CliExitCodes.cs):
--finding-idand--trace-fileare declaredRequiredon every subcommand, so a truly absent flag is rejected by the System.CommandLine parser before a handler runs (parser exit code, conventionally1). Code2(MissingRequiredOption) is only emitted by theingesthandler when--trace-fileis present but blank.- A failure reading the trace file (missing path, I/O error, or stdin error) returns code
8(GeneralError) — there is no dedicated file-not-found code on this path.- The
4/5/8split is computed from the HTTP status byRenderError:4xx → 4,5xx → 5, any other non-2xx →8.
Commands
findings runtime traces ingest
POST a runtime trace observation to the ledger. The body is read from --trace-file (a JSON document) or, if --trace-file - is passed, from stdin.
stellaops findings runtime traces ingest \
--finding-id 00000000-0000-0000-0000-000000000001 \
--trace-file ./trace.json \
--tenant tenant-a
Trace file shape (matches the ingest endpoint contract):
{
"capturedAt": "2026-04-28T12:34:56Z",
"artifactDigest": "sha256:abc...",
"componentPurl": "pkg:npm/lodash@4.17.21",
"frames": [
{"symbol": "main", "isEntryPoint": true},
{"symbol": "lodash.merge", "isVulnerableFunction": true}
]
}
Optional trace fields: containerName and metadata
The trace JSON may include containerName (string) and metadata (string→string map). Both are persisted to the trace record since sprint 026 and surface on subsequent traces list output, sourced from the most recent persisted trace for the (tenant, finding). See v1 → v2 history in the API reference for the full contract and migration notes.
Successful response: 202 Accepted. Human output prints a === Trace ingested === block listing each response field (findingId, observationId, recordedAt, artifactDigest, componentPurl, frameCount, privacyFilterApplied); --output json emits the raw body.
findings runtime traces list
GET the per-function aggregates for a finding.
stellaops findings runtime traces list \
--finding-id 00000000-0000-0000-0000-000000000001 \
--limit 25 --sort-by recent
Renders a table with FUNCTION, HITS, DIRECT, FIRST SEEN, LAST SEEN columns plus a summary header. The summary header surfaces Total hits, Unique paths, Posture, Container count, and Last hit (each printed only when present in the response). --output json emits the full response body verbatim.
--sort-by accepts hits (default) or recent; the CLI rejects any other value at parse time (AcceptOnlyFromAmong). --limit defaults to 50 and is clamped to [1, 200] server-side.
A 404 NotFound is returned (and exit code 4) when no aggregates exist — this is the correct “no data” state, not an error condition.
findings runtime score get
GET the current runtime score with breakdown.
stellaops findings runtime score get \
--finding-id 00000000-0000-0000-0000-000000000001
Human output renders the display score as 0..100 and includes the raw wire value in parentheses, for example 78.00/100 (wire: 0.78). --output json emits the raw response where score.score is 0..1. The command also renders the computedAt timestamp and per-component breakdown (observationScore, recencyFactor, qualityFactor).
findings runtime timeline range
GET chronological events in a [from, to] window.
stellaops findings runtime timeline range \
--finding-id 00000000-0000-0000-0000-000000000001 \
--from 2026-04-27T00:00:00Z \
--to 2026-04-28T00:00:00Z \
--bucket-hours 4
Defaults: to = now, from = to - 24h, bucket-hours = 1. The server clamps bucket-hours to [1, 168] and rejects a window where from > to with 400 Bad Request (exit code 4). Human output prints the resolved From / To / BucketHours header, then a table of TIMESTAMP, KIND, CORRELATION-ID columns; --output json emits the raw response.
Wire note: the timeline route is
GET /api/v1/findings/{id}/runtime-timeline(a dash, not aruntime/timelinepath segment), unlike thetracesandscoreroutes which nest underruntime/.
Sample script
#!/usr/bin/env bash
set -euo pipefail
FID="00000000-0000-0000-0000-000000000001"
# 1. Ingest a synthetic trace.
stellaops findings runtime traces ingest \
--finding-id "$FID" --trace-file ./trace.json
# 2. Query the score.
stellaops findings runtime score get --finding-id "$FID"
# 3. List aggregates.
stellaops findings runtime traces list \
--finding-id "$FID" --sort-by hits --limit 5
