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

# Auth

> Sign in, switch workspaces and check which identity a run will use.

Flags and arguments below are the contract as the binary states it. The global flags (`--json`, `--timeout`, …) apply here too and are documented on [Global flags](/docs/cli/contract/global-flags). Error codes are a workspace-global contract, not a per-command one — the taxonomy, and how to read a code that is not in it, is on [The error envelope](/docs/cli/contract/error-envelope).

## `octolens login`

Authenticate the CLI (browser handoff or API key)

**Arguments**

| Argument | Type     | Required | Description                                                 |
| -------- | -------- | -------- | ----------------------------------------------------------- |
| `KEY`    | `string` | optional | API key to save (with --with-key); prefer the masked prompt |

**Flags**

| Flag           | Type                           | Required (headless) | Description                                                                                                                                                                                                                                                                                |
| -------------- | ------------------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--no-browser` | `boolean`                      | no                  | Print the authorize URL instead of opening a browser, then wait for the key to arrive out of band. The wait is time-bounded: the global --timeout governs it (default 180s without the flag), and expiry exits 2 with a LOGIN\_TIMEOUT envelope — the process always terminates on its own |
| `--profile`    | `string`                       | no                  | Name to store this login under                                                                                                                                                                                                                                                             |
| `--scope`      | enum: `read`, `write`, `admin` | no                  | Scope to mint during the browser handoff (default: `write`)                                                                                                                                                                                                                                |
| `--with-key`   | `boolean`                      | no                  | Authenticate with an API key (headless boxes) instead of the browser — create one at [https://app.octolens.com/me/api](https://app.octolens.com/me/api)                                                                                                                                    |

**Examples**

```bash theme={null}
octolens login
octolens login --with-key
octolens login --with-key ak_live_xxx
```

**Returns**

With `--json`, stdout carries one JSON document with these fields.

| Field                      | Type                         | Description                                                                                                    |
| -------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `loggedIn`                 | boolean                      | Always `true` — a failed login answers the error envelope instead.                                             |
| `edition`                  | enum: `internal`, `customer` | The CLI build edition (same value `version` reports).                                                          |
| `profile`                  | string \| null               | Name of the stored profile this login created or updated.                                                      |
| `workspace`                | object \| null               | The authenticated workspace (`{organizationId, name, plan}`), when it could be read.                           |
| `workspace.organizationId` | string                       | Organization id.                                                                                               |
| `workspace.name`           | string                       | Workspace name.                                                                                                |
| `workspace.plan`           | string \| null               | Current plan. `null` when none.                                                                                |
| `actingAs`                 | object \| null               | Present when this login acts on another workspace (`{orgId, workspace?}`). `null` otherwise.                   |
| `baseUrl`                  | string                       | The effective app base URL for this login — what the REST transport targets.                                   |
| `pinnedBaseUrl`            | string \| null               | The deployment the key was verified against and persisted with the profile. `null` for flows that pin nothing. |

Without `--json`: A terminal prints one confirmation line naming the workspace and profile.

Example output:

```json theme={null}
{
  "loggedIn": true,
  "edition": "customer",
  "profile": "acme",
  "workspace": {
    "organizationId": "org_2abcDEFghij345",
    "name": "Acme",
    "plan": "Pro_v3"
  },
  "actingAs": null,
  "baseUrl": "https://app.octolens.com",
  "pinnedBaseUrl": "https://app.octolens.com"
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE · `8` CANCELLED. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens logout`

Remove stored login credentials

**Flags**

| Flag        | Type      | Required (headless) | Description                   |
| ----------- | --------- | ------------------- | ----------------------------- |
| `--all`     | `boolean` | no                  | Remove every stored profile   |
| `--profile` | `string`  | no                  | Name of the profile to remove |

**Examples**

```bash theme={null}
octolens logout
octolens logout --profile acme
octolens logout --all
```

**Returns**

With `--json`, stdout carries one JSON document with these fields.

| Field                       | Type      | Description                                                                                   |
| --------------------------- | --------- | --------------------------------------------------------------------------------------------- |
| `loggedOut`                 | boolean   | Always `true` — having nothing to remove is an error (exit 2), not a payload.                 |
| `removed`                   | string\[] | Names of the profiles that were removed.                                                      |
| `envCredentialsStillActive` | boolean   | `true` when `OCTOLENS_API_KEY`/`OCTOLENS_ORG` are set — logout cannot remove env credentials. |
| `activeProfile`             | null      | Always `null` after a logout: another stored login is never silently promoted.                |
| `remainingProfiles`         | string\[] | Profiles still stored (switch back in with `switch`). Empty when none remain.                 |

Without `--json`: A terminal prints what was removed and which profiles remain.

Example output:

```json theme={null}
{
  "loggedOut": true,
  "removed": [
    "acme"
  ],
  "envCredentialsStillActive": false,
  "activeProfile": null,
  "remainingProfiles": [
    "globex"
  ]
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens signup`

Create an Octolens workspace from the terminal (browser handoff, or --headless email code)

**Flags**

| Flag           | Type      | Required (headless) | Description                                                                                                                                                                                                                                                                                                                                |
| -------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--code`       | `string`  | no                  | The 6-digit verification code from the email (requires --signup-id headlessly)                                                                                                                                                                                                                                                             |
| `--domain`     | `string`  | no                  | Your company domain (e.g. corp.com) — sets up the workspace profile. Defaults to your email's domain for work addresses; personal providers (gmail, outlook, yahoo, …) say nothing about your company, so they still require this flag (or the prompt). An explicit --domain always wins.                                                  |
| `--email`      | `string`  | no                  | Work email to sign up with (--headless; prompted for interactively when omitted)                                                                                                                                                                                                                                                           |
| `--headless`   | `boolean` | no                  | Sign up entirely in the terminal: a verification code is emailed to you (no browser anywhere in the loop, works over SSH).                                                                                                                                                                                                                 |
| `--no-browser` | `boolean` | no                  | Print the signup URL instead of opening a browser, then wait for the key to arrive out of band. The wait is time-bounded: the global --timeout governs it (default 180s without the flag), and expiry exits 2 with a SIGNUP\_TIMEOUT envelope pointing at the `login --with-key` paste fallback — the process always terminates on its own |
| `--profile`    | `string`  | no                  | Name to store this login under                                                                                                                                                                                                                                                                                                             |
| `--signup-id`  | `string`  | no                  | Pending signup id from a previous `signup --headless --email …` run — resume verification without restarting                                                                                                                                                                                                                               |

**Examples**

```bash theme={null}
octolens signup
octolens signup --no-browser
octolens signup --headless
octolens signup --headless --email you@corp.com --json
octolens signup --headless --signup-id 4f2a… --code 123456 --domain corp.com --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields.

| Field                      | Type                         | Description                                                                                                                                                                                  |
| -------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signedUp`                 | boolean                      | `true` when the workspace was created and the profile saved — both the browser handoff and the headless finishing run answer it (the headless step-1 run answers the `false` variant below). |
| `edition`                  | enum: `internal`, `customer` | The CLI build edition (same value `version` reports).                                                                                                                                        |
| `profile`                  | string \| null               | Name of the stored profile this signup created.                                                                                                                                              |
| `workspace`                | object \| null               | The freshly created Agents workspace (`{organizationId, name, plan}`) — same shape `login` emits.                                                                                            |
| `workspace.organizationId` | string                       | Organization id.                                                                                                                                                                             |
| `workspace.name`           | string                       | Workspace name.                                                                                                                                                                              |
| `workspace.plan`           | string \| null               | Current plan — `Agents` for a fresh signup.                                                                                                                                                  |
| `actingAs`                 | object \| null               | Always `null` — a signup never acts on another workspace.                                                                                                                                    |
| `baseUrl`                  | string                       | The effective app base URL for this signup — what the REST transport targets.                                                                                                                |
| `pinnedBaseUrl`            | string \| null               | The deployment the minted key was verified against and persisted with the profile.                                                                                                           |

Two modes, one success document. Default (browser handoff): the browser runs the actual signup (Clerk sign-up, domain, workspace creation) and the document reports the credential the handoff delivered and validated. `--headless`: the minted API key is saved into the profile and never printed — `--json` carries no secret. The company domain defaults to your email's domain for work addresses: the finishing run completes without `--domain`, while a personal-provider email (gmail, outlook, yahoo, …) still requires it; an explicit `--domain` always wins. A wrong `--code` answers the server's `INVALID_CODE` envelope (exit 2); the attempt cap answers `SIGNUP_ATTEMPTS_EXCEEDED`, after which a fresh `--email` run restarts the flow. An interruption at ANY later point is equally recoverable by re-running with the same `--email`: a signup whose workspace never became usable is re-adopted after the new code is verified, and `EMAIL_ALREADY_REGISTERED` (409) answers only for a fully set-up account.

Without `--json`: A terminal prints the browser hand-off (or the emailed-code prompt flow with --headless), then one confirmation line naming the new workspace and profile.

Example output:

```json theme={null}
{
  "signedUp": true,
  "edition": "customer",
  "profile": "acme",
  "workspace": {
    "organizationId": "org_2abcDEFghij345",
    "name": "Acme",
    "plan": "Agents"
  },
  "actingAs": null,
  "baseUrl": "https://app.octolens.com",
  "pinnedBaseUrl": "https://app.octolens.com"
}
```

Headless step 1 (`--headless --email` without `--code`) answers the pending-signup coordinates instead and exits 0 — the emailed code cannot be read by this process.

| Field              | Type           | Description                                                                                                                                                                                                                                                                       |
| ------------------ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signedUp`         | boolean        | Always `false` for the step-1 document.                                                                                                                                                                                                                                           |
| `signupId`         | string         | Pending signup id — quote it back via `--signup-id` to finish.                                                                                                                                                                                                                    |
| `email`            | string         | Normalized email the code was sent to.                                                                                                                                                                                                                                            |
| `expiresInSeconds` | integer        | How long the emailed code stays valid.                                                                                                                                                                                                                                            |
| `derivedDomain`    | string \| null | The company domain the finishing run defaults to when `--domain` is omitted — your email's domain for work addresses (`you@corp.com` → `corp.com`); `null` for personal providers (gmail, outlook, yahoo, …), which still require `--domain`. An explicit `--domain` always wins. |
| `next`             | string         | The exact finishing command, with `--signup-id` filled in — it only includes `--domain` when the domain could not be derived from the email.                                                                                                                                      |

Example output:

```json theme={null}
{
  "signedUp": false,
  "signupId": "4f2a9c81d6e05b37a1428f6f9c03d5aa",
  "email": "you@corp.com",
  "expiresInSeconds": 600,
  "derivedDomain": "corp.com",
  "next": "octolens signup --headless --signup-id 4f2a9c81d6e05b37a1428f6f9c03d5aa --code <code from the email>"
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE · `8` CANCELLED. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens switch`

Switch the active workspace profile

**Arguments**

| Argument  | Type     | Required | Description                                   |
| --------- | -------- | -------- | --------------------------------------------- |
| `PROFILE` | `string` | optional | Profile name (or 1-based number) to switch to |

**Examples**

```bash theme={null}
octolens switch acme
octolens switch --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields.

| Field     | Type    | Description                                                               |
| --------- | ------- | ------------------------------------------------------------------------- |
| `active`  | string  | The now-active profile name.                                              |
| `changed` | boolean | `false` when the requested profile was already active (idempotent no-op). |

Without `--json`: A terminal prints one confirmation line (interactive runs list the profiles and prompt first).

Example output:

```json theme={null}
{
  "active": "globex",
  "changed": true
}
```

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE · `8` CANCELLED. The full map is on [Exit codes](/docs/cli/contract/exit-codes).

## `octolens whoami`

Show the active login: who you are, workspace, plan, and scope

**Examples**

```bash theme={null}
octolens whoami
octolens whoami --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `GET /api/v2/auth`.

| Field                      | Type                         | Description                                                                                                                                                                                |
| -------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `edition`                  | enum: `internal`, `customer` | The CLI build edition (same value `version` reports).                                                                                                                                      |
| `profile`                  | string \| null               | The stored profile supplying the credential — `null` when auth comes from the environment.                                                                                                 |
| `workspace`                | object \| null               | The authenticated workspace (`{organizationId, name, plan}`) — same shape `login` emits.                                                                                                   |
| `workspace.organizationId` | string                       | Organization id.                                                                                                                                                                           |
| `workspace.name`           | string                       | Workspace name.                                                                                                                                                                            |
| `workspace.plan`           | string \| null               | Current plan. `null` when none.                                                                                                                                                            |
| `actingAs`                 | object \| null               | Present when acting on another workspace (`{orgId, workspace?}`). `null` otherwise.                                                                                                        |
| `transport`                | enum: `direct`, `rest`       | The transport this run selected.                                                                                                                                                           |
| `authSource`               | string                       | Where the selected transport's credential came from (`profile`, `env`, …).                                                                                                                 |
| `scope`                    | string\[] \| null            | The credential's LIVE effective scopes (`read`/`write`/`admin`) from auth introspection — the preflight an agent checks before mutating. `null` only when scopes are genuinely unknowable. |
| `baseUrl`                  | string                       | The effective app base URL for this configuration.                                                                                                                                         |
| `ignoredEnv`               | string\[]                    | Env identity vars that are set but IGNORED for the selected transport (e.g. `OCTOLENS_ORG_ID` on REST, where the API key selects the workspace). Empty when nothing is ignored.            |

Without `--json`: A terminal renders the identity a human cares about (OCT-1545): workspace name + company domain, the acting user's email (omitted when unavailable), a one-line company headline, the plan label (Agents renders as `Sandbox`) and scope. Org id / edition / transport / auth source stay JSON-only, and the base URL prints ONLY when it is non-default.

<Accordion title="Example output">
  ```json theme={null}
  {
    "edition": "customer",
    "profile": "acme",
    "workspace": {
      "organizationId": "org_2abcDEFghij345",
      "name": "Acme",
      "plan": "Pro_v3"
    },
    "actingAs": null,
    "transport": "rest",
    "authSource": "profile",
    "scope": [
      "read",
      "write"
    ],
    "baseUrl": "https://app.octolens.com",
    "ignoredEnv": []
  }
  ```
</Accordion>

**Exit codes** — `0` OK · `1` UNEXPECTED · `2` USAGE. The full map is on [Exit codes](/docs/cli/contract/exit-codes).
