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

# Environments

> The top-level primitive — a named composition of clones you reason about and eval against.

An **environment** is the thing you reason about and evaluate against. A
[**clone**](/concepts/clones) is the component it composes.

```
ENVIRONMENT  (named, version-controlled via environment.yaml)
  └── members: clone ids        ← the single source of truth for membership
        └── CLONE                isolated SaaS-app instance
              ├── backend        per-clone database + Redis prefix
              └── frontend       optional (full mode, Slack only)
```

Two nouns at two altitudes: the clone is the unit you build and compose; the
environment is the unit you point an agent at and score. Membership lives on the
environment (`Environment.members`), never on the clone — one source of truth, so
the two can't drift.

## Shape

| Field                     | Example                         | What it is                                                                                      |
| ------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------- |
| `name`                    | `acme`                          | The handle you pass to `env` commands.                                                          |
| `members`                 | `["slack-a1b2", "stripe-c3d4"]` | Clone ids in this environment. The source of truth.                                             |
| `spec`                    | `acme.env.yaml` or `null`       | Path to the `environment.yaml` that produced it, or `null` for ad-hoc (`spin -g`) environments. |
| `state`                   | `running`                       | Rolled up from members: `running` (all up), `partial` (some up), `stopped`, `failed`.           |
| `createdAt` / `updatedAt` | ISO                             | Timestamps.                                                                                     |

## Two ways to create one

**Declaratively**, from a version-controlled spec. List as many clones as you
want — `env spin` brings them up in declared order:

```yaml theme={null}
# acme.env.yaml
name: acme
clones:
  - template: slack
    mode: full
    seed: acme-corp
  - template: stripe
    mode: api
```

```bash theme={null}
asymmetric env spin acme.env.yaml
```

**Ad-hoc**, by tagging clones as you spin them — each clone joins the named
environment:

```bash theme={null}
asymmetric spin slack stripe --group acme   # both clones land in environment "acme"
```

Either way, operate the environment as a unit:

```bash theme={null}
asymmetric env status             # list environments and their members
asymmetric env reset acme         # reset every member to its clean seeded state
asymmetric env destroy acme       # tear down every member
```

See the [`env` command reference](/cli/environments) for the full surface.

## How `env spin` behaves

The spin is **sequential and continue-all**: each clone is created and joined to
the environment before the next is started, and one member's failure doesn't
abort the rest.

* Every `create()` self-persists, so a crash mid-spin still leaves a real
  environment holding the members spun so far.
* A failed member is rolled back (never recorded), and the environment is stamped
  `partial`; the command exits non-zero.

## The schema is strict

The `environment.yaml` schema **rejects** anything it can't actually honor,
loudly, rather than parsing it and silently doing nothing:

| In the spec                                  | Today                                   |
| -------------------------------------------- | --------------------------------------- |
| One or more `clones` entries                 | Spun, in order.                         |
| `identity:` (shared users/org across clones) | Hard error — not supported yet.         |
| `data:` (bring-your-own Postgres)            | Hard error — not supported yet.         |
| An unknown key                               | Hard error, with a "did you mean" hint. |

<Info>
  Declared-but-unbuilt features fail **loudly** on purpose. For an eval product, a
  silently-ignored `identity:` block would make results quietly wrong. A clear error
  is the honest behavior until the feature is real.
</Info>

## On the roadmap

A shared cross-clone **identity** graph (one set of users/org spanning every
member) and **bring-your-own Postgres** data are reserved in the schema but not
yet enforced. The data model and the `environment.yaml` schema already make room
for them, so nothing about today's shape has to change when they ship.

## The registry

Environments and clones are both persisted to `~/.asymmetric/registry.json`
(schema-versioned, migrated on read). See
[Clones, environments, and the registry](/concepts/clones#the-registry).
