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

# Environments

> Environments are at the heart of how you organize and share configuration in Ghostable.

<Card title="Need the shared environment model?" icon="circle-info" href="/fundamentals/v2/core-objects/environments">
  Read the Fundamentals page for the shared object model, then use this guide for CLI commands.
</Card>

Each project can have as many environments as you need. While **production** and **staging** are
common defaults, you’re free to create environments for feature branches, client-specific setups,
QA, or any other workflow you use.

Environments define how variables are organized, accessed, and shared within your team.

You can safely **push**, **pull**, or **deploy** environment data using the Ghostable CLI, and every
operation is scoped to a specific environment and auditable.

<Tip>
  Think of environments as named contexts for your configuration — isolated, auditable, and built
  for secure collaboration.
</Tip>

## Variable Promotions (Approval Workflow)

Need to request cross-environment key changes with an explicit review step?

<Card title="Use promotion requests" icon="shuffle" href="/cli/v2/workflows/variable-promotions">
  Create and review variable promotion requests with `ghostable env promote` workflows.
</Card>

## Listing Environments

The `env list` command displays all environments associated with the current project as defined in
your `.ghostable/ghostable.yaml` manifest.

```bash theme={null}
ghostable env list
```

You’ll see each environment’s ID, name, type, and base (if applicable) in a structured table.

<Note>
  Note: You must be logged in and have an initialized project (ghostable init) before using this
  command.
</Note>

## Creating Environments

To create a new environment, run the `env create` command:

```bash theme={null}
ghostable env create
```

You'll be prompted to:

* Select an environment type (e.g., Production, Staging)
* If `--name` isn't provided, choose a suggested name or enter a custom slug-formatted name

<ParamField path="--name" type="string">
  Environment name (slug)
</ParamField>

## Pushing Variables

To upload your local `.env` file to Ghostable, use the `push` command:

```bash theme={null}
ghostable env push
```

This command securely uploads your environment variables to Ghostable for the currently linked
project and organization. If no environment is specified, you’ll be prompted to select one
interactively.

<Warning>
  Ghostable only pushes keys that exist in your local .env file. It will not remove remote keys
  unless explicitly told to using --prune-server.
</Warning>

<ParamField path="--env" type="string">
  Specify which environment to push (e.g. `production`, `staging`). If omitted, Ghostable will
  prompt you to choose.
</ParamField>

<ParamField path="--file" type="string">
  Path to the `.env` file to read from.\
  Defaults to `.env.<env>` or `.env` if unspecified.
</ParamField>

<ParamField path="--assume-yes" type="boolean">
  Skip confirmation prompts and proceed automatically.
</ParamField>

<ParamField path="--sync" type="boolean">
  Prune remote variables that are not present in your local `.env` file. This is equivalent to
  `--replace`, `--prune-server`, and `env sync`.
</ParamField>

<ParamField path="--replace" type="boolean">
  Alias for `--sync`.
</ParamField>

<ParamField path="--prune-server" type="boolean">
  Alias for `--sync`.
</ParamField>

<ParamField path="--conflict-mode" type="string">
  Conflict handling mode for push operations:

  * `strict` (default): block the push when local and server versions drift.
  * `warn`: detect stale keys. In interactive terminals, Ghostable prompts you to pull latest
    values, continue overwrite, or cancel.
</ParamField>

<ParamField path="--force-overwrite" type="boolean">
  Bypass optimistic conflict checks and force overwrite remote values.
</ParamField>

<Note>
  In interactive warn mode, choosing **Pull latest and cancel push** runs `ghostable env pull`
  immediately, updates your local `.env` target file, and cancels the push so you can review
  changes before retrying. Use `--assume-yes` to skip this prompt.
</Note>

#### Ignoring Variables

Some secrets (deployment tokens, platform-specific values, etc.) should never leave your machine.
List them under the `ignore` key for an environment inside `.ghostable/ghostable.yaml` and the CLI
will skip them during `env push`, `env sync`, `var push`, and `var pull`.

```yaml theme={null}
environments:
    production:
        type: production
        ignore:
            - GHOSTABLE_CI_TOKEN
            - STRIPE_WEBHOOK_SECRET
```

Ignored keys remain untouched remotely and locally. They also appear in summaries when you pass
`--show-ignored` to commands like `env pull` or `env diff`, so you know they were intentionally
skipped.

