# Authenticate

Authentication has two parts: an API key proves who you are, and a workspace ID selects the tenant the CLI is allowed to act in.

## Prerequisites

- A working [`hlix` installation](/getting-started/install/)
- An hlix API key
- The ID of a workspace you can access

Create an API key in [Developer tools → API keys](https://app.hlix.ai/developer-tools/api-keys). That page also shows the active workspace ID with a copy button. A newly created key is displayed once, so save it in your password manager before closing the dialog.
**Never put an API key in argv:** Do not run `hlix auth login --api-key …`. The CLI refuses that flag because command arguments can be retained in shell history and process listings.

## Sign in

Pick the path that matches where the command runs.

**Interactive login**, on a machine with a terminal:

1. **Start login with the workspace ID.**

   ```bash
   hlix auth login --workspace <workspace-id>
   ```

2. **Paste the API key into the hidden prompt.** The value is not echoed.

3. **Wait for verification.** The CLI makes an authenticated project-list request before storing anything. An invalid key or inaccessible workspace leaves no convincing saved login behind.

Expected result:

```text
Signed in to https://server.hlix.ai
Credential stored at …/hlix/credentials.json
```

The credential file is written with owner-only permissions. Its location follows `HLIX_CONFIG_HOME`, then `XDG_CONFIG_HOME`, then `~/.config`.

**In CI**, use secret environment variables instead of writing a credential file. There is **no login step** — the variables are the credential.

```bash
export HLIX_API_KEY='…'
export HLIX_WORKSPACE_ID='<workspace-id>'
hlix projects list --json
```

Expected result: a JSON envelope with `schemaVersion` and `data`. `HLIX_BASE_URL` is optional and defaults to `https://server.hlix.ai`.

When `HLIX_API_KEY` is set, the CLI uses the environment credential instead of any saved file. That makes a CI override explicit and leaves a machine login untouched.

**Against a self-hosted or local API**, point `--base-url` at your deployment:

```bash
hlix auth login \
  --workspace <workspace-id> \
  --base-url https://api.example.com
```

The URL must use HTTPS. Plain HTTP is accepted only for `localhost`, `127.0.0.1`, or `::1` — anything else exits `invalid_base_url` rather than sending a key in the clear.

The stored credential remembers this origin, so later commands in that folder reach the same deployment without repeating the flag.

## Check which credential is in use

```bash
hlix auth status
```

Expected result:

```text
credential  file (/Users/you/.config/hlix/credentials.json)
api         https://server.hlix.ai (from credential)
workspace   org_2p9xk4 (from credential)
status      valid
```

This names the credential's **source** — the environment or the stored file — and probes it against the API. It never prints the key, not even a prefix, because machine output gets piped into logs. When the probe fails, the failure code is the same one every other command would return, and the context (`credential from file, workspace …, api …`) goes to stderr.

`hlix status` answers the wider question — which workspace this *folder* resolves to, and why. See [Where a command points](/reference/cli/).

## Sign out

```bash
hlix auth logout
```

This removes the credential **file** only. It asks first; `--yes` skips the prompt, and a `--json` or non-interactive caller is refused with `approval_required` rather than defaulted to yes.

A key supplied through `HLIX_API_KEY` is reported and left alone — it belongs to the shell that set it:

```text
HLIX_API_KEY is set in this environment; unset it there to sign out.
```

## If login fails

- `--workspace is required`: pass the workspace ID or set `HLIX_WORKSPACE_ID`.
- `missing_credential` — ``No API key entered. Run from a terminal or set HLIX_API_KEY for CI.`` Run the command in an interactive terminal, or set `HLIX_API_KEY` for CI.
- `unauthenticated`: the key was rejected. Rotate or replace it, then retry.
- `forbidden`: the key is valid, but the user cannot act in that workspace.
- `invalid_base_url` — ``--base-url must use HTTPS (HTTP is allowed only for localhost).`` Use TLS, or a loopback hostname for local development.
- `unreachable`: verify the API URL, DNS, TLS, and network path.
- `workspace_mismatch`: you are inside a folder bound to a different workspace and passed a contradicting `--workspace`, `--base-url`, or `HLIX_*` value. `hlix auth login` is exempt from this — signing in to a second workspace from a bound folder works — but every other command refuses rather than guessing.
- `approval_required` from `auth logout`: the caller cannot answer a prompt. Repeat with `--yes`.

## Next steps

[Quickstart: ship your first task](/getting-started/quickstart/)
  [Move an existing project to hlix](/guides/quickstart/)
  [Import a project](/cli/import/)
  [CLI commands](/reference/cli/)