StarSling
CLICommands

Analyzing CI

usage, top, time, why, and labels — attribute cost, rank hotspots, decompose wall-clock, and diagnose failures

View Markdown

Five commands that answer analytical questions rather than listing records. Each is a first-class product surface, not a dashboard export.

sling usage

sling usage [--org <slug> | --repo <owner/name>] [--group-by <axis>] [--order-by <col>]
            [--asc | --desc] [window] [--json | --agent]

Attributes StarSling runner minutes and dollar cost over a time window.

FlagMeaning
--org, --repoScope. --repo owner/name narrows to one repo; mutually exclusive. Defaults to your default org.
--group-bylabel (default) · workflow · job · repo · day
--order-bycost (default) · minutes · jobs · key
--asc / --descSort direction, default --desc. Naming both is a usage error. Not valid with --group-by day.
--window <n>dTrailing window, e.g. 30d. Defaults to 30 days.
--month <YYYY-MM>A calendar month.
--from / --toAn explicit half-open range [from, to). Both required together.
--json, --agentMachine mode.
sling usage --org mastra-ai --window 7d --group-by repo
StarSling usage — by repo
2026-07-07 → 2026-07-14

KEY                     RUNNER MIN    JOBS     COST $  % TOTAL
mastra-ai/mastra           25459.0   10784    $202.85    89.3%
mastra-ai/docs              3040.2    1120     $24.22    10.7%

The window flags are mutually exclusive — passing two is a usage error, not a silent precedence rule. A single-row result omits % TOTAL, since a lone row's share is always 100%. --group-by day renders a burn-down chart instead of a table.

Cost is minutes × vCPU × $0.002, where minutes are billed minutes — max(1, ceil(duration / 60s)) per job. A five-second job still costs a minute.

The plan block

Every response carries a top-level plan describing the caller's billing state, which shapes both the window and the human chrome on any --group-by axis:

FieldMeaning
statuspaid · free · blocked. Paid orgs get no bar or banner.
period_sourcestripe · install_cycle · calendar_month · explicit — labels the window.
free_minutes_limit / free_minutes_usedFree orgs only — the remaining lifetime grant, drawn as a bar.
blocked_reasonBlocked orgs only — why jobs will not dispatch, shown as a red banner.

Fields that do not apply are omitted, not null. Machine mode passes the whole block through verbatim.

Exit codes: 0 ok · 2 usage error · 4 not signed in · 5 control-plane failure. Calls GET /api/usage.

sling top

sling top [--by <axis>] [--metric <col>] [--asc | --desc] [--org | --repo]
          [-n <count>] [window] [--json | --agent]

Ranks what burns the most runner time and money — the hotspots worth optimizing. Groups the same facts as usage, but sorts by a chosen metric and adds a period-over-period trend so a regression stands out.

FlagMeaning
--byworkflow (default) · job · label · repo · branch
--metricrunner-minutes · cost · jobs · p95-duration · p99-duration · queue-wait
--asc / --descSort direction, default --desc.
--org, --repoScope; mutually exclusive.
-n, --limitRow count.
--json, --agentMachine mode — ranked rows plus a local block.
sling top --by workflow --metric cost --window 30d
sling top — by workflow · cost · last 30d

KEY · WORKFLOW   REPO           COST     TREND
Prebuild         acme/api    $528.35    ↑55.2%
Test             (multiple)  $203.11    ↓12.3%
Lint             acme/web     $44.90        —

(multiple) marks a key spanning several repos. TREND compares against the prior equal-length window, or shows when there is no prior data. Calls GET /api/top.

sling time

sling time <run|job|attempt id | URL>
sling time --repo <owner/name> [window]

Decomposes CI wall-clock into phases — so you can see whether time goes to infrastructure or to your workload. Polymorphic, with a different analysis at each level:

  • A job or attempt splits wall-clock into the phase enum, with a per-step breakdown inside steps.
  • A run adds DAG analysis: the critical path, parallelism efficiency (busy-runner-seconds ÷ wall-clock × width), and the blocking job — the single job whose speedup most reduces run wall-clock, so optimization effort lands where it pays.
  • --repo aggregates p50/p95 per phase, per runner label, over a window — answering whether a repo's time goes to queue, provisioning, cache, or actual work.