### Refreshing Local Version State

Ghostable tracks local key version baselines in `.ghostable/state/...` so strict conflict mode can
detect stale writes.

```bash theme={null}
ghostable env state refresh --env production
```

You can also run `ghostable env state` with no subcommand for guided refresh.

Run this when:

* You want strict conflict checks before pushing.
* Teammates updated the same environment recently.
* CI needs a fresh version baseline before `env push --conflict-mode strict`.

`ghostable env pull` refreshes this version baseline automatically after a successful pull.

<Warning>
  `env state refresh` updates local **version baselines only**. It does not pull new secret
  values into your local `.env` file. Run `ghostable env pull --env <env>` if you need value
  sync before pushing.
</Warning>

### Syncing Variables

The `env sync` command provides a **one-way synchronization** between your local `.env` file and the
remote environment in Ghostable.

```bash theme={null}
ghostable env sync
```

It treats your local file as the source of truth—remote variables are replaced wholesale and keys
that no longer exist locally are pruned.

<ParamField path="--env" type="string">
  Specify which environment to sync (e.g. `production`, `staging`). If omitted, Ghostable will
  prompt you to select one.
</ParamField>

<ParamField path="--file" type="string">
  Path to the local `.env` file to read from.\
  Defaults to `.env.<env>` or `.env` if unspecified.
</ParamField>

<ParamField path="--assume-yes" type="boolean">
  Skip confirmation prompts and proceed automatically.
</ParamField>

<ParamField path="--conflict-mode" type="string">
  Conflict handling mode for sync operations:

  * `strict` (default): block sync when local and server versions drift.
  * `warn`: detect stale keys and continue after warning or guided confirmation.
</ParamField>

<ParamField path="--force-overwrite" type="boolean">
  Force overwrite server values even when strict conflict checks would block.
</ParamField>

### Command comparison

| Command                             | Behavior                              | Remote effect                                                        | Prunes missing keys? | When to use                                                  |
| :---------------------------------- | :------------------------------------ | :------------------------------------------------------------------- | :------------------- | :----------------------------------------------------------- |
| `ghostable env push`                | Upload only keys in your current file | Updates/creates provided keys; untouched keys remain                 | No                   | Routine updates when you changed a subset of values          |
| `ghostable env push --sync`         | Push and prune remote extras          | Deletes remote keys not present locally while pushing submitted keys | Yes                  | Enforce local `.env` as source of truth for that environment |
| `ghostable env push --replace`      | Alias for `--sync`                    | Same as `env push --sync`                                            | Yes                  | Teams that prefer explicit “replace” wording                 |
| `ghostable env push --prune-server` | Alias for `--sync`                    | Same as `env push --sync`                                            | Yes                  | Teams that prefer explicit prune wording                     |
| `ghostable env sync`                | Shortcut to push with prune behavior  | Same as `env push --sync`                                            | Yes                  | Faster command for one-way synchronization workflows         |

### Validating Variables

Run schema validation before pushing or deploying to catch bad values early. The command pulls
`schema.yaml` plus any per-environment overrides and validates your local `.env`:

```bash theme={null}
ghostable env validate --env production
```

Output lists failing keys (if any) and exits non-zero so you can wire it into CI. See the
[Validation rules guide](/cli/v2/reference/validation) for rule syntax.

<ParamField path="--env" type="string">
  Environment whose `.env` should be validated. If omitted, the CLI prompts you to choose.
</ParamField>

<ParamField path="--file" type="string">
  Optional path to a non-standard `.env` file. Defaults to `.env.<env>` or `.env`.
</ParamField>

### Pushing a Single Variable

`var push` encrypts **one** environment variable from your local `.env` file and uploads it to
Ghostable.

It reads project + environment info from `.ghostable/ghostable.yaml`, respects your **ignore
rules**, and uses your local CLI keys to encrypt before upload.

```bash theme={null}
ghostable var push
```

<Note>
  This command only sends the one variable you select. It won’t touch other keys locally or
  remotely.
</Note>

<ParamField path="--env" type="string">
  Environment to push to (e.g. `production`, `staging`). If omitted, you’ll be prompted to choose
  from your manifest.
</ParamField>

<ParamField path="--key" type="string">
  The environment variable name to push (e.g. `APP_URL`). If omitted, the CLI lists variables from
  the resolved .env and prompts you to choose.
