# Exec

Submit a new job to an existing cluster without re-provisioning.

## Run command

```bash
ml exec my-cluster 'python train.py'
```

## Run from YAML

```bash
ml exec my-cluster task.yaml
```

## Interactive shell

```bash
ml exec my-cluster
```

Opens interactive shell on head node.

## Options

| Flag | Description |
|------|-------------|
| `--detach-run, -d` | Don't stream logs |
| `--down` | Terminate cluster after job |

## Multi-node clusters

Command runs on head node by default. Use task YAML for distributed execution.

## Job queue

Each exec creates a job. View with:

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

## When to use exec vs launch

| Scenario | Command |
|----------|---------|
| Only `run` commands changed | `ml exec my-cluster task.yaml` (faster) |
| Setup, file_mounts, or resources changed | `ml launch -c my-cluster task.yaml` |

### What exec skips

`ml exec` is faster because it skips:
- Provisioning checks
- Setup commands
- File mounts syncing

It only syncs `workdir` and runs the `run` commands.

### Iterative development workflow

```bash
# Check for existing clusters first
ml status

# If cluster exists and is UP: reuse it
ml exec my-cluster task.yaml

# If no cluster or setup changed: launch
ml launch -c my-cluster task.yaml
```

