# Environments

**An Environment is a named bundle of variables, files, skills and MCP servers that every task in a project loads into its checkout.** A project can hold several, and exactly one is active at a time. It turns "this project always needs these three files and that skill" into a setting instead of an instruction the agents have to be reminded of.

## Prerequisites

- A project in your Workspace.
- `manage` access on the project.
- Any secret an Environment variable should carry stored as a [project secret](/configure/secrets/) — see the warning below.

## What a bundle contains

| Key | Type | What happens to it at task time |
| --- | --- | --- |
| `vars` | Map of name to value | Merged into the project's environment values and delivered the same way a project secret is |
| `files` | List of `{ path, content }` | Written as-is into the task's checkout, relative to the repository root |
| `skills` | List of skill slugs | Each named skill is copied from hlix's skill library into `.claude/skills/<slug>/` in the checkout |
| `mcpServers` | List of server definitions | Merged into the checkout's `.mcp.json`, keeping anything the repository already declares |
| `managedPaths` | List of paths | The paths hlix writes and manages, so it can update them without touching your edits elsewhere |

A skill slug the library does not have is **skipped**, never written as an empty placeholder that could hide a real skill of the same name.

**Variables are configuration, not a secret store:** Environment `vars` are stored as written and are readable by anyone who can read the project's settings. Put credentials in [Secrets](/configure/secrets/) instead: a project secret **overrides** an Environment variable of the same name, so the bundle can name a variable and the secret can supply its value.

## Create one

```bash
curl -sS -X POST "$HLIX_BASE_URL/v1/api/environments/project/$PROJECT_ID" \
  -H "x-api-key: $HLIX_API_KEY" \
  -H "X-Organization-Id: $HLIX_WORKSPACE_ID" \
  -H 'content-type: application/json' \
  -d '{
    "label": "Default",
    "isActive": true,
    "config": {
      "vars": { "NODE_ENV": "test" },
      "files": [{ "path": ".nvmrc", "content": "22\n" }],
      "skills": ["api-design-review"]
    }
  }'
```

Expected result: `201` and the stored Environment, with `isActive: true`.

`label` is required and capped at 100 characters. `vars` defaults to an empty map, and `files`, `skills`, `mcpServers` and `managedPaths` are all optional.

### List, update, delete

```bash
curl -sS "$HLIX_BASE_URL/v1/api/environments/project/$PROJECT_ID" \
  -H "x-api-key: $HLIX_API_KEY" \
  -H "X-Organization-Id: $HLIX_WORKSPACE_ID"
```

Expected result: `200` and the project's Environments, newest first, each with its own `isActive` flag.

`PATCH /v1/api/environments/project/{projectId}/{id}` changes the label, the config or the active flag. `DELETE /v1/api/environments/project/{projectId}/{id}` removes one.

## How a bundle reaches a task

When a task starts, hlix reads the project's **active** Environment and adds it to the task:

1. `vars` are merged beneath the project's secrets; a secret always wins over a variable of the same name.
2. `files`, `skills` and `mcpServers` go to the task's sandbox.
3. In the task's checkout, the files are written, the skills are copied in, and the MCP definitions are merged into `.mcp.json`.

A project with no Environment runs normally: nothing is merged, and nothing fails.

**Every coder receives the bundle:** Steps 2 and 3 apply to every coder alike, Hlix Code included. See [MCP servers](/configure/mcp-servers/#where-it-lands-in-a-task).

**Paths stay inside the checkout:** Every `files` path is resolved beneath the repository root. An absolute path, a path containing `..`, or a path whose parent is a symbolic link is refused rather than written.

## If an Environment does not take effect

- **`{"error":"Project not found"}` with `404`.** The project is not in the Workspace named by `X-Organization-Id`.
- **`{"error":"Environment not found"}` with `404`.** The Environment id does not belong to that project.
- **`{"error":"Failed to create environment"}` with `500`.** The write did not persist. Retry; if it repeats, the payload is the thing to check — a very large `files` array is the usual cause.
- **A variable is missing inside the task.** Only the **active** Environment is loaded. Check `isActive`, and check that a project secret of the same name is not overriding it with a different value.
- **A skill you listed is not in the checkout.** The slug is not in the skill library, so it was skipped. Check the slug against [Packs & skills](/configure/packs-and-skills/); a Workspace custom skill is delivered as a file, not as a `skills` slug.
- **A file you listed is not in the checkout.** The path was refused for leaving the repository root, or its parent directory could not be created safely. Use a plain project-relative path with no `..` segments.
- **An MCP server is in the bundle and the coder does not see it.** hlix merges it into `.mcp.json`; the coder still has to be one that reads that file. See [MCP servers](/configure/mcp-servers/).
- **A task fails naming a missing secret.** ``MCP server … requires missing project secret …`` — an imported MCP server references an environment key that has no project secret behind it. Add the secret, or re-import the server.

## Where to go next

| If you want to… | Read |
| --- | --- |
| Store the values behind these variables | [Secrets](/configure/secrets/) |
| Add a skill to the bundle | [Packs & skills](/configure/packs-and-skills/) |
| Add an MCP server to the bundle | [MCP servers](/configure/mcp-servers/) |
| See what a task scan collects automatically | [Environment discovery](/cli/environment-discovery/) |

## Next steps

[Secrets](/configure/secrets/)
  [Packs & skills](/configure/packs-and-skills/)
  [MCP servers](/configure/mcp-servers/)
  [The Coding Workspace](/concepts/coding-workspace/)