> ## 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.

# Admin

> Administer the workspace: company profile, members, organization settings and billing.

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 billing`

Show your plan + usage; --web opens the subscription page in the browser

**Examples**

```bash theme={null}
octolens billing
octolens billing --json
octolens billing --web
```

**Returns**

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

| Field                    | Type           | Description                                                                                       |
| ------------------------ | -------------- | ------------------------------------------------------------------------------------------------- |
| `plan`                   | string \| null | Current subscription plan. `null` when no active plan.                                            |
| `isAnnualPlan`           | boolean        | Whether the subscription bills annually.                                                          |
| `usage`                  | object         | Plan usage counters — same shape as `org usage`.                                                  |
| `usage.plan`             | string \| null | Current subscription plan. The `*.limit` numbers already reflect it.                              |
| `usage.mentions.count`   | integer        | Mentions consumed in the current billing cycle.                                                   |
| `usage.mentions.limit`   | integer        | Mention allowance for the cycle (plan + extensions + purchased add-ons).                          |
| `usage.mentions.resetAt` | string \| null | When the mention counter resets (start of next cycle). `null` for plans without a reset schedule. |
| `usage.keywords.count`   | integer        | Live keyword count.                                                                               |
| `usage.keywords.limit`   | integer        | Keyword allowance (plan + purchased add-ons).                                                     |
| `billingUrl`             | string         | URL of the app's billing page for managing the subscription.                                      |

Composed from the workspace read and the usage read (no single backing endpoint). When flex (usage-based) pricing is enabled for the org, the usage object additionally carries `flex` (`{enabled: true, budgetCents, used, resetAt}`); it is absent otherwise. On the Agents plan the usage object additionally carries `searches` (`{used, limit, remaining}`) — the lifetime on-demand search allowance (it never resets), read from the canonical quota method; it is absent on every other plan.

Without `--json`: A terminal renders the plan line, the usage block, and the billing-page URL.

<Accordion title="Example output">
  ```json theme={null}
  {
    "plan": "Pro_v3",
    "isAnnualPlan": false,
    "usage": {
      "plan": "Pro_v3",
      "mentions": {
        "count": 1240,
        "limit": 5000,
        "resetAt": "2026-09-01T00:00:00.000Z"
      },
      "keywords": {
        "count": 7,
        "limit": 15
      }
    },
    "billingUrl": "https://app.octolens.com/settings/billing"
  }
  ```
</Accordion>

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

## `octolens company get`

Show the monitored company profile

**Examples**

```bash theme={null}
octolens company get
octolens company get --json
```

**Returns**

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

| Field                      | Type           | Description                                                                     |
| -------------------------- | -------------- | ------------------------------------------------------------------------------- |
| `id`                       | integer        | Internal company profile id.                                                    |
| `name`                     | string         | Company display name — the AI's subject.                                        |
| `domain`                   | string         | Primary domain, no scheme.                                                      |
| `website`                  | string         | Full website URL.                                                               |
| `logo`                     | string \| null | Logo image URL. `null` if not enriched yet.                                     |
| `industry`                 | string         | High-level industry classification, injected into AI prompts.                   |
| `sector`                   | string         | Finer-grained sector beneath `industry`.                                        |
| `tags`                     | string         | Comma-separated category tags — additional AI relevance context.                |
| `description`              | string         | Prose description of the company. Fed into every relevance prompt.              |
| `linkedin`                 | string \| null | LinkedIn company slug. `null` if not set.                                       |
| `twitter`                  | string \| null | X/Twitter handle(s) without `@`, comma-separated.                               |
| `relevanceContext`         | string \| null | Short disambiguation sentence injected into every relevance prompt.             |
| `productUseCases`          | string \| null | Free-text product use cases, injected into relevance prompts.                   |
| `competitors`              | string \| null | JSON-encoded competitor list (`[{"name", "description"?}]`) stored as a string. |
| `companyMoat`              | string \| null | Prose description of the competitive advantage.                                 |
| `relevanceGuidelines`      | string \| null | Org-specific guidance injected into the relevance-scoring prompt.               |
| `classificationGuidelines` | string \| null | Org-specific guidance injected into the post-classification/tagging prompt.     |

Without `--json`: A terminal renders the monitored company profile.

<Accordion title="Example output">
  ```json theme={null}
  {
    "id": 12,
    "name": "Acme",
    "domain": "acme.com",
    "website": "https://acme.com",
    "logo": "https://logo.clearbit.com/acme.com",
    "industry": "Technology",
    "sector": "Developer Tools",
    "tags": "B2B,SaaS,Developer Tools",
    "description": "Acme builds cloud storage infrastructure for developers.",
    "linkedin": "acme",
    "twitter": "acme",
    "relevanceContext": "Acme is a cloud storage company, not the cartoon.",
    "productUseCases": "Store and sync build artifacts across CI runs.",
    "competitors": "[{\"name\":\"Globex\",\"description\":\"Enterprise storage suite\"}]",
    "companyMoat": "Deep integrations with every major IDE.",
    "relevanceGuidelines": "Posts asking for storage recommendations are relevant.",
    "classificationGuidelines": null
  }
  ```
</Accordion>

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

## `octolens company update`

Update the monitored company profile (name, description, AI guidelines)

**Flags**

| Flag                          | Type     | Required (headless) | Description                                                                     |
| ----------------------------- | -------- | ------------------- | ------------------------------------------------------------------------------- |
| `--classification-guidelines` | `string` | no                  | Extra guidance injected into the post-classification/tagging prompt             |
| `--company-moat`              | `string` | no                  | Prose description of your competitive advantage                                 |
| `--competitors`               | `string` | no                  | JSON-encoded competitors list (opaque)                                          |
| `--description`               | `string` | no                  | Prose description fed into every relevance prompt                               |
| `--linkedin`                  | `string` | no                  | LinkedIn company slug                                                           |
| `--logo`                      | `string` | no                  | URL to a public logo image (absolute http(s) URL)                               |
| `--name`                      | `string` | no                  | Company display name (the AI's subject)                                         |
| `--product-use-cases`         | `string` | no                  | Free-text list of what the product does / typical use cases                     |
| `--relevance-context`         | `string` | no                  | Short disambiguation sentence (≤400 chars) injected into every relevance prompt |
| `--relevance-guidelines`      | `string` | no                  | Extra guidance injected into the relevance-scoring prompt                       |
| `--twitter`                   | `string` | no                  | X/Twitter handle(s), comma-separated, no @                                      |

**Examples**

```bash theme={null}
octolens company update --description 'Cloud platform for frontend teams'
octolens company update --relevance-context 'Vercel is a cloud platform, not a vehicle brand'
octolens company update --relevance-guidelines '...' --json
```

**Returns**

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

| Field                      | Type           | Description                                                                     |
| -------------------------- | -------------- | ------------------------------------------------------------------------------- |
| `id`                       | integer        | Internal company profile id.                                                    |
| `name`                     | string         | Company display name — the AI's subject.                                        |
| `domain`                   | string         | Primary domain, no scheme.                                                      |
| `website`                  | string         | Full website URL.                                                               |
| `logo`                     | string \| null | Logo image URL. `null` if not enriched yet.                                     |
| `industry`                 | string         | High-level industry classification, injected into AI prompts.                   |
| `sector`                   | string         | Finer-grained sector beneath `industry`.                                        |
| `tags`                     | string         | Comma-separated category tags — additional AI relevance context.                |
| `description`              | string         | Prose description of the company. Fed into every relevance prompt.              |
| `linkedin`                 | string \| null | LinkedIn company slug. `null` if not set.                                       |
| `twitter`                  | string \| null | X/Twitter handle(s) without `@`, comma-separated.                               |
| `relevanceContext`         | string \| null | Short disambiguation sentence injected into every relevance prompt.             |
| `productUseCases`          | string \| null | Free-text product use cases, injected into relevance prompts.                   |
| `competitors`              | string \| null | JSON-encoded competitor list (`[{"name", "description"?}]`) stored as a string. |
| `companyMoat`              | string \| null | Prose description of the competitive advantage.                                 |
| `relevanceGuidelines`      | string \| null | Org-specific guidance injected into the relevance-scoring prompt.               |
| `classificationGuidelines` | string \| null | Org-specific guidance injected into the post-classification/tagging prompt.     |

Without `--json`: A terminal prints a confirmation line and the profile after the update.

<Accordion title="Example output">
  ```json theme={null}
  {
    "id": 12,
    "name": "Acme",
    "domain": "acme.com",
    "website": "https://acme.com",
    "logo": "https://logo.clearbit.com/acme.com",
    "industry": "Technology",
    "sector": "Developer Tools",
    "tags": "B2B,SaaS,Developer Tools",
    "description": "Acme builds cloud storage infrastructure for developers.",
    "linkedin": "acme",
    "twitter": "acme",
    "relevanceContext": "Acme is a cloud storage company, not the cartoon.",
    "productUseCases": "Store and sync build artifacts across CI runs.",
    "competitors": "[{\"name\":\"Globex\",\"description\":\"Enterprise storage suite\"}]",
    "companyMoat": "Deep integrations with every major IDE.",
    "relevanceGuidelines": "Posts asking for storage recommendations are relevant.",
    "classificationGuidelines": null
  }
  ```
</Accordion>

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

## `octolens members invitations`

List invitations that haven't been accepted yet

**Flags**

| Flag      | Type      | Required (headless) | Description                                                  |
| --------- | --------- | ------------------- | ------------------------------------------------------------ |
| `--all`   | `boolean` | no                  | Show the full collection (the default for this bounded list) |
| `--limit` | `integer` | no                  | Show only the first N items (mutually exclusive with --all)  |

**Examples**

```bash theme={null}
octolens members invitations
octolens members invitations --json
```

**Returns**

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

| Field                   | Type                    | Description                                                          |
| ----------------------- | ----------------------- | -------------------------------------------------------------------- |
| `data`                  | object\[]               | Invitations sent but not yet accepted.                               |
| `data[].id`             | string                  | Invitation id (`orginv_…`) — what `members rm` accepts to revoke it. |
| `data[].email`          | string                  | Invitee's email address.                                             |
| `data[].role`           | enum: `admin`, `member` | Role assigned when the invitation is accepted.                       |
| `data[].createdAt`      | string                  | When the invitation was created, ISO 8601.                           |
| `pagination.nextCursor` | null                    | Always `null`: the whole invitation set fits one response.           |

Without `--json`: A terminal renders an aligned invitation table; piped stdout emits one tab-delimited record per invitation.

Example output:

```json theme={null}
{
  "data": [
    {
      "id": "orginv_3Ciq0qskipF0g0gxlfLckBtnXk2",
      "email": "bob@example.com",
      "role": "member",
      "createdAt": "2026-07-01T08:00:00.000Z"
    }
  ],
  "pagination": {
    "nextCursor": null
  }
}
```

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

## `octolens members invite`

Invite a member by email (admin only)

**Flags**

| Flag      | Type                    | Required (headless) | Description                                                      |
| --------- | ----------------------- | ------------------- | ---------------------------------------------------------------- |
| `--email` | `string`                | yes (headless)      | Address to send the invitation to                                |
| `--role`  | enum: `admin`, `member` | no                  | Role to assign when the invitation is accepted (default: member) |

**Examples**

```bash theme={null}
octolens members invite --email teammate@acme.com
octolens members invite --email admin@acme.com --role admin --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `POST /api/v2/org/members/invite`.

