Reference
Authentication
Sign in with a browser or a pre-minted PAT, and control where credentials are stored.
The CLI authenticates with a Personal Access Token (PAT) — the same credential the dashboard issues under Settings → Personal Access Tokens. A PAT carries a fixed scope set chosen at mint time; the CLI sends it on every request.
There are two ways to sign in: an interactive browser flow (best for laptops) and a pre-minted token (best for CI).
Interactive sign-in
Section titled “Interactive sign-in”alter auth loginThis opens the dashboard in the browser, waits for the Authorize click, and receives the freshly-minted PAT on a local listener. No copy-paste, and the token never lands in shell history.
With no --scopes flag, the browser flow requests this exact routine set:
dashboard_apps:read, dashboard_apps:write,dashboard_keys:read, dashboard_keys:write,dashboard_agents:read, dashboard_agents:write,dashboard_providers:read, dashboard_providers:write,dashboard_app_policy:read, dashboard_audit:read, dashboard_pats:read,dashboard_secrets:read, dashboard_secrets:write,dashboard_grants:readIt deliberately excludes every admin / delete permission, policy-rule
mutation, identity-provider trust/webhook permission, and the read-only
analytics, end-user, branding, and approvals families. Pass --scopes to
request a different set. The supplied list replaces the defaults; it does
not append to them. The one exception is dashboard_pats:read: the CLI always
adds it, because it verifies every sign-in by reading the new token’s own
metadata (the same call alter auth status makes), and a token without it
cannot complete the login. It is a read-only self-inspection permission, never
a widening. The consent page shows it as required and does not let it be
dropped, so the approved token always carries it.
# Read-only sessionalter auth login --scopes dashboard_apps:read,dashboard_keys:read
# Privileged session containing exactly these two permissions (plus dashboard_pats:read)alter auth login --scopes dashboard_keys:admin,dashboard_apps:deleteThe browser flow waits up to 10 minutes for the approval; if the page is left unapproved, the CLI exits with a timeout and the login can simply be re-run.
Scope names are validated before the browser opens, so a typo fails fast. See the scope reference below.
Login flags
Section titled “Login flags”| Flag | Applies to | Behavior |
|---|---|---|
--token-file <path> | Pre-minted PAT | Read the token from a file. Mutually exclusive with the other token channels. |
--token-stdin | Pre-minted PAT | Read the token from stdin. At a terminal this prompts with hidden input; a pipe or redirect is read non-interactively. Mutually exclusive with the other token channels. |
--token <pat> | Pre-minted PAT | Read the token from argv. The value is visible in shell history and process listings; prefer a file or stdin. |
--base-url <url> | Both flows | Use and persist an alternate API origin. HTTPS is required and trailing slashes are removed. |
--dashboard-url <url> | Browser flow | Override the consent-page origin when it cannot be derived from the API origin. HTTPS is required. |
--scopes <list> | Browser flow | Replace the default requested scopes with a validated comma-separated list. dashboard_pats:read is always added (CLI 0.9.2 and later). |
--bind-ip <ip-or-cidr> | Browser flow | Bind the minted PAT to one IPv4/IPv6 host or CIDR. Bare hosts normalize to /32 or /128; DNS names, zone IDs, malformed ranges, and every /0 catch-all are rejected. |
--no-bind-ip | Browser flow | Explicitly request an unbound PAT. This is also the current default, so the flag is a compatibility no-op. |
--bind-ip and --no-bind-ip use last-flag-wins semantics when both appear.
Neither binding flag nor --scopes may be combined with a pre-minted token,
because those properties were fixed when that PAT was minted.
Headless and CI
Section titled “Headless and CI”In an environment with no browser, mint a PAT in the dashboard (Settings → Personal Access Tokens → New token) and hand it to the CLI through one of these channels, in decreasing order of safety. Include dashboard_pats:read in its scopes: alter auth login and alter auth status verify the token by reading its own metadata, and a token without that permission is refused at sign-in with a message naming it.
The cleanest option for CI is a masked secret named ALTER_PAT. Configure it in your CI provider and let the provider inject it into the job environment — do not type a literal token into a shell command.
# ALTER_PAT is injected by the CI provider's secret storealter apps listKeeps the value out of shell history and out of ps output.
umask 077 && printf '%s' "$PAT" > ~/alter-pat.txtalter auth login --token-file ~/alter-pat.txtAt a terminal this prompts for the token with hidden input, so the value never enters argv, shell history, or the visible screen:
alter auth login --token-stdin# Paste the token at the prompt and press Enter — input stays hiddenWhen stdin is a pipe or redirect the token is read non-interactively instead, with no prompt. Use this in scripts where the value is already held in a variable or secret store:
printf '%s' "$PAT" | alter auth login --token-stdinPassing the token inline with --token <pat> works but is discouraged — the value is visible to other local users via ps and lands in shell history.
The CLI verifies the token authenticates before storing it, so a wrong paste fails immediately rather than on the next command.
Credential storage
Section titled “Credential storage”After a successful alter auth login, the PAT is resolved in this order (highest precedence first):
ALTER_PATenvironment variable — the canonical CI / headless source.- OS keychain — macOS Keychain, Linux Secret Service /
gnome-keyring, or Windows Credential Manager. This is the default location after an interactive login. - Plaintext fallback file at
$XDG_CONFIG_HOME/alter/auth.toml, or~/.config/alter/auth.tomlwhenXDG_CONFIG_HOMEis unset (mode0600) — used only when the OS keychain isn’t available on the host. The CLI prints a warning on every fallback save and warns on reads if the file is group- or world-readable.
If keychain support isn’t loading, install the platform build tools and reinstall:
xcode-select --installnpm install -g @alter-ai/clisudo apt install libsecret-1-dev gnome-keyringnpm install -g @alter-ai/cliFor the app and agent keys you mint with the CLI, which the CLI does not store, see Your Credentials.
Status and sign-out
Section titled “Status and sign-out”# Show the active PAT, its scopes, and expiryalter auth status
# Same view, under the pats namespacealter pats whoami
# Forget the locally-stored PAT (does NOT revoke it server-side)alter auth logoutalter auth logout only clears the local credential. To revoke a PAT so it can no longer be used anywhere, delete it in the dashboard.
ALTER_PAT has higher precedence than every stored credential and is not
modified by logout. If it remains exported, subsequent commands continue to
authenticate with that environment token; unset it separately. auth status
and pats whoami return exit code 3 both when no credential resolves and when
the backend rejects the resolved PAT (revoked, expired, or created before the
September 2026 key-security upgrade), so a script can treat 3 as “sign in
again”. A PAT that lacks the scope needed to read itself returns 7, and a
backend that is temporarily unavailable returns the generic 1 — retry
instead of signing in again. Regular resource commands map a backend 401 to
code 3 the same way.
Self-hosted and staging
Section titled “Self-hosted and staging”By default the CLI talks to Alter’s production API. For an alternate
deployment, pass --base-url during login; that origin is stored with the PAT
and reused by later commands. The browser flow derives the dashboard origin
from it, or accepts --dashboard-url when the origins do not follow the
standard naming pattern. Both flags require https://. --dashboard-url is
ignored by the pre-minted-token flow because no browser is opened.
Scopes
Section titled “Scopes”A PAT’s scopes are <resource>:<verb> strings. Each resource supports a fixed verb set:
| Resource | Verbs | Used by |
|---|---|---|
dashboard_apps | read, write, admin, delete | apps |
dashboard_keys | read, write, admin | keys |
dashboard_agents | read, write, admin | agents |
dashboard_providers | read, write, admin, delete | providers; delete is wildcard-excluded |
dashboard_secrets | read, write, admin, delete | managed-secrets |
dashboard_app_policy | read, rules_create, rules_update, rules_delete | policy — the rules_* verbs are mintable for API automation and consumed by alter policy rules …; CLI update/delete also require read for the before/after review |
dashboard_audit | read | audit — grants the runtime audit trail to any member; management-plane rows (key / provider / identity-provider lifecycle) narrow to the token owner’s own actions unless that owner is an organization admin, and audit integrity-check is admin-only. Checked at use time against the live role, like keys mint below. |
dashboard_identity_providers | create, webhooks | identity-providers — both verbs must be admin-minted (see below) |
dashboard_pats | read | pats whoami |
dashboard_grants | read, admin | grants |
dashboard_analytics | read | analytics |
dashboard_end_users | read | end-users |
dashboard_branding | read, write | branding |
dashboard_approvals | read | approvals |
Three resources separate delete into its own verb instead of bundling it under admin: dashboard_apps, dashboard_secrets, and dashboard_providers. Each delete is an irreversible cascade, so it requires an explicit opt-in at mint time and a server-enforced type-to-confirm value — the same posture as GitHub’s separate delete_repo scope. A token with write or admin can do everything except those cascade deletes. dashboard_app_policy applies the same explicit opt-in to its rules_update and rules_delete verbs: updating or deleting a deny rule can loosen enforcement, so neither is ever granted by a wildcard — select them by name at mint time (rules_create only ever restricts, so it stays a routine automation verb).
dashboard_identity_providers:create and :webhooks govern SSO trust configuration — an organization-admin area — so, like the wildcard-excluded delete/policy verbs, they are never granted by a wildcard and only an organization admin can mint a PAT carrying them: a non-admin’s alter auth login --scopes dashboard_identity_providers:create is refused at sign-in. (Creating an SDK API key via alter keys mint/rotate is likewise admin-only, but enforced at use time against the token owner’s role rather than at mint time — so dashboard_keys:write itself stays member-mintable.)
If a command returns exit code 7 (FORBIDDEN), the request was refused — most often because the PAT is valid but missing a scope. Start a new browser login with --scopes containing the complete desired set, or mint a broader PAT in the dashboard; a plain login only requests the routine default set and never upgrades the existing token implicitly. The same code is also returned when the organization’s plan does not include the feature (for example alter branding set without custom branding) — no PAT can satisfy that, so read the stderr line, which names which of the two applies.