> ## Documentation Index
> Fetch the complete documentation index at: https://sysg.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# migrate-state

# migrate-state

Move legacy `__loose__` state into per-manifest project directories.

A manifest that declares no `project:` is a *loose* manifest. Loose manifests
used to share a single project called `__loose__` — one directory, one slot. So
starting a second loose manifest looked to the supervisor like an edit of the
first: it reconciled the difference by stopping the service already running
there. Every loose manifest now owns a project derived from its own path, and
they coexist.

`migrate-state` places the state the old shared layout left behind.

```sh theme={null}
$ sysg migrate-state --dry-run
```

## Why it is a command and not automatic

The migration moves state and logs you cannot reconstruct, and the supervisor
loads state *before* it takes its lock — so a migration running at boot could be
observed half-finished by a second `sysg` invocation. Running it explicitly means
it happens once, with no supervisor alive, with the report in front of you.

It refuses with [`SG0602`](/how-it-works/dialog/codes#sg0602) while a supervisor
is running. `--dry-run` is always allowed.

## What it will not do

Legacy state records a *service name*. The new layout keys by *project*. When
several manifests declare the same service name, nothing in the old state says
which one owned it:

```sh theme={null}
Cannot be attributed (archived, not assigned):
  [service] gamecast-tunnel: declared by 3 manifests: ...
  [cron] de98291cbf657443: no manifest declares it
```

Those artifacts are archived and reported rather than assigned to a guess. The
archive is a faithful, checksum-verified copy, so nothing is lost — place them by
hand if you want them, or leave them.

## Options

| Short | Long            | Description                                                                          |
| ----- | --------------- | ------------------------------------------------------------------------------------ |
| `-`   | `--units <DIR>` | Directory of manifests to attribute state to (defaults to the state root's `units/`) |
| `-`   | `--dry-run`     | Report what would move without changing anything                                     |
| `-v`  | `--verbose`     | Print operation progress                                                             |
| `-`   | `--sys`         | Opt into privileged system mode. Requires running as root                            |
| `-`   | `--plain`       | Disable terminal decoration for automation                                           |
| `-`   | `--log-level`   | Set logging verbosity for this invocation                                            |

## Usage

Review first — this is the recommended path, since the report tells you exactly
what can and cannot be attributed:

```sh theme={null}
$ sysg migrate-state --dry-run
```

Then stop the supervisor and run it:

```sh theme={null}
$ sysg stop --supervisor
$ sysg migrate-state
```

## Safety

Nothing is deleted. Every source is copied into a timestamped archive beside the
state root and checksum-verified before the migration proceeds, and the legacy
`projects/__loose__/` tree is left in place. A run records its progress in a
journal, so an interrupted migration resumes where it stopped rather than leaving
a layout that is part old and part new
([`SG0604`](/how-it-works/dialog/codes#sg0604)).

The journal and archive live *outside* the state root, so
[`purge`](/how-it-works/commands/purge) cannot destroy the record of a migration
still in progress.

## See also

* [`migrate`](/how-it-works/commands/migrate) - Convert a manifest's shape
* [Projects](/how-it-works/projects) - How one supervisor hosts many projects
* [Diagnostics](/how-it-works/dialog) - [`SG0601`](/how-it-works/dialog/codes#sg0601), [`SG0602`](/how-it-works/dialog/codes#sg0602), [`SG0603`](/how-it-works/dialog/codes#sg0603), [`SG0604`](/how-it-works/dialog/codes#sg0604), [`SG0605`](/how-it-works/dialog/codes#sg0605)
