---
title: Auth (OTP login)
description: The two-step email OTP flow that provisions the CLI with no browser — login-request then login-complete — plus the error table and nextAction hints.
---

Scripto's CLI auth is a **two-step email OTP** that mints a durable `scripto_` API key and stores it as a local profile. It's **open signup**: an unknown email is registered when you complete the flow, so the same two commands serve both first-time signup and returning login.

<Info>

This is what makes "send the docs to an agent" work without a human in the browser: an agent can provision itself entirely from the terminal, given an email it can read a code from.

</Info>

## Step 1 — request a code

```bash
scripto auth login-request --email you@example.com
```

```text
✓ Sign-in code sent to you@example.com

  Then run:
    scripto auth login-complete --email you@example.com --code <6-digit-code>
```

This emails a 6-digit code and exits. It is public — no key required.

### Flags

| Flag | Purpose |
|---|---|
| `--email <email>` | **Required.** The email to sign in with. |
| `--api-url <url>` | Override the backend (e.g. a dev server). |
| `--profile <name>` | Use a profile's `baseUrl`. |
| `--json` | Emit the envelope. |

## Step 2 — complete login

```bash
scripto auth login-complete --email you@example.com --code 123456
```

```text
✓ Signed in

  Email:    you@example.com
  Profile:  you (now active)
  API key:  scripto_••••••••

  Try it:  scripto whoami
```

This verifies the code, mints a long-lived key bound to your user, and stores it as a profile that becomes active.

### Flags

| Flag | Purpose |
|---|---|
| `--email <email>` | **Required.** Same email as the request. |
| `--code <code>` | **Required.** The 6-digit code from the email. |
| `--name <name>` | Human-readable name for the minted key. |
| `--profile-name <name>` | Local profile name (auto-derived from the email otherwise). |
| `--api-url <url>` / `--profile <name>` / `--json` | As above. |

## Error handling

Failures return the `{ success: false, error: { code, message, nextAction? } }` envelope and exit non-zero. Common cases:

| Situation | `code` | Typical `nextAction` |
|---|---|---|
| Missing/invalid email | `invalid-argument` | `Pass --email <your-email> to: scripto auth login-request` |
| Missing code | `invalid-argument` | `request a new code with: scripto auth login-request` |
| Wrong or expired code | `invalid-argument` | `request a new code with: scripto auth login-request` |
| Send failed | `internal` | retry shortly |

<Note>

When you script this flow, read `nextAction` and surface it to the user verbatim. It tells you exactly what to do next.

</Note>

## Already have a key?

Skip OTP entirely:

```bash
scripto config set --api-key scripto_your_key_here
```

## Next

- **[Configuration](/cli/configuration)** — where the minted profile lives.
- **[CLI auth endpoints](/api-reference/cli-auth)** — the HTTP routes behind these commands.