| Field            | Type                    | Description                                                                                                                     |
| ---------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `id`             | string                  | Invitation id (`orginv_…`) — what `members rm` accepts to revoke it.                                                            |
| `email`          | string                  | Invitee's email address.                                                                                                        |
| `role`           | enum: `admin`, `member` | Role assigned when the invitation is accepted.                                                                                  |
| `createdAt`      | string                  | When the invitation was created, ISO 8601.                                                                                      |
| `alreadyInvited` | boolean                 | `true` when the address already had an outstanding invitation and this IS it — no second email was sent (idempotent re-invite). |

Without `--json`: A terminal prints one confirmation line naming the invitee and role.

Example output:

```json theme={null}
{
  "id": "orginv_3Ciq0qskipF0g0gxlfLckBtnXk2",
  "email": "bob@example.com",
  "role": "member",
  "createdAt": "2026-07-01T08:00:00.000Z",
  "alreadyInvited": false
}
```

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

## `octolens members list`

List the organization's members

**Flags**

| Flag      | Type      | Required (headless) | Description                                                  |
| --------- | --------- | ------------------- | ------------------------------------------------------------ |
| `--all`   | `boolean` | no                  | Show the full collection (the default for this bounded list) |
| `--limit` | `integer` | no                  | Show only the first N items (mutually exclusive with --all)  |

