---
description: Pause a run at a stage, interrupt it safely, cap it to a few passes, and continue later — without losing work or resubmitting jobs.
---

# Stop a run and continue it later

Every way of stopping MatMelt is resumable, because state lives on disk and
every submitted job is recorded before it is polled. This page covers the four
ways you will actually use.

## Interrupt it: Ctrl-C

Press Ctrl-C. The run stops after the current pass and tells you what it did:

```text
pass 1: submitted=2

Interrupted -- state and in-flight jobs are saved; re-run the same command to
resume where it left off.
```

Exit code `0` — an interrupted run is not a failed run. Jobs already submitted
**keep running**; they are OS processes (or cluster jobs), not children of the
command you just stopped.

## Cap it: `--max-passes`

To do a bounded amount of work — a smoke test, or a slot on a shared machine —
cap the number of orchestrator passes:

```console
$ matmelt run --only screen --materials Cl1Na1_3D-16,Cl1Na1_3D-25 --max-passes 3 --yes
```

```text
pass 1: submitted=2
  Materials by state
┏━━━━━━━━━━━━┳━━━━━━━┓
┃ State      ┃ Count ┃
┡━━━━━━━━━━━━╇━━━━━━━┩
│ SCREENED   │     2 │
│ STRUCTURED │    32 │
└────────────┴───────┘
--only screen: paused with work still pending -- re-run the same command to
continue.
```

The wording is precise: **paused with work still pending**, not finished.

## Resume: run the same command again

`status` shows what is still in flight after a pause:

```console
$ matmelt status
```

```text
In flight: 2 job(s)
  screen on laptop: Cl1Na1_3D-16
  screen on laptop: Cl1Na1_3D-25
```

Re-running the same command re-attaches to those jobs instead of starting new
ones:

```console
$ matmelt run --only screen --materials Cl1Na1_3D-16,Cl1Na1_3D-25 --yes
```

```text
pass 1: completed=2
```

`completed=2` with no `submitted` — both relaxations had continued while no
MatMelt process was running, and the new process collected them. This took six
seconds where the original submission took forty: the work was not repeated.

That is what the in-flight ledger buys. A job's handle — a PID, or a scheduler
job id — is written down at the moment of submission, so any later process can
poll it. Kill the tool mid-run and nothing on the compute plane is orphaned or
duplicated.

## Pause the funnel at a stage: `stop_after`

To generate candidates now and screen them next week, stop the funnel partway:

```yaml
pipeline:
  stop_after: structure
```

```text
pass 8: expanded=1, children=37
  Materials by state
┏━━━━━━━━━━━━┳━━━━━━━┓
┃ State      ┃ Count ┃
┡━━━━━━━━━━━━╇━━━━━━━┩
│ EXPANDED   │     2 │
│ STRUCTURED │    37 │
└────────────┴───────┘
stop_after structure: stage drained; materials rest at its output, ready for the
next stage -- raise or remove stop_after (or use --only) to continue them.
```

The 37 candidates **rest** at `STRUCTURED`: live, claimable, and waiting. To
continue them later, raise `stop_after`, remove it, or run one stage on demand.
Nothing needs re-generating.

:::{important}
Resting depends on there being a stage after the stop. `stop_after` naming the
**last stage you configured** is not a pause — the run went through the whole
funnel it was given, so those materials retire as `DONE`. If you configure only
`compose` and `structure` and set `stop_after: structure`, you get 37 `DONE`
materials, not 37 resting ones.
:::

## Run exactly one stage: `--only`

```console
$ matmelt run --only screen --yes
```

`--only` runs one stage over whatever is already waiting for it, and stops:

```text
--only screen: seeding skipped -- this run consumes materials already waiting
for the screen stage.
...
--only screen: stage drained; downstream stages were not run.
```

Two behaviours worth knowing. Seeding is skipped unless the stage is `compose`,
because fresh seeds nothing consumes would spin the loop forever. And a
mid-funnel `--only` never retires materials as `DONE` — later stages still have
work to do on them.

`--only` and `stop_after` are mutually exclusive, and saying so is the whole
error:

```text
run: --only and pipeline.stop_after are mutually exclusive -- remove stop_after
from the config or drop --only.
```

Exit `2`. Remove `stop_after` from the config, or drop the flag.

## Restrict to chosen materials: `--materials`

Any run — full, `--only`, or capped — can be narrowed to named materials **and
their descendants**:

```console
$ matmelt run --materials Cl1Na1_3D-6,Cl1Na1_3D-10 --yes
$ matmelt run --materials-file picked.txt --yes
```

```text
--materials: the selected materials are settled; unselected materials were not
run.
```

Get the ids from `matmelt status --state <STATE>`. Descendants are included by
lineage, so naming a fan-out parent reaches everything it produced.

## Related

- {doc}`../reference/states` — resting states, terminal states, and what
  finalizes a material.
- {doc}`diagnose-a-failure` — when a pause is really a stall.
- {doc}`../tutorials/t4-monitor` — watching a long run while it drains.
