# Tasks, Clusters, and Jobs

Three concepts to understand how `ml launch` and `ml exec` work together.

## Task

A **task** is the YAML spec — what to run and what resources it needs.

```yaml
# task.yaml
resources:
  accelerators: B200:8
run: python train.py
```

A task is a *definition*, not something running.

## Cluster

A **cluster** is the provisioned compute environment where tasks run. Named with `-c`:

```bash
ml launch task.yaml -c my-cluster
```

A cluster persists after the task finishes. You manage it with `ml status`, `ml stop`, `ml down`, and `ssh`.

## Job

A **job** is a running instance of a task on a cluster. Each time you submit a task, it becomes a numbered job in the cluster's queue.

```bash
ml queue my-cluster
```

```
JOB_ID  STATUS     COMMAND
1       SUCCEEDED  python train.py
2       RUNNING    python eval.py
```

## How they relate

| Command | What it does |
|---------|--------------|
| `ml launch task.yaml -c my-cluster` | Creates cluster + submits job 1 |
| `ml exec my-cluster task.yaml` | Submits a new job to existing cluster (no re-provisioning) |
| `ml queue my-cluster` | Lists all jobs on the cluster |
| `ml cancel my-cluster JOB_ID` | Cancels a specific job |
| `ml down my-cluster` | Tears down the cluster and all its jobs |

`ml launch` does two things at once: provisions the cluster and submits the first job. After that, use `ml exec` to submit more jobs to the same cluster without re-provisioning.