**Examples**

```bash theme={null}
octolens members list
octolens members list --json
octolens members list --limit 5
```

**Returns**

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

| Field                   | Type                    | Description                                                          |
| ----------------------- | ----------------------- | -------------------------------------------------------------------- |
| `data`                  | object\[]               | Every accepted member of the workspace (bounded — no paging needed). |
| `data[].id`             | string                  | Membership id (`orgmem_…`), not user id — what `members rm` accepts. |
| `data[].userId`         | string                  | User id of the member.                                               |
| `data[].email`          | string \| null          | Primary email on the member's profile.                               |
| `data[].firstName`      | string \| null          | First name, if set on the profile.                                   |
| `data[].lastName`       | string \| null          | Last name, if set on the profile.                                    |
| `data[].role`           | enum: `admin`, `member` | Role within the organization.                                        |
| `data[].createdAt`      | string                  | When the member joined, ISO 8601.                                    |
| `pagination.nextCursor` | null                    | Always `null`: the whole member set fits one response.               |

Pending invitations are NOT in this list — read `members invitations` for those.

Without `--json`: A terminal renders an aligned member table; piped stdout emits one tab-delimited record per member.

<Accordion title="Example output">
  ```json theme={null}
  {
    "data": [
      {
        "id": "orgmem_3CiC5zwdWxMVsGsePg1xYkHbQO0",
        "userId": "user_2abcDEFghij345",
        "email": "alice@example.com",
        "firstName": "Alice",
        "lastName": "Nguyen",
        "role": "admin",
        "createdAt": "2026-02-01T12:00:00.000Z"
      }
    ],
    "pagination": {
      "nextCursor": null
    }
  }
  ```