</ParamField>

<ParamField path="--file" type="string">
  Path to the .env file to read from.\
  Defaults to `.env.<env>` when `--env` is provided, otherwise `.env`.
</ParamField>

<ParamField path="--conflict-mode" type="string">
  Conflict handling mode for single-variable pushes:

  * `strict` (default): block the push when local and server versions drift.
  * `warn`: detect stale key versions. In interactive terminals, Ghostable prompts you to pull
    latest values, continue overwrite, or cancel.
</ParamField>

<ParamField path="--force-overwrite" type="boolean">
  Force overwrite the selected key even if local and server versions differ.
</ParamField>

<Note>
  In interactive warn mode, **Pull latest and cancel push** runs `ghostable env pull` for the
  environment, updates the local `.env` target file, and cancels the single-key push.
</Note>

In interactive terminals, `var push` also prompts for an optional **Reason for change**. That reason
is encrypted client-side and attached to the exact version created by the push.

### Variable Notes and Comments

Use `var context` when you want to work on the shared note or comments for a single variable.

```bash theme={null}
ghostable var context
```

The CLI walks you through environment and variable selection, then lets you:

* review the current note and comment thread,
* replace the shared note,
* add a new comment,
* delete one of your own comments,
* refresh the context view after a teammate updates it.

Adding a comment uses a normal inline prompt. Editing the note uses a multiline terminal composer so
you can keep line breaks without leaving the CLI.

***

## Pulling Variables

To fetch a remote environment and write it to your local `.env` file, use the `pull` command:

```bash theme={null}
ghostable env pull
```

This command downloads the latest variables from Ghostable for the selected environment and writes
them to your local .env file.

<Info>
  If your device is newly linked and key access is not yet shared, pull/diff commands return an
  explicit pending key re-share state (`ENV_KEY_RESHARE_REQUIRED`) with guidance instead of a
  generic failure.
</Info>

<Tip>
  Your local `.env` file will be overwritten unless you use `--dry-run`.
  By default, Ghostable automatically creates a timestamped backup of your existing `.env` file before writing.

  You can disable this behavior with `--no-backup`.
</Tip>

<ParamField path="--env" type="string">
  Specify which environment to pull (e.g. `production`, `staging`). If omitted, Ghostable will
  prompt you to select one.
</ParamField>

<ParamField path="--file" type="string">
  Path to the `.env` file where variables will be written.\
  Defaults to `.env.<env>` or `.env` if unspecified.
</ParamField>

<ParamField path="--format" type="string">
  Output format for the generated file. Accepts `alphabetical`, `grouped`, or `grouped:comments`.
  If omitted, the CLI prompts you to choose interactively.
</ParamField>

<ParamField path="--only" type="string[]" repeatable>
  Pull only specific variable keys. Can be repeated, e.g. `--only APP_KEY --only DB_PASSWORD`.
</ParamField>

<ParamField path="--dry-run" type="boolean">
  Preview which variables would be pulled without writing any files.
</ParamField>

<ParamField path="--show-ignored" type="boolean">
  Show variables that were skipped (ignored) during pull due to local configuration or filters.
</ParamField>

<ParamField path="--replace" type="boolean">
  Replace the entire local `.env` file instead of merging values.
</ParamField>

<ParamField path="--prune-local" type="boolean">
  Remove local variables that no longer exist on the server.
</ParamField>

<ParamField path="--no-backup" type="boolean">
  Skip automatic backup creation.
</ParamField>

### Pulling a Single Variable

`var pull` fetches one environment variable from Ghostable, decrypts it locally using your CLI keys,
and `upserts` it into your target `.env` file (creates the file if missing, replaces the line if it
exists, or appends a new line). If the variable’s metadata marks it as commented, the line is
written as a comment.

```bash theme={null}
ghostable var pull
```

<Note>
  This command only touches the one variable you request. It won’t prune or rewrite other keys.
</Note>

<ParamField path="--env" type="string">
  Environment to pull from (e.g. `production`, `staging`). If omitted, you’ll be prompted to
  choose from your manifest.
</ParamField>

<ParamField path="--key" type="string">
  The environment variable name to pull (e.g. `APP_KEY`). If omitted, you’ll be shown a selectable
  list from the remote environment.
</ParamField>

