# Projects & Environments (/docs/environments)

Give the agent a real machine — a managed VM or your own server — and attach to it from the desktop, the CLI or the hub.

An **environment** is a machine where the codai agent actually works: shell, files, builds and dev servers. A small daemon, `codaid`, runs on it and keeps one **outbound** WebSocket to the relay (`wss://relay.codai.ro`) — the machine never opens a listening port. Your devices attach through the same relay, so tools run in the environment while you watch and steer from wherever you are.

```text
 desktop / CLI / hub                gateway  ai.codai.ro        (projects, environments, members, ports)
   │  attach, terminal, ports ───▶  relay    relay.codai.ro     (daemon + client WebSockets, presence)
   │  https://3000-<slug>.preview.codai.ro ─▶ │ preview router
                                              ▼ outbound WebSocket, never inbound
                               environment (managed VM or your own server)
                                 codaid: shell · files · terminals · ports · git state · build lock
```

## Vocabulary [#vocabulary]

| Object | What it is |
| --- | --- |
| **Project** | A repository plus its settings: `repo_url`, `default_branch`, optional `devcontainer_path`, and an **isolation mode** that decides how developers share machines. Owned by you, optionally attached to an org you administer. |
| **Environment** | One machine inside a project. Has a globally unique `slug` (it becomes the preview hostname), a `provider`, a `state`, an idle timeout and, for managed machines, a size and an hourly rate. |
| **Member** | A person with a role on one environment: `owner` ≥ `maintainer` ≥ `developer` ≥ `viewer`. Each member gets their own Linux account and a block of 100 ports inside the machine. |
| **Port** | A port you publish with a **visibility** (`owner`, `org`, `authenticated`, `public`). Published HTTP ports get a preview URL. |
| **Secret** | An `ENV_STYLE` value stored sealed; names can be listed, values are never returned. |
| **Event** | An append-only audit row: every state change, enrolment, member, port and secret change. The last 20 appear on the environment page. |

## Two ways to get a machine [#two-ways-to-get-a-machine]

| | Managed | Bring your own (BYO) |
| --- | --- | --- |
| Who provisions it | codai, on OpenStack (Cloudify, EU) or Hetzner Cloud | You — any Linux server you control |
| How `codaid` gets there | Installed and enrolled by cloud-init, automatically | You run the installer with a one-time token |
| Start / stop | Yes, plus idle auto-stop | No — the machine is yours; archive or destroy only |
| Price | Per second of runtime, from your wallet | Free |
| Availability | Rolling out — feature-gated per account | Open to every key |

Details: [install on your own server](./byo-install.mdx), [managed environments](./managed.mdx), [billing](./billing.mdx).

## Attach from your devices [#attach-from-your-devices]

| Surface | What you can do today |
| --- | --- |
| **Hub** — [hub.codai.ro/projects](https://hub.codai.ro/projects) | Create projects and environments (BYO and managed), start/stop/archive/destroy, generate an enrolment token with the install command, manage members and your SSH key. The environment page shows forwarded ports, secret names, agent tasks, SSH access, this month's compute cost and the last events. |
| **Desktop** — Environments view (<kbd>Alt</kbd>+<kbd>5</kbd> in the Developer skin, <kbd>Ctrl</kbd>+<kbd>5</kbd> in the Assistant skin) | Attach the agent to an environment, open a terminal in it, see listening ports and change their visibility, copy or open preview URLs, create a BYO environment and enrol it. |
| **CLI** — `codaid env …` | List, create, start, stop, archive, destroy; show status and ports; set or remove port visibility; mint preview links; forward a port to `127.0.0.1`; open a shell; SSH in with a 12-hour certificate (`env ssh`, `env ssh-ca`); queue and follow agent tasks (`env tasks list`, `create`, `get`); manage members (`env members list`, `add`, `role`, `remove`) and secrets (`env secrets list`, `set`, `rm`); follow the event log. |
| **Phone** (Android) | *Environments* screen: list your environments, start and stop managed ones, open preview links. |
| **MCP** | Tools for agents: `list_projects`, `list_environments`, `get_environment`, `start_environment`, `stop_environment`, `list_environment_ports`, `create_environment_task`, `list_environment_tasks`, `get_environment_task`. Destroying environments and reading or writing secrets are deliberately not exposed over MCP. |

When the desktop agent is attached, the **agent loop runs on your device and its tools run in the environment** — the composer shows *in &lt;name&gt;*. Running the whole loop inside the environment (headless) is coming soon.

Preview hosts (`https://{port}-{slug}.preview.codai.ro`) and the relay (`wss://relay.codai.ro`) are served directly by codai's Google Cloud load balancer; Cloudflare only answers DNS for them and does not proxy the traffic.

## Lifecycle at a glance [#lifecycle-at-a-glance]

```text
 BYO:      pending ──enrol──▶ enrolling      (online / offline = daemon presence on the relay)
 managed:  creating ──VM up──▶ enrolling ──▶ running ⇄ stopping ─▶ stopped ─▶ archiving ─▶ archived
                                                  (idle / budget / funds)
 any state ──destroy──▶ destroying ──▶ destroyed      (BYO: straight to destroyed)
```

A BYO environment has no provider step, so `destroy` lands on `destroyed` at once (and revokes the daemon's key) and `archive` on `archived`.

For a BYO machine the stored state stays `enrolling` after enrolment; whether it is reachable right now is the relay's **presence** (`online`), which drops 45 seconds after the daemon's last heartbeat.

Next: [install codaid on your own server](./byo-install.mdx) or [create a managed environment](./managed.mdx).
