Inspecting CI
resolve, runs, jobs, and logs — find a run, walk its jobs and attempts, and read only the log lines that matter
Four commands for navigating what actually ran. They share one primitive — polymorphic id resolution — so all of them accept a prefixed id, a bare number, or a pasted GitHub Actions URL.
Identifiers
| Form | Meaning |
|---|---|
run_<id> | One workflow run. |
job_<id> | One job within a run. |
att_<job_id>.<n> | One execution of a job. Retries create new attempts; earlier ones are preserved. |
runner_<id> | The GitHub Actions runner a job ran on. |
Bare GitHub ids and GitHub Actions UI URLs are accepted anywhere a run, job, or attempt id is — so you can paste a URL straight from the browser without translating identifiers.
Resolution is polymorphic: an id resolves downward to the most specific sensible target. Where several candidates match, the command lists them and exits 2 — it never picks silently, so you are never handed the wrong target.
sling resolve
sling resolve <id | GitHub Actions URL> [--target run|job|attempt]Resolves a polymorphic id to its concrete target. This is the primitive the id-taking commands share, exposed on its own so you can see what an id maps to.
| Flag | Meaning |
|---|---|
--target run|job|attempt | Bias resolution to one level when the id is ambiguous. |
--json, --agent | Machine output — the resolved target, or { candidates } on ambiguity. |
sling resolve run_2990884649
run_2990884649 (run)
acme/api
# ambiguous → candidates (exit 2)
sling resolve 88886665361
Ambiguous — 2 candidates; pass one:
run_88886665361 (acme/api)
job_88886665361 typecheck (acme/api)Exit codes: 0 resolved · 2 usage or ambiguous · 3 not found · 4 not signed in · 5 control-plane failure. Calls POST /api/resolve.
sling runs
Inspect workflow runs. list (alias ls) pages newest-first with server-side filters; show (alias get) renders one run and can block until it concludes.
sling runs list
sling runs list [filters] [--limit n] [--cursor c]| Flag | Meaning |
|---|---|
--branch, --status, --conclusion, --trigger, --workflow-path, --label | Server-side filters; combine freely. |
--window, --month, --from / --to | Time window. Mutually exclusive; passing two is a usage error. |
--limit, --cursor | Page size, and the cursor to page with. has_more prints the next --cursor. |
--json, --agent | Machine mode — { runs, has_more, next_cursor } on stdout. |
sling runs list --status in_progress --limit 3
RUN WORKFLOW BRANCH EVENT STATUS DUR JOBS CREATED
2990884649 Test main push in_progress — 4 2026-07-23 14:02
2990884101 Prebuild main push queued — 1 2026-07-23 13:58Calls GET /api/runs.
sling runs show
sling runs show <run id | URL> [--wait [--fail-fast] [--wait-timeout 30m]]| Flag | Meaning |
|---|---|
--wait | Poll until the run reaches a terminal state, then exit 0 on success or 10 on any non-success conclusion. |
--fail-fast | With --wait, return as soon as a job fails instead of waiting for the rest. |
--wait-timeout <dur> | Cap the wait, e.g. 30m. |
--json, --agent | Machine mode — the run detail on stdout. |
sling runs show run_2990884649 --wait; echo $?
…run concludes…
10 # a non-success conclusion under --wait--wait is what lets a script or agent gate on a run. Exit 10 is not an error — the command worked and the run failed. See exit codes.
Exit codes: 0 ok · 2 usage · 3 not found · 4 not signed in · 5 control-plane failure · 10 run concluded non-success under --wait. Calls GET /api/runs/{id}.
sling jobs
Inspect workflow jobs. list is scoped to one run (--run) or one repo (--repo plus a window) — exactly one is required. show renders one job; passing a run id is a usage error that redirects you to runs show.
sling jobs list
sling jobs list --run <id> | --repo <owner/name> [--conclusion c] [window]| Flag | Meaning |
|---|---|
--run <id> | --repo <owner/name> | The scope. Mutually exclusive; one is required. |
--conclusion | Filter by conclusion — failure, success, and so on. |
--window, --month, --from / --to | Time window, with --repo. |
--limit, --cursor | Pagination. |
--json, --agent | Machine mode — { jobs, has_more, next_cursor } on stdout. |
sling jobs list --run 2990884649 --conclusion failure
JOB NAME STATUS LABEL ATTEMPTS DURATION RUN CREATED
88886665361 typecheck failure starsling-ubuntu-24.04 1 2.4m 2990884649 2026-07-23 14:02
sling jobs show run_2990884649
That id is a run, not a job — try `sling runs show`. # exit 2A terminal job shows its conclusion; an in-flight one shows its status. Calls GET /api/jobs and GET /api/jobs/{id}.
sling logs
sling logs <run|job|attempt id | URL> [--job <name>] [--grep <re>] [--since <dur>]
[--timestamps] [--limit <n>] [--cursor <c>] [--output-file <path>]Reads a run, job, or attempt's logs filtered server-side — so you fetch the failing lines, not the whole transcript.
| Flag | Meaning |
|---|---|
--job <name> | For a run target, restrict to one job leg. |
--grep <re> | Server-side regex filter, e.g. --grep '##\[error\]'. |
--since <dur> | Only lines newer than a trailing duration. |
--timestamps | Prefix each line with its timestamp. |
--limit <n> | Maximum lines per page. |
--cursor <c> | Resume from a next_cursor. |
--output-file <path> | Write to a file instead of stdout. |
--json, --agent | Emit a JSON page — { lines, has_more, next_cursor } — instead of raw lines. |
sling logs job_88886665361 --grep '##\[error\]'
##[error]Process completed with exit code 101.Unusually for sling, this command writes to stdout in both modes: the human path streams raw lines and auto-follows pages to the end. That makes | head and | less work naturally — closing the pipe early exits cleanly.
Exit codes: 0 ok · 2 usage · 3 not found · 4 not signed in · 5 control-plane failure. Calls GET /api/logs/{id}.