# login, whoami and token

```sh
scribase login [--json] [--no-wait] [--scope <s>]... [--name <client>] [--no-browser] [--api-url <url>]
                                                     # device login: approve in the browser
scribase login --token <pat> [--api-url <url>]      # verify and store a personal access token
scribase login --with-token [--api-url <url>]       # the same, reading the token from stdin
scribase login --email <email> [--api-url <url>]    # built-in password (+ TOTP) sign-in
scribase logout                                      # delete the stored credentials
scribase whoami                                      # GET /v1/account
scribase token list                                  # GET /v1/account/tokens
scribase token create <name> [--expires-in-days N]   # POST /v1/account/tokens
scribase token revoke <token-id>                     # DELETE /v1/account/tokens/{id}
```

## login in the browser (device login)

```sh
scribase login
```

The CLI prints a link and a code such as `SCRB-7F3K-Q2MX`, opens your browser
when it runs in a terminal, and waits. In the console you check the code,
choose the organization, project, access level, capabilities and lifetime (8
hours by default), and approve. The CLI then receives its own agent token
(`scb_agt_…`) with exactly what you approved, and stores it; it never prints
it. This is the flow coding agents use, so nobody pastes a secret into a chat
(see [Why you never need to paste a secret key](https://docs.scribase.com/docs/agents/no-secret-keys.md)
and the [Device login API](https://docs.scribase.com/docs/api/device-login.md)).

| Flag | Effect |
|---|---|
| `--json` | One JSON line with `verification_uri_complete` and `user_code` right away, then one line with the outcome (`{"ok":true,"status":"approved",...}` or `{"ok":false,"error":{"code":"access_denied"}}`) |
| `--no-wait` | Print the link and code and exit; run `scribase login` again to pick the same request back up |
| `--scope <s>` | Request specific scopes (repeatable). Default `project:write sql:write migrations:write functions:deploy branches:write` |
| `--name <client>` | The name shown on the approval page |
| `--no-browser` | Do not open a browser |

`npx scribase login` does the same from the npm package, and
`npx scribase init` starts it automatically when you are not signed in.

## login with a personal access token

Create a token in the console under **Account > Access tokens**, then:

```sh
scribase login --with-token --api-url https://api.example.com < token.txt
```

`--with-token` reads the token from standard input so it stays out of your
shell history; `--token <pat>` takes it as an argument. The CLI checks it against `GET /v1/account` first and only
stores it if the API accepts it. A rejected token stores nothing.

## login with the built-in password

On a control plane running `SCRIBASE_AUTH_MODE=builtin` (see
[Built-in admin login](https://docs.scribase.com/docs/admin-login.md)):

```sh
scribase login --email you@example.com --api-url https://api.example.com
```

The password is read from the terminal with echo off, never from arguments. If
the account has an authenticator app, the CLI then asks for a code. The session
this stores ends after the control plane's idle and absolute timeouts (2 and 12
hours by default), so use a token for automation.

## Where credentials live

`login` keeps the token in the operating system keychain when there is one
(macOS Keychain through `security`, the Secret Service on Linux through
`secret-tool`) and writes only `api_url` to
`$XDG_CONFIG_HOME/scribase/credentials` (default
`~/.config/scribase/credentials`, mode `0600`). Without a keychain, or with
`SCRIBASE_NO_KEYCHAIN=1`, the token goes into that file too. `SCRIBASE_ACCESS_TOKEN` and
`SCRIBASE_API_URL` in the environment always take precedence over the stored
values, which is what CI should use. `logout` deletes the file and the keychain entry.

## Tokens

```sh
scribase whoami
scribase token create ci-deploy --expires-in-days 90
scribase token list
scribase token revoke <token-id>
```

`token create` prints the secret once. Scribase stores only a SHA-256 digest
and a short display prefix. `token list` shows metadata (name, prefix, created,
last used, expiry), never the secret. Revoke a token as soon as it may have
leaked.

Organization API keys for CI and bots are created in the console under
**Organization > API tokens** or over the API. See
[Access tokens & API keys](https://docs.scribase.com/docs/api/tokens.md).
