• Start
Sign In

surrealctl

/

Commands

token

Reference for surrealctl token — listing, creating and revoking personal access tokens, and browsing the scopes a token can be granted.

surrealctl token manages personal access tokens: the sdbp_… credentials that authenticate CI jobs and automation against the control plane.

Usage
surrealctl token <COMMAND> [OPTIONS]surrealctl tokens <COMMAND> [OPTIONS]
VerbPurposeAlias
listList your personal access tokensls
createCreate a personal access token
deleteRevoke a personal access tokenrm
scopesList the scopes a token can be granted
Important

Every verb in this group needs an interactive login session. A personal access token is refused locally, before any request is sent, and exits 4. This is deliberate and worth keeping: a leaked token must not be able to mint its own replacements, nor revoke the one an operator would use to clean up after it. The refusal is decided by the credential's kind rather than by its scopes, so no token can be minted carrying something that lifts it.

What a token gets instead
Managing personal access tokens needs an interactive login session, so nothing was sent.

Sign in with:  surrealctl auth login

Being signed out is a different answer with a different code: 3, not 4. Sign in with auth login.

These tokens are not database credentials. For a token a SurrealDB client can authenticate with, use instance token.

List your personal access tokens.

Usage
surrealctl token list [OPTIONS]

This command takes no positional arguments.

Accepts the list presentation flags and nothing else. Column ids are label, id, scopes, created_at and expires_at, with user_id under --wide.

surrealctl token list
Output
LABEL              ID                    SCOPES                  CREATED       EXPIRES
build runner       67upif0m8sh1cn1p2c8t  read:cloud              2 months ago  in 4 days
nightly export     6a2k9lqzt4v8bn3m1x5c  read:cloud              3 days ago    never
Tokens expiring within the week
surrealctl token list --json | jq -r '.[] | .label + " " + .expires_at'

Only the label, the id, the scopes and the timestamps are stored — the secret itself exists once, at creation. A token with no expiry carries the 9999-12-31T23:59:59Z sentinel under --json.

Create a personal access token.

Usage
surrealctl token create [OPTIONS] <LABEL>

Arguments

NameDescription
<LABEL>
required
What this token is for, shown in every listing. Between 1 and 120 characters.

Options

NameDefaultDescription
--scope<SCOPE>
NoneA scope to grant. Repeat the flag to grant several, up to 32.
--expires-in<DAYS>
30Days until the token expires, between 1 and 365, or the literal never. Defaults to the API's 30 days.
--reveal
NonePrint the secret even when stdout is a terminal.

The secret is returned exactly once. Capture it on creation or create another one.

Capture the secret into a variable
TOKEN=$(surrealctl token create "build runner" --scope read:cloud | tail -1)
Several scopes, and a shorter life
surrealctl token create "nightly export" \
    --scope read:cloud \
    --scope write:cloud-instances \
    --expires-in 90 \
    | tail -1 > /run/secrets/surrealctl

Output is a detail view with the secret stripped, then a success line, then the bare secret as the last line on stdout — so | tail -1 is the whole capture recipe. The footer names the token's id rather than its label, because a label may contain spaces.

Warning

This is the one command in the whole CLI with no --json form. Passing --json is a usage error, exit 2, raised before anything is minted.

Passing --json
`token create` has no --json form. The secret is returned exactly once, and it can neither go inside
the document nor share stdout with it.
Run it without --json and take the last line:
  surrealctl token create <label> | tail -1

Refusals, all exit 2 and all before the request:

  • stdout is a terminal and --reveal was not passed:

Refusing to print a secret to a terminal, where it would stay in your scrollback.
Pipe it:  surrealctl token create <label> | tail -1
Or pass --reveal if you meant to see it.
  • A label outside 1 to 120 characters.

  • More than 32 scopes: A token carries at most 32 scopes; 40 were given.

  • An --expires-in outside 1 to 365 days, unless it is the literal never.

Warnings before the request:

  • --expires-in never warns, because the API's own schema calls a non-expiring token discouraged.

  • No --scope at all notes that the token will be permitted nothing, and points at token scopes.

Scopes are not pre-checked against the catalogue. An ungrantable scope answers 403 naming the problem, which is more useful than the bare 400 the API gives for everything else.

Revoke a personal access token.

Usage
surrealctl token delete [OPTIONS] <TOKEN>

Arguments

NameDescription
<TOKEN>
required
The token, by id or label.

Options

NameDescription
--force
Revoke without confirming.
By label
surrealctl token delete "build runner"
By id, from a script
surrealctl token delete 67upif0m8sh1cn1p2c8t --force --json

Refusals. The confirmation names the token. Declining exits 0. In a non-interactive session without --force or --yes, it exits 2 having sent nothing.

Note

Revocation is not instantaneous everywhere. The gateway caches token exchanges for a few minutes, so a revoked token may keep working for up to about ten minutes. Treat revocation as the start of the process when responding to a leak, and rotate whatever the token could reach.

List the scopes a token can be granted.

Usage
surrealctl token scopes [OPTIONS]

This command takes no positional arguments.

Accepts the list presentation flags and nothing else. Column ids are id, category and label, with description under --wide.

surrealctl token scopes
Just the ids, to paste into a create
surrealctl token scopes --columns id --no-header

This is the menu. auth scopes is the receipt: what the credential in hand actually carries.

Was this page helpful?