> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuneplane.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Cluster Status

> Cluster overview.

Jobs in flight come from the ledger rather than the backend: the ledger is the only
place holding project_key, project and owner, which is exactly what the list has to
show and link to.



## OpenAPI

````yaml /api-reference/openapi.json get /api/cluster/status
openapi: 3.1.0
info:
  title: TunePlane Console
  description: >-
    The TunePlane control plane. Everything the `tuneplane` CLI and the web
    console do goes through this API, and so can your own tooling.


    Authenticate with a bearer token from `POST /api/auth/login` or a CLI device
    flow; see the Authentication page for how to get one and how long it lasts.
  version: 0.3.42
servers:
  - url: https://{host}
    description: Your TunePlane deployment
    variables:
      host:
        default: tuneplane.your-company.com
        description: >-
          The domain your administrator gave you, without a scheme or trailing
          slash.
security: []
tags:
  - name: auth
    description: >-
      Log in, exchange a CLI device code, and inspect the current identity.
      Everything else on this API needs a bearer token from here.
  - name: profile
    description: >-
      The signed-in user's own account: quota, tokens, preferences, and
      notification settings.
  - name: projects
    description: >-
      Projects group runs the way `tuneplane.yaml` names them. A run belongs to
      exactly one.
  - name: experiments
    description: >-
      Read the experiment definitions the console found in the configured
      repository.
  - name: submit
    description: >-
      Admit a JobSpec. This is what `tp submit` calls: the catalog handshake,
      quota check, and preflight all happen here, and a rejection names the gate
      that refused it.
  - name: jobs
    description: >-
      Everything about a job after it is admitted: status, logs, metrics,
      samples, artifacts, and the pause/resume/stop controls.
  - name: runs
    description: >-
      Finished work, addressed by run id. A run outlives the job that produced
      it.
  - name: ingest
    description: >-
      The endpoints training code reports to. `tuneplane.report` speaks this;
      you only call it directly when writing an adapter for a framework the
      catalog does not cover.
  - name: datasets
    description: >-
      Versioned dataset upload, listing, and metadata. Protected datasets expose
      identity and schema here but never their records.
  - name: volumes
    description: Governed directories of files a job may mount read-only.
  - name: environments
    description: >-
      Agent RL environments: their manifests, versions, and upload URLs. A
      taskset is never returned.
  - name: benchmarks
    description: >-
      The benchmark catalog, the score matrix across runs, and externally scored
      evaluations.
  - name: rubrics
    description: >-
      Written scoring standards, their revisions, and which runs cited which
      version.
  - name: judge
    description: >-
      The LLM-judge endpoint a training job calls to score a rollout.
      OpenAI-compatible.
  - name: models
    description: >-
      The model registry: register a version, promote it, archive it, read its
      card.
  - name: model-deployments
    description: >-
      Managed model versions serving application traffic: revisions, promotion,
      rollback, suspension, and deployment tokens.
  - name: inference
    description: >-
      OpenAI-compatible inference against a promoted deployment revision. This
      is the endpoint applications call.
  - name: playground
    description: >-
      Short-lived serving sessions for human evaluation. Distinct from a
      deployment: a session expires, a deployment does not.
  - name: reflow
    description: >-
      The governed path from a deployment's production traffic back to the
      training data of its next version.
  - name: annotate
    description: 'Preference annotation: pull a batch, push judgements, read progress.'
  - name: plugins
    description: Installed plugins and the extension shelf the console renders.
  - name: diagnosis
    description: >-
      Automated analysis of a finished or failed run, and the accumulated
      project memory it draws on.
  - name: approvals
    description: 'Approval requests: an escalation path, one level deep, with a record.'
  - name: billing
    description: >-
      What the GPU-hours cost. One price on top of the hours the usage page
      already shows.
  - name: teams
    description: 'Teams: the unit capacity is budgeted to. A department, not a tenant.'
  - name: agent
    description: >-
      Submit plans: a proposed submission a human approves or rejects before it
      becomes a job.
  - name: share
    description: >-
      Public, revocable read-only links to a job or a comparison. The
      `/api/share/{token}` routes need no bearer token, which is the point.
  - name: notifications
    description: The signed-in user's notification feed.
  - name: search
    description: Cross-surface search over jobs, runs, datasets, and models.
  - name: sandbox
    description: >-
      Execute model-generated code in a throwaway container with no GPU and no
      network.
  - name: uploads
    description: >-
      Resumable upload sessions used by dataset, environment, and plugin
      publishing.
  - name: integrations-hf
    description: Hugging Face account linking and repository push.
  - name: mcp
    description: Model Context Protocol access information and per-user tool settings.
  - name: mcp-oauth
    description: >-
      OAuth metadata, authorization, token exchange, and dynamic client
      registration for MCP clients.
  - name: cluster
    description: Live capacity and node state across the fleets.
  - name: fleets
    description: >-
      Registered execution backends and the machines in them. Reading is open to
      every user; creating a fleet, minting a join token and draining a node are
      admin-only. Joining is authorized by the join token alone.
  - name: admin
    description: >-
      User, role, quota, hardware, schedule, integration, and settings
      administration. Admin role required.
  - name: tasks
    description: >-
      Scheduled platform maintenance tasks: what they are, when they last ran,
      and running one now.
  - name: report
    description: The rendered daily report page.
  - name: health
    description: Liveness and version. Unauthenticated.
