CLI & API

May 11, 2026 ยท View on GitHub

!!! info "Prerequisites" Ensure the server is up and running. To use dstack with AI agents, install skills.

The primary way to use dstack is the CLI. It can be used to manage fleets, dev environments, tasks, services, volumes, and gateways, view logs, and inspect events. Use the HTTP API for functionality not available in the CLI or for integrations that need to call the server directly.

CLI

See installation on how to install the CLI.

Configuration

The CLI requires a project configuration with the project name, server URL, and user token in ~/.dstack/config.yml.

projects:
  - name: main
    url: http://127.0.0.1:3000
    token: <user token>
    default: true
  - name: octocat
    url: https://sky.dstack.ai
    token: <user token>

Use dstack project to list, add, delete, and set the default project configurations. To run a command against a non-default project, pass --project NAME, or set DSTACK_PROJECT in the current shell.

??? info "Projects" Projects enable the isolation of different teams and their resources. Users can be added to projects and assigned roles. Each user has a user token for authentication.

Manage fleets

Before submitting runs, you must create at least one fleet. Fleets act as both pools of instances and templates for how those instances are provisioned.

Use dstack fleet to list existing fleets, their configurations, and instances (if any):

$ dstack fleet

??? info "Offers" Offers are available instance configurations that match resource requirements.

<div class="termy">

```shell
$ dstack offer --gpu H100 --max-offers 10
```

</div>

If no fleet is specified,
[`dstack offer`](../reference/cli/dstack/offer.md) shows offers from all
configured backends.

Use `--fleet NAME` to restrict offers to a fleet. Listing offers does not
create capacity.

Define a fleet configuration in a YAML file. The filename must end with .dstack.yml, for example fleet.dstack.yml:

type: fleet
name: default

nodes: 0..1
idle_duration: 1h

resources:
  gpu: 0

Pass the fleet configuration to dstack apply:

$ dstack apply -f fleet.dstack.yml

If the nodes range starts with 0, dstack creates a fleet template. Instances are provisioned when matching runs are submitted.

Submit runs

To submit a run, define a dev environment, task, or service configuration. The example below submits a task.

type: task
name: hello

commands:
  - echo hello world

Submit the run:

$ dstack apply -f .dstack.yml

!!! info "Plan and confirmation" dstack apply shows the plan and asks for confirmation before submitting the run. To only see the plan, answer n at the prompt:

<div class="termy">

```shell
$ echo "n" | dstack apply -f .dstack.yml
```

</div>

Use `-y` to skip confirmation.

!!! info "Attached by default" For run configurations, dstack apply automatically attaches after submitting the run. This configures SSH access, forwards declared ports, and streams logs. See Attach to runs.

Use `-d` to submit in detached mode.

Attach to runs

If the run was submitted with -d, or if you need to attach to another job in a multi-job run, use dstack attach:

$ dstack attach &lt;run name&gt;

!!! info "SSH" During dstack apply in attached mode and during dstack attach <run name>, the CLI downloads the current user's built-in private SSH key if needed and stores it under ~/.dstack/ssh/.

While attached, the CLI updates `~/.dstack/ssh/config` and ensures this file
is included from `~/.ssh/config`. The file contains a `Host <run name>`
alias used by `ssh <run name>` to SSH into the run container:

<div editor-title="~/.dstack/ssh/config">

```ssh-config
Host <run name>
    HostName <host>
    Port <ssh port>
    User <user>
    IdentityFile <private user SSH key>
    IdentitiesOnly yes
```

</div>

