# Inspecting CI (/sling-cli/commands/inspect)



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`

```text
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. |

```console
$ 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`](/api/resolve/resolve-target).

## `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`

```text
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.                    |

```console
$ 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:58
```

Calls [`GET /api/runs`](/api/runs/list-runs).

### `sling runs show`

```text
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.                                                                         |

```console
$ sling runs show run_2990884649 --wait; echo $?
…run concludes…
10   # a non-success conclusion under --wait
```

<Callout type="info">
  `--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](/sling-cli/configuration#exit-codes).
</Callout>

**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}`](/api/runs/get-run).

## `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`

```text
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. |

```console
$ 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 2
```

A terminal job shows its **conclusion**; an in-flight one shows its **status**. Calls [`GET /api/jobs`](/api/jobs/list-jobs) and [`GET /api/jobs/{id}`](/api/jobs/get-job).

## `sling logs`

```text
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. |

```console
$ 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}`](/api/logs/get-logs).