paths:
  /api/cluster/status:
    get:
      tags:
        - cluster
      summary: Cluster Status
      description: >-
        Cluster overview.


        Jobs in flight come from the ledger rather than the backend: the ledger
        is the only

        place holding project_key, project and owner, which is exactly what the
        list has to

        show and link to.
      operationId: cluster_status_api_cluster_status_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClusterStatusOut'
      security:
        - HTTPBearer: []
components:
  schemas:
    ClusterStatusOut:
      properties:
        gpu:
          anyOf:
            - $ref: '#/components/schemas/GpuSummaryOut'
            - type: 'null'
        storage:
          anyOf:
            - $ref: '#/components/schemas/StorageSummaryOut'
            - type: 'null'
        active_jobs:
          items:
            $ref: '#/components/schemas/JobRowOut'
          type: array
          title: Active Jobs
          default: []
        active_count:
          type: integer
          title: Active Count
          default: 0
        profiles:
          items:
            $ref: '#/components/schemas/ClusterProfileOut'
          type: array
          title: Profiles
          default: []
      type: object
      title: ClusterStatusOut
    GpuSummaryOut:
      properties:
        total:
          type: integer
          title: Total
          default: 0
        used:
          type: integer
          title: Used
          default: 0
        free:
          type: integer
          title: Free
          default: 0
        blocked:
          type: integer
          title: Blocked
          default: 0
        queued:
          type: integer
          title: Queued
          default: 0
        blocked_reason:
          type: string
          title: Blocked Reason
          default: ''
        blocked_notes:
          items:
            $ref: '#/components/schemas/GpuBlockNoteOut'
          type: array
          title: Blocked Notes
          default: []
        series:
          items:
            $ref: '#/components/schemas/GpuSeriesOut'
          type: array
          title: Series
          default: []
      type: object
      title: GpuSummaryOut
      description: >-
        Cluster GPU overview.


        ★ The four numbers satisfy **total = used + free + blocked**, from one

        source each: the executor says how many cards exist (only it knows the

        infrastructure), the ledger says how many are occupied -- counting only

        jobs that actually hold cards -- and whatever cannot be scheduled right
        now

        goes to `blocked` with a reason in plain words. No page should have to

        explain "why does it say free when I cannot submit".


        `queued` is the fifth number and sits outside that equation on purpose:
        a

        queued job is demand on the cluster, not a slice of it. Folding it into

        `used` is how the console once showed eight occupied cards on a box
        where

        the platform was running nothing at all.
    StorageSummaryOut:
      properties:
        measured:
          type: boolean
          title: Measured
          default: false
        stale:
          type: boolean
          title: Stale
          default: false
        measured_at:
          type: number
          title: Measured At
          default: 0
        total_bytes:
          type: integer
          title: Total Bytes
          default: 0
        free_bytes:
          type: integer
          title: Free Bytes
          default: 0
        used_bytes:
          type: integer
          title: Used Bytes
          default: 0
        runs_bytes:
          type: integer
          title: Runs Bytes
          default: 0
        cache_bytes:
          type: integer
          title: Cache Bytes
          default: 0
        watermark_pct:
          type: integer
          title: Watermark Pct
          default: 0
        root:
          type: string
          title: Root
          default: ''
      type: object
      title: StorageSummaryOut
      description: >-
        Platform storage overview (admin only).


        * The difference from the GPU summary matters and has to reach the page:
        GPU
          numbers are computed from the ledger and are exact when asked, while these
          are a **periodic measurement**. A training process writes to disk without
          telling the control plane, so the only way to know is to walk the tree.
          Hence measured_at / stale — the page must show when this was taken.
    JobRowOut:
      properties:
        id:
          type: string
          title: Id
        exp:
          type: string
          title: Exp
        project_key:
          type: string
          title: Project Key
          default: ''
        name:
          type: string
          title: Name
          default: ''
        project:
          type: string
          title: Project
          default: ''
        project_display_name:
          type: string
          title: Project Display Name
          default: ''
        status:
          type: string
          title: Status
        entrypoint:
          type: string
          title: Entrypoint
          default: ''
        start:
          type: string
          title: Start
        started_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Started At
        submitted_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Submitted At
        ended_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Ended At
        dur:
          type: string
          title: Dur
        running:
          type: boolean
          title: Running
        pending_action:
          type: string
          title: Pending Action
          default: ''
        run_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Run Id
        job_ref:
          anyOf:
            - type: string
            - type: 'null'
          title: Job Ref
        username:
          anyOf:
            - type: string
            - type: 'null'
          title: Username
        user_display_name:
          anyOf:
            - type: string
            - type: 'null'
          title: User Display Name
        recipe:
          type: string
          title: Recipe
          default: unversioned
        recipe_version:
          anyOf:
            - type: string
            - type: 'null'
          title: Recipe Version
        profile:
          anyOf:
            - type: string
            - type: 'null'
          title: Profile
        framework:
          anyOf:
            - type: string
            - type: 'null'
          title: Framework
        framework_version:
          anyOf:
            - type: string
            - type: 'null'
          title: Framework Version
        parent_run_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Parent Run Id
        step_role:
          type: string
          title: Step Role
          default: train
        pipeline_id:
          type: string
          title: Pipeline Id
          default: ''
        derived_from_run_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Derived From Run Id
        pipeline:
          anyOf:
            - $ref: '#/components/schemas/PipelineOut'
            - type: 'null'
        retry_count:
          type: integer
          title: Retry Count
          default: 0
        can_retry:
          type: boolean
          title: Can Retry
          default: false
        retry_blocker:
          type: string
          title: Retry Blocker
          default: ''
        can_rerun:
          type: boolean
          title: Can Rerun
          default: false
        rerun_blocker:
          type: string
          title: Rerun Blocker
          default: ''
        sweep_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Sweep Id
        tags:
          items:
            type: string
          type: array
          title: Tags
          default: []
        has_note:
          type: boolean
          title: Has Note
          default: false
      type: object
      required:
        - id
        - exp
        - status
        - start
        - dur
        - running
      title: JobRowOut
    ClusterProfileOut:
      properties:
        name:
          type: string
          title: Name
        label:
          type: string
          title: Label
          default: ''
        series:
          type: string
          title: Series
          default: ''
        num_nodes:
          type: integer
          title: Num Nodes
          default: 1
        gpus_per_node:
          type: integer
          title: Gpus Per Node
          default: 1
      type: object
      required:
        - name
      title: ClusterProfileOut
      description: >-
        Profile summary, visible to every signed-in user.


        The CLI completes --profile from it and materialises `--profile
        <name>[:<cards>]`

        into JobSpec resource pools: the series and the default shape both come
        from here,

        so no client has to copy the topology by hand.
    GpuBlockNoteOut:
      properties:
        code:
          type: string
          title: Code
        series_label:
          type: string
          title: Series Label
          default: ''
        next_open_at:
          type: string
          title: Next Open At
          default: ''
      type: object
      required:
        - code
      title: GpuBlockNoteOut
      description: >-
        Why cards cannot be scheduled, as a code the console words itself.


        A code rather than a finished sentence, because the control plane owns
        the

        *fact* and the console owns how it is said. The sentence used to be
        composed

        here in one language and shipped straight to a bilingual console, so an

        English reader got `不在可用时段`; and the timestamp inside it was rendered  #
        i18n-allow: quoting the shipped zh sentence this replaces

        in the administrator's timezone, sitting next to a pill showing the same

        instant in the reader's own.


        What the **executor** reports stays a sentence --
        `GpuSummaryOut.blocked_reason`.

        Four backends compose it out of fleet ids, node names and card numbers,
        none

        of which is enumerable, and they live in a package that knows nothing
        about

        the console.
    GpuSeriesOut:
      properties:
        id:
          type: string
          title: Id
        label:
          type: string
          title: Label
        total:
          type: integer
          title: Total
          default: 0
        used:
          type: integer
          title: Used
          default: 0
        free:
          type: integer
          title: Free
          default: 0
        blocked:
          type: integer
          title: Blocked
          default: 0
        queued:
          type: integer
          title: Queued
          default: 0
        note:
          anyOf:
            - $ref: '#/components/schemas/GpuBlockNoteOut'
            - type: 'null'
      type: object
      required:
        - id
        - label
      title: GpuSeriesOut
      description: One series' capacity. Satisfies total = used + free + blocked.
    PipelineOut:
      properties:
        pipeline_id:
          type: string
          title: Pipeline Id
        state:
          type: string
          title: State
        steps:
          items:
            $ref: '#/components/schemas/PipelineStepOut'
          type: array
          title: Steps
          default: []
        verdict:
          type: string
          title: Verdict
          default: ''
        gpu_seconds:
          type: integer
          title: Gpu Seconds
          default: 0
      type: object
      required:
        - pipeline_id
        - state
      title: PipelineOut
      description: A submission and every step the platform ran on its behalf (ADR-0019).
    PipelineStepOut:
      properties:
        run_id:
          type: string
          title: Run Id
        job_ref:
          type: string
          title: Job Ref
          default: ''
        role:
          type: string
          title: Role
        status:
          type: string
          title: Status
          default: ''
        presence:
          type: string
          title: Presence
          default: ''
        depends_on:
          items:
            type: string
          type: array
          title: Depends On
          default: []
        started_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Started At
        ended_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Ended At
        gpu_seconds:
          type: integer
          title: Gpu Seconds
          default: 0
      type: object
      required:
        - run_id
        - role
      title: PipelineStepOut
      description: One job inside a Pipeline, as the strip renders it.
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````