FlagMeaning
<id | URL>A run, job, or attempt id, or a pasted GitHub Actions URL.
--repo <owner/name>The repo aggregate instead of a single target.
--window, --month, --from / --toOnly with --repo. Passing one alongside an id is a usage error — a single target already names its window.
--json, --agentMachine mode.
sling time
Job Name: Lint, typecheck, test & spell · Wall-Clock: 58s · Queue-Wait: 2s

  PHASES                           TIME %-SHARE  TIMELINE
  provision                        4.0s   7.14%  ██░░░░░░░░░░░░░░░░░░░░░░
  checkout+patch                   2.0s   3.57%  ░░░░░░░░░░░░░░░░░░░░░░░
  steps                           46.0s  82.14%  ░░░███████████████████░░
    Set up Bun                     1.0s          ░░░░░░░░░░░░░░░░░░░░░░░
    Set up mise tools              2.0s          ░░░░░░░░░░░░░░░░░░░░░░░
    Install dependencies           1.0s          ░░░░░░░░░░░░░░░░░░░░░░░
    Lint (Biome)                   2.0s          ░░░░░░░░░░░░░░░░░░░░░░░
    Lint shell (shellcheck)       14.0s          ░░░░░██████░░░░░░░░░░░░░
    Lint Dockerfiles (hadolint)    0.0s          ░░░░░░░░░░░░░░░░░░░░░░░
  ▸ Typecheck                     18.0s          ░░░░░░░░░░░████████░░░░░
    Test                           7.0s          ░░░░░░░░░░░░░░░░░░░███░░
    Catalog drift                  1.0s          ░░░░░░░░░░░░░░░░░░░░░░
    Spell (typos)                  0.0s          ░░░░░░░░░░░░░░░░░░░░░░
  teardown                         4.0s   7.14%  ░░░░░░░░░░░░░░░░░░░░░░██

Top Steps

  STEP                       TIME
  Typecheck                 18.0s
  Lint shell (shellcheck)   14.0s
  Test                       7.0s
  Set up mise tools          2.0s
  Lint (Biome)               2.0s

The TIMELINE column places each phase and step on the job's wall-clock, so you can see what ran when and what overlapped — not just what was slow. marks the single largest contributor. Top Steps then ranks the steps outright, which is the list to optimize from: here Typecheck and Lint shell are 32 of the 46 seconds inside steps.

Phases come from a frozen vocabulary shared by the runner hooks and the facts store: queue_wait, provision, image_pull, cache_restore, checkout+patch, steps, cache_save, teardown. Only the phases with time recorded against them are shown. Percentages are share of phase time, so they sum across the phase rows — the nested steps are a breakdown of steps, not extra rows in that sum.

Exit codes: as elsewhere, plus 6 for partial — telemetry was incomplete, and the body is still emitted. Calls GET /api/time.

sling why

sling why <run | job | attempt id | URL> [--json | --agent]

A server-authored diagnosis — why a CI job failed, so an agent can fix the failure instead of re-deriving it from logs. It is read straight from the facts store: the last failing step, a bounded ##[error] window, and run context. No LLM sits in the request path, so the same job always classifies the same way. A run id diagnoses that run's most-diagnosable job.

Every diagnosis carries a classification, evidence references, suggested actions with ready-to-run commands, and an agent-ready remediation prompt.

Classifications: step_failure · hang · oom · timeout · cancelled · terminated · infra · network_egress · unknown.

On a cancelled target, why identifies the canceller — a user, a concurrency group, or a merge-queue flush — so an external cancellation is not misdiagnosed as a code failure.

sling why job_88886665361
JobID: 88886665361 · JobName: test (3)
Failure Reason: The step 8 "Test" step failed (exit code 101).

Evidence
  Classification: step_failure
  Phase: step 8 "Test"
  Logs:
    ##[error]Process completed with exit code 101

Suggestions:
  1. Verify the logs
     sling logs 88886665361 --grep '##\[error\]'

Every diagnosis carries evidence, a suggested next step, and a ready-to-run prompt for a downstream agent. Calls GET /api/why.

sling labels list

sling labels list [--json | --agent]

The catalog of available runner labels and their specs, so runs-on mapping and cost hints reference concrete options instead of hardcoded names. The catalog is static and global — identical for every caller — so the usual --org, --repo, and window flags are accepted but inert. list is the only subcommand.

sling labels list
StarSling runner labels

LABEL                        CPU   MEM (GiB)  ARCH      $/MIN
starsling-ubuntu-24.04         4          16  x64      $0.008
starsling-ubuntu-24.04-2       2           8  x64      $0.004
starsling-ubuntu-24.04-8       8          32  x64      $0.016
starsling-ubuntu-24.04-16     16          64  x64      $0.032
starsling-ubuntu-24.04-32     32         128  x64      $0.064
starsling-ubuntu-24.04-64     64         256  x64      $0.128
FieldMeaning
labelThe runs-on runner label.
cpuvCPU count.
memory_gbRAM in GiB — a strict 4 GiB per vCPU.
archCPU architecture; x64 today.
price_per_min_usdPer-minute cost, cpu × $0.002 — the same rate usage and bill charge.

See Instance types for the same catalog in context. Calls GET /api/labels.

On this page