# Why you never need to paste a secret key

Paste a `service_role` key or a database password into Claude Code, Codex or
Cursor and a good agent will stop: it will not echo it, may refuse to use it,
and asks you to rotate it. It is right. A pasted secret lives on in the chat
transcript, in the model provider's logs and in whatever the agent writes
next, it grants everything, and it never expires.

Scribase is built so you never have to. Every way an agent gets access is
either a browser approval (no secret leaves the console) or a token designed
to be shared with an agent.

## Three ways in, none of them a secret key

### 1. `scribase login`: approve the agent in your browser

The agent runs one command and shows you a link and a short code:

```sh
scribase login --json
```

```json
{"event":"device_authorization","verification_uri":"https://console.scribase.com/device","verification_uri_complete":"https://console.scribase.com/device?user_code=SCRB-7F3K-Q2MX","user_code":"SCRB-7F3K-Q2MX","expires_in":600}
```

You open the link (the console asks you to sign in if needed), check that the
code matches, and see who is asking and for what: the client name, the
requested scopes, the address the request came from. Pick the organization,
one project (or all), the access level, the capabilities to allow and how
long it lasts (8 hours by default), then **Approve** or **Deny**.

The command, which has been polling, receives its own agent token and stores
it in the operating system keychain (macOS Keychain, or the Secret Service on
Linux through `secret-tool`), falling back to
`~/.config/scribase/credentials` with mode `0600`. It never prints the token;
the last line is only the outcome:

```json
{"ok":true,"status":"approved","organization_id":"acme","project_id":"web","scopes":["project:web:write","sql:write","migrations:write"],"expires_at":1790028000,"stored_in":"keychain"}
```

`npx scribase login` does the same without installing the full CLI, and
`npx scribase init` runs this flow automatically when you are not signed in.
Agents whose shell only shows output after a command ends can use
`--no-wait`: it prints the link and exits, and running `scribase login` again
picks the same request back up. This is the OAuth 2.0 Device Authorization
Grant (RFC 8628); see [Device login API](https://docs.scribase.com/docs/api/device-login.md).

### 2. MCP with OAuth

Add the hosted MCP server without a header, and your editor opens the
Scribase consent screen the first time it connects; you choose the access
there. See [Connect your agent](https://docs.scribase.com/docs/agents/setup.md).

### 3. A temporary project

No account at all:

```sh
npx scribase init --temp --yes --json
```

The agent gets a 72-hour project and an agent token scoped to it; you keep the
project by opening the claim link. See
[Temporary databases](https://docs.scribase.com/docs/agents/temporary-databases.md).

## Paste-safe agent tokens (`scb_agt_`)

Sometimes pasting is simplest: you are in a hosted agent with no browser, or
you want to hand one project to one session. Agent tokens are made for that.
On **Account > Access tokens**, **Copy for your AI agent** creates one and
copies a message the agent understands:

```text
Scribase agent token (scoped to project web, read/write, expires in 8h,
revocable at https://console.scribase.com/account/tokens). Designed to be
shared with coding agents: scb_agt_1p-rw-sqlw-mig-fn-x2609260412_3f9a...
```

The token describes itself. After `scb_agt_` comes a short, readable summary,
then the secret:

| Part | Meaning |
|---|---|
| `1p` / `np` / `all` / `org` | One project, several named projects, every project, or organization read only |
| `ro` / `rw` / `admin` | Read, read/write, or admin on those projects |
| `sql` / `sqlw` | Read-only SQL, or read-write SQL |
| `mig`, `fn`, `br` | Apply migrations, deploy functions, write branches |
| `keys` | Can read secret keys (never set by *Copy for your AI agent*) |
| `x2609260412` | Expires 2026-09-26 04:12 UTC (`xnever` if it does not expire) |

The summary is for people and agents to read; the server ignores it and
trusts only the token's digest, so editing it just makes the token invalid.

Why it is safe to share:

- **Scoped.** One project by default, and only the capabilities you chose. It
  can never do more than you can, and can never mint tokens, manage members,
  billing or SSO.
- **Short-lived.** 8 hours by default for copy-paste tokens.
- **Revocable.** One click on the tokens page, effective on the next request.
- **Audited.** Every request it makes is recorded (method, path, status,
  address) under *Activity*.
- **No secret keys.** Without the `keys:secret` scope, the keys route returns
  only the public (anon) key, and SQL never runs as a superuser. Copy-paste
  tokens never carry `keys:secret`.

The worst a leaked copy-paste token can do is what you allowed on one project
for a few hours, and you can see and stop it.

## Never paste these

| Secret | Instead |
|---|---|
| `service_role` / `sb_secret_` keys | They bypass row level security. Keep them in server-side env only; an agent that needs admin work gets a scoped token |
| Database passwords and connection strings | Agents use SQL and migrations through the API with an agent token |
| Personal access tokens (`scb_pat_`) | They are you, in every organization. Use `scribase login` or an agent token |
| Organization API keys (`sbk_`) | Meant for CI secret stores, not chats |

If one of these ended up in a chat, revoke or rotate it now (tokens under
**Account > Access tokens**, keys in the project's settings), then sign the
agent in with `scribase login`.

## What our agent rules say

The rules and skills we ship for Claude Code, Codex, Cursor and Windsurf
(see [Build with AI agents](https://docs.scribase.com/docs/agents.md)) tell the agent: never ask for API
keys, service-role keys or passwords; authenticate with `scribase login`, or
`npx scribase init --temp` for a throwaway project; a pasted `scb_agt_` token
is designed for agents and fine to use (kept in `SCRIBASE_ACCESS_TOKEN` or the
gitignored env file, never committed); anything else that looks like a secret
is not repeated back, and the user is asked to revoke it and use login.
