---
description: Every MatMelt command and flag, rendered from the real application, plus the shared options and exit-code conventions.
---

# Command-line reference

The command listing further down this page is **rendered from the real Typer
application when the site is built**, so it is the same text `matmelt --help`
prints on your machine. It cannot fall behind the code.

What surrounds it — the shared options, the exit-code conventions, and which
commands write — is stated here once rather than repeated in nine help strings.

## The commands at a glance

| Command | Does | Writes to your workspace |
|---|---|---|
| `init` | Scaffold `matmelt.yaml`, then diagnose the environment against it | the config file |
| `doctor` | Report backend health, per-stage dependencies, enumeration size | no |
| `run` | Execute the funnel until it drains | yes — the state DB and item dirs |
| `status` | Per-state tally, failures, in-flight jobs; `--state` lists ids | no |
| `monitor` | Live dashboard over a run in progress or finished | no |
| `results` | List finished materials, `--export` their records as JSON | only with `--export` |
| `retry` | Reset `FAILED` materials so a later run re-runs them | yes — with `--yes` |
| `cif` | Export CIFs of DFTB+ relaxed structures from the calculate stage | writes the export directory |
| `update` | Upgrade MatMelt in place, from the spec `install.sh` recorded | no (changes the install) |

Four commands open the state database **read-only** — `status`, `monitor`,
`results` and `cif` — which is enforced by SQLite's `query_only` pragma rather
than by convention. Watching or exporting from a run cannot disturb it.

## Shared options

`--version` and `--help` belong to the `matmelt` command itself; `--help` also
works on every subcommand.

Every command **except `update`** takes the same config option:

| Flag | Default | Description |
|---|---|---|
| `--config PATH`, `-c PATH` | `matmelt.yaml` | The YAML file the command reads |

`update` takes none: it reads the spec recorded at install time, not your
project's config.

(which-file-config-resolves-to)=

### Which file `--config` resolves to

When you do not pass `--config`, the command looks for `matmelt.yaml` in the
current directory. If that file does not exist and a **`materials-cli.yaml`**
does, the legacy file is read instead and a deprecation note is printed on
**stderr** — so `--json` output on stdout stays parseable, and a workspace
created before the rename keeps working with no migration.

An explicit `--config` is never redirected: if you name a file, that is the file
that is read, or the command fails.

## Exit codes

The same three codes mean the same three things everywhere:

| Code | Meaning |
|---|---|
| `0` | Success. |
| `1` | The command refused, or found problems. |
| `2` | Config error, or invalid flag usage. |

Two consequences are worth stating outright, because they are what people get
wrong when scripting MatMelt:

**Science failures are results, not process failures.** A `run` in which
materials were screened out — even all of them — exits `0`. The verdicts are
data; the run did its job. Likewise `status` exits `0` while listing failures.
Exit `1` means MatMelt could not do what you asked: unmet dependencies, an
unreachable backend, no run state yet, a refusal to overwrite, a failed export.

**Exit `2` is always your file or your flags**, never the science: unparseable
YAML, an unknown key, a broken cross-reference (each reported with its dotted
YAML path), or a usage conflict such as `--only` together with
`pipeline.stop_after`, an unknown `--state`, or an empty `--materials`
selection.

```console
$ matmelt doctor --json > report.json    # 0 = ready, 1 = problems found
$ matmelt run --yes                      # 0 even if every material fails screening
```

## Full command listing

```{typer} matmelt.cli:app
:prog: matmelt
:show-nested:
:make-sections:
:width: 88
:preferred: text
```