<ParamField path="--file" type="string">
  Destination file to update.\
  Defaults to `.env.<env>` when `--env` is provided, otherwise `.env`.
</ParamField>

***

## Comparing Environments

The `env diff` command helps you see what’s changed between your local .env file and the version
stored in Ghostable.

```bash theme={null}
ghostable env diff
```

**How It Works**

* The command pulls the latest **encrypted environment bundle** from Ghostable for the selected
  project and environment.
* It then decrypts that bundle **locally** using your master seed (stored in the OS keychain).
* It reads your local `.env` file, parses each variable, and compares the two sets of values.

<Note>
  Because Ghostable is **zero-knowledge**, the diff is performed entirely on your machine — no
  plaintext values are ever sent to Ghostable’s servers.
</Note>

<Card title="What’s Compared" horizontal>
  For each environment variable, Ghostable compares:

  | Field               | Description                                                                                   |
  | :------------------ | :-------------------------------------------------------------------------------------------- |
  | **Name**            | The variable key (for example, `APP_KEY`, `DB_HOST`).                                         |
  | **Value**           | The decrypted plaintext value from Ghostable compared against the value in your local `.env`. |
  | **Commented State** | Indicates whether the variable is commented or active, based on Ghostable’s stored metadata.  |
</Card>

<Card title="Possible Outcomes" horizontal>
  The diff output highlights three types of changes:

  | Symbol  | Meaning                                                          | Example Output                          |
  | :------ | :--------------------------------------------------------------- | :-------------------------------------- |
  | **`+`** | **Added locally** – exists in your `.env` but not in Ghostable   | `+ NEW_FEATURE_FLAG=true`               |
  | **`~`** | **Updated** – exists in both but values differ                   | `~ APP_URL: https://old -> https://new` |
  | **`-`** | **Removed locally** – exists in Ghostable but not in your `.env` | `- LEGACY_SETTING=on`                   |

  If there are no differences, you’ll see: `No differences detected.`
</Card>

<ParamField path="--env" type="string">
  Specify which environment to compare (e.g. `production`, `staging`) and skip the interactive
  picker.
</ParamField>

<ParamField path="--file" type="string">
  Path to the local `.env` file to diff against (default: `.env.<env>` or `.env`).\
  Alias for `--local`.
</ParamField>

<ParamField path="--local" type="string">
  Explicit local `.env` path. Same as `--file`; provided for compatibility with older scripts.
</ParamField>

<ParamField path="--token" type="string">
  API token to use for the remote pull. If omitted, the CLI uses your logged-in session or
  `GHOSTABLE_TOKEN`.
</ParamField>

<ParamField path="--only" type="string[]" repeatable>
  Diff only specific variable keys. Repeatable, e.g. `--only APP_KEY --only DB_PASSWORD`.
</ParamField>

<ParamField path="--show-ignored" type="boolean">
  Show variables that were skipped (ignored) during comparison due to local configuration or
  filters.
</ParamField>

### Viewing Change History

Audit every change to an environment with the `env history` command (legacy alias: `env audit`). It
summarizes recent activity and prints a table of individual operations.

```bash theme={null}
ghostable env history --env production
```

You'll see who changed which key, when it happened, whether the key was commented, and the version
number associated with the change. Handy for debugging regressions or reviewing peer updates.

History includes the new variable context workflow as well. Depending on the event, you may see:

* note updates,
* comment creation or deletion,
* variable updates tagged with a reason for change.

The activity rows stay metadata-only. They tell you what happened and who did it without exposing
decrypted note or comment bodies in the history table.

Example output:

| When                           | Actor                                     | Operation | Key       | Version | Notes                    |
| :----------------------------- | :---------------------------------------- | :-------- | :-------- | :------ | :----------------------- |
| 2 hours ago (2024-06-05 10:17) | [dev@example.com](mailto:dev@example.com) | update    | `APP_URL` | v12     | URL changed to prod host |
| 1 day ago (2024-06-04 09:02)   | [dev@example.com](mailto:dev@example.com) | comment   | `DEBUG`   | v11     | Flag commented out       |
| 3 days ago (2024-06-02 18:45)  | [ops@example.com](mailto:ops@example.com) | create    | `API_KEY` | v1      | New key provisioned      |

Returned **3** change(s).

<ParamField path="--env" type="string">
  Environment to inspect. Defaults to an interactive picker.
</ParamField>
