# Core concepts (/docs/concepts)

The pieces that make up a solitary cell.

## Cell [#cell]

A cell is the unit of isolation and lifecycle. It has a definition, a Lima VM, a persistent disk, and a container. Cells are meant to be disposable: destroy one when its state is no longer useful, then create a clean one from the same definition.

## VM [#vm]

The VM is the boundary. It is the part that separates a cell from the host kernel. On macOS and Linux, solitary uses Lima to create and manage it.

## Container [#container]

The container is the toolset, not the security boundary. Change `image:` or `build:` and bring the cell up again to replace the container while retaining the cell's disk.

## Host [#host]

The host is the operator and the display. It starts machines, forwards selected ports, stores secrets, and performs explicit file transfers. It does not mount your repository into a cell.

## Persistence [#persistence]

The cell's home directory lives on the VM disk. It survives a stopped machine and a replaced container. `rm` destroys the VM and its disk; the cell definition and host-held secrets remain available for a fresh `up`.

## Changing a cell [#changing-a-cell]

A cell is edited by editing `cell.yaml` and running `up` again. What that costs depends on which of the three layers the setting belongs to:

| Layer     | Settings                                                        | Applied by                             |
| --------- | --------------------------------------------------------------- | -------------------------------------- |
| Container | `image`, `build`, `command`, `secrets`, `git`                   | `up` — the container is replaced       |
| Machine   | `vm`, `ports`, `network`                                        | The next boot: `down` then `up`        |
| Disk      | what `vm.provision` did, and everything the cell has done since | `rm` then `up` — the disk goes with it |

`up` says which one it is: it replaces a container without being asked, warns when a running machine is holding settings that changed, and applies them itself when the machine is stopped.

Removing a setting is applied like adding one. A machine that was restricted or tunnelled has its resolver, firewall and tunnel taken back out at the next boot, so the guest matches the definition in both directions — the machine is not left enforcing an allow list nothing describes any more.

`vm.provision` is the exception, and the reason the third row exists. The script runs in the machine and changes its disk; the disk survives every change short of `rm`. A new script runs at the next start, but nothing undoes what the old one did, so a machine built by the current script alone is a machine created again from scratch. Both `up` and the dashboard say so when the script changes.

## How it works [#how-it-works]

`up` renders an embedded Lima template into a machine definition, creates the machine, and starts one rootless podman container inside it. Both are driven by shelling out — `limactl` on the host, `podman` through `limactl shell` in the machine — so there is nothing to install beyond Lima.

The container runs with `--network host`. The machine is the boundary, so there is no reason to put a second one between the container and the machine it lives in; ports reach the host through Lima's forwarding.

A container's identity is recorded in two labels: the image as written in `cell.yaml`, and a digest of the environment it was started with. `up` compares both and replaces the container when either has moved, which is why changing a secret or an image needs no separate command.

## Authority [#authority]

A cell receives authority in named pieces:

* `secrets` controls which environment variables enter the container.
* `ports` controls which listening ports are reachable from the host.
* `network.allow` controls which destinations the cell can reach.
* `image` or `build` determines which code is trusted inside the cell.

A cell also has **no browser** and no launcher configured. Anything that would normally authenticate by opening one is authenticated on the host instead, and the resulting credential is passed in under `secrets`.

The configuration should make those decisions reviewable before the cell runs. Because values are separated from names, the definition can be committed and shared as a reusable workflow without sharing credentials, and taken with [`solitary clone`](/docs/sharing).
