# Project configuration

A `.c3` YAML file at the root of your project describes the job. Run `c3 deploy` from that folder or any folder below it. `c3 init` writes a starter file.

```
project: my-experiment
script: run.sh
hardware: l40
time: "04:00:00"

python:
  project: ./

datasets:
  - ref: /datasets/imagenet
    mount: /data/imagenet

output:
  - ./checkpoints
  - ./results
```

## Fields[​](#fields "Direct link to Fields")

| Field                         | Required | Description                                                                                                                                   |
| ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `script`                      | yes      | Bash script to run, relative to `.c3`                                                                                                         |
| `project`                     | no       | Name, lowercase letters, digits and hyphens. Generated by `c3 init`                                                                           |
| `hardware`                    | no       | A class (`l40`, `a100`, `h100`) or an exact profile. Omit to let C3 choose. See [Hardware](https://docs.cthree.cloud/hardware.md)             |
| `time`                        | no       | Maximum runtime as `"HH:MM:SS"`. Default one hour. You pay only for time used                                                                 |
| `job_name`                    | no       | Display name in `c3 squeue` and the dashboard                                                                                                 |
| `python.project`              | no       | Directory with `pyproject.toml` and `uv.lock`. See [Environments](https://docs.cthree.cloud/environments.md)                                  |
| `docker.image`                | no       | Public Docker Hub or `ghcr.io` image. Cannot be combined with `python`                                                                        |
| `docker.requires_accelerator` | no       | `cuda` or `none`. C3 refuses a mismatched machine before the script runs                                                                      |
| `datasets`                    | no       | List of `ref` and optional `mount`. See [Datasets](https://docs.cthree.cloud/datasets.md)                                                     |
| `output`                      | no       | Directories to collect as results. See [Artifacts](https://docs.cthree.cloud/artifacts.md)                                                    |
| `provider`                    | no       | Pin a provider such as `nebius`. Omit to auto-route                                                                                           |
| `regions`                     | no       | Allowlist of provider region IDs. Omit for any region                                                                                         |
| `capacity.on_unavailable`     | no       | `wait` (default) or `fail` when the provider has no stock. See [Hardware](https://docs.cthree.cloud/hardware.md#when-capacity-is-unavailable) |
| `capacity.max_wait_minutes`   | no       | How long to wait for stock, 1 to 360. Default 60                                                                                              |
| `ignore_file`                 | no       | Ignore rules file to use instead of `.c3ignore`                                                                                               |
| `api_key`                     | no       | Local credential. Stripped from the uploaded copy. See [Authentication](https://docs.cthree.cloud/authentication.md)                          |
| `gpu`                         | no       | Older alias for `hardware`. Do not set both                                                                                                   |

Comments are allowed: `#` at the start of a line or after a value. Quote values that contain `#`.

## What gets uploaded[​](#what-gets-uploaded "Direct link to What gets uploaded")

`c3 deploy` uploads the regular files under the folder containing `.c3`. It always skips `.git/`, `node_modules/`, Python virtual environments and caches, compiled Python files, shared libraries, symlinks and OS metadata. Everything else is included, including `.env` files, lock files and any data you have left in the folder.

Every file is hashed on every deploy and only new content is transferred, so code is cheap to redeploy. Large inputs are not: keep them out of the project folder and upload them once as a [dataset](https://docs.cthree.cloud/datasets.md#workspace-or-dataset) instead.

Preview the selection without uploading or signing in:

```
c3 deploy --list-files
c3 deploy --list-files --json     # {"files":[".c3","run.sh","src/train.py"]}
```

### Exclude files[​](#exclude-files "Direct link to Exclude files")

Add a `.c3ignore` next to `.c3`. It uses `.gitignore` syntax:

```
.env
.env.*
!.env.example
results/
scratch/
```

To reuse your `.gitignore` instead:

```
ignore_file: .gitignore
```

To combine both, keep `.c3ignore` and import:

```
#!include:.gitignore
scratch/
```

Rules: `*.log` matches at any depth, `/local.txt` only at the root, `results/` matches directories, `!pattern` re-includes, last match wins. Built-in exclusions cannot be undone. Excluding the `script` is an error. Ignore rules affect only the workspace upload, not datasets or results.

## Machine-readable output[​](#machine-readable-output "Direct link to Machine-readable output")

`c3 deploy --json` prints one JSON object to stdout after submission and nothing else. It cannot be combined with `-f`.

| Field                               | Meaning                               |
| ----------------------------------- | ------------------------------------- |
| `id`                                | Job ID                                |
| `status`                            | Initial state, normally `PENDING`     |
| `provider`, `region`                | Selected route, `null` until assigned |
| `hardware_profile`                  | Exact profile selected, when known    |
| `hardware_kind`, `accelerator_kind` | `gpu` or `cpu`; `cuda` or `none`      |
| `dashboard_url`                     | Job page in the dashboard             |
| `pull_command`                      | The `c3 pull` command for this job    |

`c3 squeue --json` returns the same jobs as the table, as an array with lifecycle timestamps, route and the latest attempt's machine ID.

## Migrating a Slurm script[​](#migrating-a-slurm-script "Direct link to Migrating a Slurm script")

`c3 deploy job.sbatch` still works and reads `#SBATCH --time` and `--job-name`. Convert it once with `c3 migrate job.sbatch`, which writes the equivalent `.c3`.

## Deploy telemetry[​](#deploy-telemetry "Direct link to Deploy telemetry")

Each `c3 deploy` sends a short operational summary to C3: timings, outcome, selected route and aggregate file counts. No file names, contents or paths. See [Telemetry and privacy](https://docs.cthree.cloud/telemetry.md).
