Skip to content

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).

Terminal window
alter auth login

This 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:read

It 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:

Terminal window
# Read-only session
alter auth login --scopes dashboard_apps:read,dashboard_keys:read
# Privileged session containing exactly these two permissions
alter auth login --scopes dashboard_keys:admin,dashboard_apps:delete

Scope names are validated before the browser opens, so a typo fails fast. See the scope reference below.

FlagApplies toBehavior
--token-file <path>Pre-minted PATRead the token from a file. Mutually exclusive with the other token channels.
--token-stdinPre-minted PATRead the token from stdin. Mutually exclusive with the other token channels.
--token <pat>Pre-minted PATRead the token from argv. The value is visible in shell history and process listings; prefer a file or stdin.
--base-url <url>Both flowsUse and persist an alternate API origin. HTTPS is required and trailing slashes are removed.
--dashboard-url <url>Browser flowOverride the consent-page origin when it cannot be derived from the API origin. HTTPS is required.
--scopes <list>Browser flowReplace the default requested scopes with a validated comma-separated list.
--bind-ip <ip-or-cidr>Browser flowBind 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-ipBrowser flowExplicitly 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.

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.

The cleanest option for CI — nothing is persisted to disk and the value never appears in process arguments.

Terminal window
export ALTER_PAT="alter_pat_..."
alter apps list

Keeps the value out of shell history and out of ps output.

Terminal window
umask 077 && printf '%s' "$PAT" > ~/alter-pat.txt
alter auth login --token-file ~/alter-pat.txt

Pipe the token in:

Terminal window
echo "$PAT" | alter auth login --token-stdin

Passing 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.

After a successful alter auth login, the PAT is resolved in this order (highest precedence first):

  1. ALTER_PAT environment variable — the canonical CI / headless source.
  2. OS keychain — macOS Keychain, Linux Secret Service / gnome-keyring, or Windows Credential Manager. This is the default location after an interactive login.
  3. Plaintext fallback file at $XDG_CONFIG_HOME/alter/auth.toml, or ~/.config/alter/auth.toml when XDG_CONFIG_HOME is unset (mode 0600) — 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:

Terminal window
xcode-select --install
npm install -g @alter-ai/cli
Terminal window
sudo apt install libsecret-1-dev gnome-keyring
npm install -g @alter-ai/cli
Terminal window
# Show the active PAT, its scopes, and expiry
alter auth status
# Same view, under the pats namespace
alter pats whoami
# Forget the locally-stored PAT (does NOT revoke it server-side)
alter auth logout

alter 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 returns exit code 3 when no credential resolves, but its explicit backend probe returns generic code 1 when a resolved PAT is rejected. pats whoami uses the same generic code for a rejected resolved PAT. Regular resource commands that use the shared authenticated-command path map a backend 401 to code 3.

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.

A PAT’s scopes are <resource>:<verb> strings. Each resource supports a fixed verb set:

ResourceVerbsUsed by
dashboard_appsread, write, admin, deleteapps
dashboard_keysread, write, adminkeys
dashboard_agentsread, write, adminagents
dashboard_providersread, write, admin, deleteproviders; delete is wildcard-excluded
dashboard_secretsread, write, admin, deletemanaged-secrets
dashboard_app_policyread, rules_create, rules_update, rules_deletepolicy — the rules_* verbs are mintable for API automation and consumed by alter policy rules …
dashboard_auditreadaudit
dashboard_identity_providerscreate, webhooksidentity-providers — both verbs must be admin-minted (see below)
dashboard_patsreadpats whoami
dashboard_grantsread, admingrants
dashboard_analyticsreadanalytics
dashboard_end_usersreadend-users
dashboard_brandingread, writebranding
dashboard_approvalsreadapprovals

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.

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.