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

# CLI reference

> Every Sink CLI command, flag, and automation pattern.

`sink` syncs secrets between a Sink environment and a local file. It authenticates with an API key and resolves the workspace, team, project and default environment from [`.sink.json`](/cli/configuration#the-link-file).

```bash theme={null}
curl -fsSL https://usesink.co/install.sh | sh
```

Every command that takes an environment accepts a name, slug or id, and falls back to the linked default when you omit it.

## Account

<ResponseField name="sink login [--key/-k <key>] [--api-url <url>]" type="command">
  Validate an API key and remember it. Prompts for the key when it is not given; `--key -` reads it from stdin. The key goes into your OS keychain, or into `~/.config/sink/config.json` (mode `0600`) when no keychain backend exists.
</ResponseField>

<ResponseField name="sink logout" type="command">
  Forget the stored credential. Leaves `.sink.json` alone.
</ResponseField>

<ResponseField name="sink whoami" type="command">
  Show the signed-in account, the API URL, where the credential is being read from, the linked project, and — when the server supports it — the workspace's plan, seat and secret usage.
</ResponseField>

## Linking

<ResponseField name="sink init [-w <workspace>] [-t <team>] [-p <project>] [-e <env>] [--force]" type="command">
  Write `.sink.json` for the current directory. With no flags it prompts through the available workspaces, teams, projects and environments; each flag skips one prompt. `--force` overwrites an existing file.
</ResponseField>

The file it writes holds ids and display names and no values. Commit it.

## Listing

| Command                                   | Shows                                                                              |
| ----------------------------------------- | ---------------------------------------------------------------------------------- |
| `sink list workspaces`                    | Name, slug and id of every workspace on the account.                               |
| `sink list teams [-w <workspace>]`        | Teams in a workspace; defaults to the linked one.                                  |
| `sink list projects [-t <team>]`          | Projects in a team, with their active flag.                                        |
| `sink list environments`                  | Environments in the linked project, with their type. The linked default is marked. |
| `sink list secrets [env] [--show-values]` | Keys in an environment. Values masked unless revealed.                             |

## Sync

### `sink pull [environment]`

Write an environment's secrets to a local file.

```bash theme={null}
sink pull                                   # linked environment → ./.env
sink pull prod -o .env.production
sink pull prod --format json -o secrets.json
sink pull prod --stdout
sink pull prod --version 2 -o .env.v2
```

| Flag                    | Description                                                             |
| ----------------------- | ----------------------------------------------------------------------- |
| `-o, --output <path>`   | Destination file. Default `.env`.                                       |
| `--format dotenv\|json` | Output shape. Default `dotenv`.                                         |
| `--stdout`              | Print instead of writing a file.                                        |
| `-f, --force`           | Overwrite without confirming. Required when not attached to a terminal. |
| `-V, --version <n>`     | Read each secret at version `n` (minimum 1).                            |

When the target file already exists and the format is `dotenv`, `pull` first shows a diff of what is about to change, then asks before overwriting. If nothing differs it says so and leaves the file alone. Files are written mode `0600`, with a header naming the project and environment.

<Note>
  `--version` pins **each secret** to that version, not the environment to a snapshot. Secrets with fewer versions are read at their latest, and the command names them.
</Note>

### `sink diff [environment]`

Compare a local file against an environment. Changes nothing.

```bash theme={null}
sink diff prod --file .env.production --exit-code
```

| Flag                | Description                                  |
| ------------------- | -------------------------------------------- |
| `-f, --file <path>` | Local file to compare. Default `.env`.       |
| `--show-values`     | Reveal values instead of masking them.       |
| `--exit-code`       | Exit `1` when there are differences. For CI. |

Output marks keys as local-only (`+`), differing (`~`) or remote-only (`-`), and counts the unchanged.

### `sink push [environment]`

Send a local file up to an environment.

```bash theme={null}
sink push prod --dry-run
sink push prod --yes
sink push prod --prune --yes
```

| Flag                | Description                                                      |
| ------------------- | ---------------------------------------------------------------- |
| `-f, --file <path>` | Source file. Default `.env`.                                     |
| `--dry-run`         | Show the plan and stop.                                          |
| `-y, --yes`         | Skip the confirmation. Required when not attached to a terminal. |
| `--prune`           | Delete remote secrets absent from the local file.                |

`push` refuses a file with invalid variable names, prints the create/update/delete plan with values masked, and waits for a yes. New keys are created in one bulk call, changed keys updated in another — each update minting a new version — and prunes are deleted one at a time. Without `--prune`, remote-only keys are listed and left alone.

<Warning>
  `--prune --yes` deletes without a second look. Run it once with `--dry-run` first.
</Warning>

### `sink import <provider> [environment]`

Read variables out of Railway, Vercel or Render. See [Import from a provider](/guides/importing) for the full walkthrough.

```bash theme={null}
sink import railway prod
sink import vercel prod --project prj_abc --provider-env production --dry-run
sink import render prod --service srv_1 --mode overwrite --yes
```

| Flag                     | Description                                                                                                 |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- |
| `-t, --token <token>`    | Provider token. `-` reads stdin; falls back to `SINK_<PROVIDER>_TOKEN`, then a hidden prompt. Never stored. |
| `--project <id>`         | Provider project. For Render, the service.                                                                  |
| `--provider-env <id>`    | Railway environment, or Vercel target.                                                                      |
| `--service <id>`         | Railway or Render service.                                                                                  |
| `--mode skip\|overwrite` | Keys Sink already has: leave alone, or record the provider's value as a new version. Default `skip`.        |
| `--dry-run`              | Preview and stop.                                                                                           |
| `-y, --yes`              | Skip the confirmation.                                                                                      |
| `--show-values`          | Reveal values in the preview.                                                                               |

Omitted identifiers are prompted for from what the token can actually see. Variables the provider will not return in clear text are listed as skipped, with a reason.

## Exit codes

| Code | Meaning                                                                                                         |
| ---- | --------------------------------------------------------------------------------------------------------------- |
| `0`  | Success, or no differences with `--exit-code`.                                                                  |
| `1`  | A failure — bad credential, missing link, unreachable API, refused confirmation — or drift under `--exit-code`. |

Errors print to stderr with a leading `✗`. An expired or rejected credential says so and points at `sink login`; a plan limit points at Settings → Billing.

<Card title="Configuration and environment variables" icon="gear" href="/cli/configuration">
  Where the CLI keeps its state, and every variable it reads.
</Card>