</Accordion>

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

## `octolens members rm`

Remove a member or revoke a pending invitation (admin only; confirms on a TTY, --yes headless)

**Arguments**

| Argument | Type     | Required | Description                                                    |
| -------- | -------- | -------- | -------------------------------------------------------------- |
| `MEMBER` | `string` | required | Membership id (orgmem\_…), invitation id (orginv\_…), or email |

**Flags**

| Flag    | Type      | Required (headless) | Description                  |
| ------- | --------- | ------------------- | ---------------------------- |
| `--yes` | `boolean` | yes (headless)      | Skip the confirmation prompt |

**Examples**

```bash theme={null}
octolens members rm teammate@acme.com --yes
octolens members rm orgmem_3CiC5zwdWxMVsGsePg1xYkHbQO0 --yes --json
octolens members rm orginv_3HAkTMpGYup14blURlIW2fyzxFq --yes
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `DELETE /api/v2/org/members/{id}`.

| Field     | Type    | Description                                                                                           |
| --------- | ------- | ----------------------------------------------------------------------------------------------------- |
| `ok`      | boolean | Always `true` — a refused removal answers the error envelope instead.                                 |
| `id`      | string  | The membership id (`orgmem_…`) that was removed — or the invitation id (`orginv_…`) that was revoked. |
| `removed` | boolean | Always `true` on success.                                                                             |

Without `--json`: A terminal prints one confirmation line naming what was removed or revoked.

Example output:

```json theme={null}
{
  "ok": true,
  "id": "orgmem_3CiC5zwdWxMVsGsePg1xYkHbQO0",
  "removed": true
}
```

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

## `octolens org get`

Show the authenticated workspace (name, plan, platforms)

**Examples**

```bash theme={null}
octolens org get
octolens org get --json
```

**Returns**

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

| Field                  | Type                 | Description                                                                          |
| ---------------------- | -------------------- | ------------------------------------------------------------------------------------ |
| `organizationId`       | string               | Organization id (`org_…`). Immutable.                                                |
| `name`                 | string               | Workspace name, shown in email notifications and in-app headers.                     |
| `plan`                 | string \| null       | Current subscription plan (e.g. `Free_trial`, `Pro_v3`). `null` when no active plan. |
| `isAnnualPlan`         | boolean              | Whether the subscription bills annually.                                             |
| `platforms`            | `"all"` \| string\[] | Org-wide platform setting: the literal `all`, or an explicit list of platform slugs. |
| `createdAt`            | string               | When the organization was created, ISO 8601.                                         |
| `onboardingFinishedAt` | string \| null       | When onboarding finished. `null` while still onboarding.                             |
| `freeTrialExpired`     | boolean              | Whether the free trial has ended without a paid plan.                                |

Without `--json`: A terminal renders the workspace's settings panel.

Example output:

```json theme={null}
{
  "organizationId": "org_2abcDEFghij345",
  "name": "Acme",
  "plan": "Pro_v3",
  "isAnnualPlan": false,
  "platforms": "all",
  "createdAt": "2026-01-15T09:00:00.000Z",
  "onboardingFinishedAt": "2026-01-16T10:30:00.000Z",
  "freeTrialExpired": false
}
```

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

## `octolens org update`

Update workspace settings (name, monitored platforms)

**Flags**

| Flag          | Type     | Required (headless) | Description                                                                        |
| ------------- | -------- | ------------------- | ---------------------------------------------------------------------------------- |
| `--name`      | `string` | no                  | New workspace name                                                                 |
| `--platforms` | `string` | no                  | Platform to monitor org-wide (repeatable; pass `all` for every supported platform) |

**Examples**

```bash theme={null}
octolens org update --name 'Acme Corp'
octolens org update --platforms reddit --platforms twitter
octolens org update --platforms all --json
```

**Returns**

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

| Field                  | Type                 | Description                                                                          |
| ---------------------- | -------------------- | ------------------------------------------------------------------------------------ |
| `organizationId`       | string               | Organization id (`org_…`). Immutable.                                                |
| `name`                 | string               | Workspace name, shown in email notifications and in-app headers.                     |
| `plan`                 | string \| null       | Current subscription plan (e.g. `Free_trial`, `Pro_v3`). `null` when no active plan. |
| `isAnnualPlan`         | boolean              | Whether the subscription bills annually.                                             |
| `platforms`            | `"all"` \| string\[] | Org-wide platform setting: the literal `all`, or an explicit list of platform slugs. |
| `createdAt`            | string               | When the organization was created, ISO 8601.                                         |
| `onboardingFinishedAt` | string \| null       | When onboarding finished. `null` while still onboarding.                             |
| `freeTrialExpired`     | boolean              | Whether the free trial has ended without a paid plan.                                |

Without `--json`: A terminal prints a confirmation line and the workspace's settings after the update.

Example output:

```json theme={null}
{
  "organizationId": "org_2abcDEFghij345",
  "name": "Acme",
  "plan": "Pro_v3",
  "isAnnualPlan": false,
  "platforms": "all",
  "createdAt": "2026-01-15T09:00:00.000Z",
  "onboardingFinishedAt": "2026-01-16T10:30:00.000Z",
  "freeTrialExpired": false
}
```

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

## `octolens org usage`

Show mention/keyword usage against your plan limits

**Examples**

```bash theme={null}
octolens org usage
octolens org usage --json
```

**Returns**

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

| Field              | Type           | Description                                                                                       |
| ------------------ | -------------- | ------------------------------------------------------------------------------------------------- |
| `plan`             | string \| null | Current subscription plan. The `*.limit` numbers already reflect it.                              |
| `mentions.count`   | integer        | Mentions consumed in the current billing cycle.                                                   |
| `mentions.limit`   | integer        | Mention allowance for the cycle (plan + extensions + purchased add-ons).                          |
| `mentions.resetAt` | string \| null | When the mention counter resets (start of next cycle). `null` for plans without a reset schedule. |
| `keywords.count`   | integer        | Live keyword count.                                                                               |
| `keywords.limit`   | integer        | Keyword allowance (plan + purchased add-ons).                                                     |

When flex (usage-based) pricing is enabled for the org, the usage object additionally carries `flex` (`{enabled: true, budgetCents, used, resetAt}`); it is absent otherwise. On the Agents plan the usage object additionally carries `searches` (`{used, limit, remaining}`) — the lifetime on-demand search allowance (it never resets), read from the canonical quota method; it is absent on every other plan.

Without `--json`: A terminal renders the usage block with plan, mention and keyword meters.

Example output:

```json theme={null}
{
  "plan": "Pro_v3",
  "mentions": {
    "count": 1240,
    "limit": 5000,
    "resetAt": "2026-09-01T00:00:00.000Z"
  },
  "keywords": {
    "count": 7,
    "limit": 15
  }
}
```

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

## `octolens upgrade`

Open the upgrade page already signed in (single-use link; on a paid plan it opens billing)

**Flags**

| Flag           | Type      | Required (headless) | Description                                                                                                                               |
| -------------- | --------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `--no-browser` | `boolean` | no                  | Print the upgrade link instead of opening a browser. The link is single-use and expires, so open it promptly on a machine with a browser. |

**Examples**

```bash theme={null}
octolens upgrade
octolens upgrade --no-browser
octolens upgrade --json
```

**Returns**

With `--json`, stdout carries one JSON document with these fields. Backed by the v2 API operation `POST /api/v2/org/upgrade-link`.

| Field              | Type           | Description                                                                                                                               |
| ------------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `url`              | string         | Single-use, short-lived sign-in URL. Opening it lands on `destination` already authenticated — no sign-in step. Redeeming it twice fails. |
| `destination`      | string         | App path the link lands on: `/me/upgrade?src=agents` on the Agents plan, `/me/subscription` (billing) on any other plan.                  |
| `plan`             | string \| null | The workspace's current plan. `null` when no active plan.                                                                                 |
| `expiresAt`        | string         | ISO-8601 instant after which the link can no longer be redeemed.                                                                          |
| `expiresInSeconds` | integer        | Seconds the link stays redeemable from the moment it was minted.                                                                          |
| `opened`           | boolean        | Whether the CLI launched a browser. Always `false` in `--json`/piped runs and with `--no-browser` — the URL is the contract either way.   |

The v2 response (`createUpgradeLink`) plus the CLI-local `opened` flag. The link is minted for the calling credential's user and every mint is audit-logged server-side.

Without `--json`: A terminal prints the single-use URL, its expiry, and — on an interactive TTY without `--no-browser` — opens it in the default browser.

Example output:

```json theme={null}
{
  "url": "https://app.octolens.com/me/upgrade-auth?__clerk_ticket=sit_2h9…&orgId=org_2h9…&dest=%2Fme%2Fupgrade%3Fsrc%3Dagents",
  "destination": "/me/upgrade?src=agents",
  "plan": "Agents",
  "expiresAt": "2026-08-11T12:10:00.000Z",
  "expiresInSeconds": 600,
  "opened": false
}
```

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