Docs
Search docs

List the caller's own runners

GET/api/user/runners

listMyRunners

Every personal (actor-bound) runner the caller registered, in any workspace, plus every runner in the caller's personal workspace — newest first, at most 500. `workspace_slug` names each runner's workspace. Needs `user:read` and no resource lock; each row is then decided like the workspace list.

Requires authentication using a bearer token or a session cookie — see tokens and scopes.

curl

curl -X GET 'https://neosource.dev/api/user/runners' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN'

fetch

fetch("https://neosource.dev/api/user/runners", {
  method: "GET",
  headers: {
    Authorization: "Bearer $NEOSOURCE_TOKEN",
  },
});

Responses

200The caller's runners

application/json

RunnerListResponse

object

runnersrequired

array

items

RunnerSummaryResponse

object

One runner in a listing (`GET /api/workspaces/{workspace_id}/runners`, `GET /api/user/runners`). Never carries a token. Which runners a caller sees, and `can_deregister`, are per-runner policy decisions: a workspace admin sees every runner bound to the workspace; a plain member sees the workspace-bound ones read-only plus their own actor-bound ones.

actor_handle

string | null

Handle of `actor_id`, when it still resolves.

actor_id

string | null

Owning account of an actor-bound runner; `null` when workspace-bound.

bindingrequired
RunnerBindingKind
busyrequired

boolean

Holds a job lease right now.

can_deregisterrequired

boolean

Whether the caller may deregister this runner (`DELETE /api/workspaces/{workspace_id}/runners/{runner_id}`).

created_atrequired

integerint64

enrollment_id

string | null

The runner enrollment this runner was registered through (ADR 0153); absent for one registered with a user credential.

ephemeralrequired

boolean

Session runner (`neo push --runner`): removed when its push ends.

idrequired

string

labelsrequired

array

items

string

last_seenrequired

integerint64

machinerequired
RunnerMachineInfo
machine_reported_at

integer | nullint64

When `machine` was last reported (epoch ms); `null` = never.

name

string | null

Display name the agent reported; `null` for an agent that never did.

node_id

string | null

The machine identity it registered with, within that enrollment; `neo runner enroll revoke --node <node_id>` removes it.

statusrequired
RunnerStatus
vm_backendrequired
VmBackendKind
workspace_id

string | null

workspace_slug

string | null

Slug of `workspace_id`; set on `GET /api/user/runners`, which spans workspaces, and `null` on the per-workspace list.

403Forbidden — one of: forbidden, needs_scope

application/json

one of
  • ErrorForbidden
  • NeedsScopeError

    object

    `403` body returned when a classic OAuth token is asked for something its granted scopes do not cover — an explicit private listing without `repo`, or the one-click GitHub mirror without `admin:public_key`. `scope` names the missing grant so the client can say exactly what the token lacks. There is no elevation route to widen it any more (a re-link goes through the GitHub App, whose tokens carry no scopes), so the client's answer is to say so, never to start a handshake.

    errorrequired

    string

    Always `needs_scope` — this body exists to carry the extra fields that kind needs.

    "needs_scope"

    scoperequired

    string

    The provider scope to request via elevation (e.g. `"repo"`).

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 401Authentication required
  • 404Not Found — one of: not_found
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget

Schemas

Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.

RunnerBindingKind

string

Which trust binding a job executed under (ADR 0056 §1/§7). Serialized on the wire and in `workflow_run_jobs.executed_on` as the `snake_case` strings `hosted` / `workspace` / `actor`.

"hosted""workspace""actor"

RunnerMachineInfo

object

What a runner agent reports about the machine it runs on (issue #777): `POST /api/runners` (`machine`) and `PUT /api/runners/{runner_id}/machine`. Every field is optional. A value of the wrong JSON type (a string for `cpu_cores`, a negative `memory_bytes`) fails request extraction like any other malformed body; a well-typed value is never rejected for its content — strings are trimmed, stripped of control and invisible formatting characters and truncated, and counts are clamped — since this is untrusted tenant-hardware input.

agent_version

string | null

Agent build that reported, e.g. `neo 0.1.0 (abc1234)`.

arch

string | null

CPU architecture as Rust's `std::env::consts::ARCH` spells it (`x86_64`, `aarch64`, …). Open vocabulary — render, don't match.

cpu_cores

integer | nullint32

Logical CPUs available to the agent.

cpu_model

string | null

CPU model string, e.g. `AMD Ryzen 9 7950X 16-Core Processor`.

memory_bytes

integer | nullint64

Total physical memory in bytes.

name

string | null

Display name shown in the web UI and `neo runner list`. Defaults to the machine's hostname agent-side. On a report, `null` keeps the name already stored.

os

string | null

Operating system as Rust's `std::env::consts::OS` spells it (`linux`, `macos`, `windows`, …). Open vocabulary — render, don't match.

RunnerStatus

string

"online""draining""offline"

VmBackendKind

string

"docker_shell""kata_clh""kata_fc""lib_krun""k8s_runc""cloud_hypervisor"