> For [VM-based backends](../concepts/backends.md#vm-based) and
> [SSH fleets](../concepts/fleets.md), `dstack` may add an additional alias
> `<run name>-host` and use it as a proxy jump for `ssh <run name>`.

While attached, connect to the run with:

<div class="termy">

```shell
$ ssh &lt;run name&gt;
```

</div>

Use --job JOB_NUMBER with dstack attach to attach to another job. Ports declared in the run configuration are forwarded while attached.

??? info "User SSH keys" The server stores a built-in SSH key pair for each user.

Users can add custom public SSH keys via the UI or the
[users](../reference/http/users.md) API. To use a custom private key for a
particular run, pass `--ssh-identity` to `dstack apply` or `dstack attach`.

Browse logs

When dstack apply is attached, it streams logs for job 0 automatically. Use dstack logs to view logs in detached mode, or to view logs for a specific job:

$ dstack logs &lt;run name&gt;

Use --job JOB_NUMBER to select a job and --since to filter by time.

??? info "Attached logs" Use --logs with dstack attach to stream logs while attaching:

<div class="termy">

```shell
$ dstack attach &lt;run name&gt; --logs
```

</div>

Commands

Other common CLI commands include dstack ps, dstack stop, and dstack event.

!!! info "Verbose and JSON modes" Use -v for more details where supported. For automation, use --json, e.g. dstack ps --json, dstack run get <run name> --json, or dstack fleet get <fleet name> --json.

API

The dstack API is represented by the HTTP API. Use it for functionality not available in the CLI or for integrations that need to call the server directly.

Authenticate

The HTTP API requires the Authorization header for user authentication:

Authorization: Bearer <user token>

Manage fleets

The fleets API can list existing fleets, their configurations, and instances (if any):

$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/fleets/list" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{"include_imported": true}'

??? info "Offers" To check available offers via the HTTP API, call /runs/get_plan with the same lightweight task specification used by dstack offer:

<div class="termy">

```shell
$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/runs/get_plan" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{
      "run_spec": {
        "configuration": {
          "type": "task",
          "commands": [":"],
          "image": "scratch",
          "user": "root",
          "resources": {
            "gpu": 0
          }
        }
      },
      "max_offers": 5
    }'
```

</div>

If `fleets` is not set in the run configuration, offers are returned from
all configured backends. Use `"fleets": ["default"]` to restrict offers to
a fleet.

To group offers by GPU and other fields, use the
[gpus](../reference/http/gpus.md) API.

Creating fleets uses /fleets/get_plan followed by /fleets/apply:

$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/fleets/get_plan" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{
      "spec": {
        "configuration": {
          "type": "fleet",
          "name": "cpu-fleet",
          "nodes": "0..1",
          "idle_duration": "1h",
          "resources": {
            "gpu": 0
          }
        },
        "profile": {}
      }
    }'

Then apply the fleet plan:

$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/fleets/apply" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{
      "plan": {
        "spec": {
          "configuration": {
            "type": "fleet",
            "name": "cpu-fleet",
            "nodes": "0..1",
            "idle_duration": "1h",
            "resources": {
              "gpu": 0
            }
          },
          "profile": {}
        }
      },
      "force": false
    }'

Submit runs

Use the runs API to submit dev environments, tasks, and services. The example below submits a task:

$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/runs/apply" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{
      "plan": {
        "run_spec": {
          "run_name": "hello-api",
          "configuration": {
            "type": "task",
            "commands": ["echo hello world"]
          }
        }
      },
      "force": false
    }'

Set run_name if a stable run name is needed. Otherwise, the server can generate a run name.

Poll /runs/get to check the run status:

$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/runs/get" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{"run_name": "hello-api"}'

Poll logs

Use the logs API to poll logs. Get job_submission_id from /runs/get, e.g. from latest_job_submission.id.

$ curl "&lt;server URL&gt;/api/project/&lt;project name&gt;/logs/poll" \
    -X POST \
    -H "Authorization: Bearer &lt;user token&gt;" \
    -H 'Content-Type: application/json' \
    -d '{
      "run_name": "hello-api",
      "job_submission_id": "&lt;job submission id&gt;",
      "limit": 100
    }'

Use next_token from the response to continue polling.

Reference

For complete details on specific CLI commands and HTTP APIs, see the dstack server and server references.

!!! info "OpenAPI" For complete information on the HTTP API, or to generate native clients, refer to openapi.json.

!!! info "What's next?" 1. Follow the installation guide 2. Read about projects 3. Check fleets, dev environments, tasks, and services