Authentication
peppy auth login authenticates the CLI against the Peppy backend. Peppy is a public
OAuth client of the project’s identity provider (Zitadel): the CLI obtains a
bearer token through the browser and sends it to the backend, which validates it.
The CLI never sees your Google/passkey credentials. Those stay in the browser.
Commands
Section titled “Commands”| Command | What it does |
|---|---|
peppy auth login [--api-url <url>] [--no-browser] [--yes] | Logs in via the OAuth 2.0 Device Authorization Grant, caches the tokens, and federates this machine to your organization’s cloud router. |
peppy auth whoami (alias status) | Shows the current identity, backend, and token validity. --json for machine-readable output. |
peppy auth logout [--yes] | Revokes the access token on the backend (across replicas), deletes the local credentials, and de-federates this machine. |
--yes (-y) skips the daemon-restart confirmation prompt described under
Organization federation.
Logging in
Section titled “Logging in”peppy auth loginOn a terminal this prints a verification URL and a user code, then opens your browser at that URL (with the code pre-filled). Approve the request in the browser and the CLI stores the tokens. Subsequent commands reuse them: you log in once and stay logged in until the refresh token expires; expired access tokens are refreshed automatically.
Over SSH or anywhere without a browser, use --no-browser: the CLI prints the
URL and code and waits for you to approve them on another device.
peppy auth login --no-browserHow it works
Section titled “How it works”- The CLI fetches the public
GET {api_url}/cli/config, which returns theissuer, theclient_id, and the exactscopesto request. - It runs OIDC discovery against the
issuer({issuer}/.well-known/openid-configuration) to find the device and token endpoints. - It starts the device flow, opens the browser, and polls until you approve.
- It caches the tokens (and the
issuer/client_id, so refresh works offline) under~/.peppy/conf/credentials.json5.
Organization federation
Section titled “Organization federation”Logging in does more than cache a token: it stamps this machine with your
organization namespace (your account’s stable organization id) and federates
the peppy daemon’s local messaging router to your organization’s private cloud
router. Robots signed in to the same organization then interoperate across that
federation, while different organizations stay routing-isolated. Logged out, the
machine falls back to the local namespace, which never reaches the cloud router;
two logged-out machines on the same LAN still discover each other, but nothing
leaves the local network.
A session’s namespace is fixed once the daemon opens it, so changing it (logging
in or out) restarts the messaging daemon and wipes the running node stack.
When a daemon is running with user nodes, login and logout confirm first:
Logging in changes this machine's organization namespace, which restarts the messaging daemon and wipes the running node stack.Continue? [y/N]Pass --yes (-y) to skip the prompt. It is also skipped automatically when
stdin is not a terminal (so scripts and CI are never blocked), when no daemon is
running, or when the stack holds no user nodes; in each case the restart wipes
nothing.
login is strict about federation: after your credentials are saved it waits
for the daemon to establish the federation link and exits non-zero if it cannot
(no daemon running, the cloud router is unreachable or untrusted, or it times
out). You stay authenticated in that case (only the command fails), so re-run it
once the daemon is reachable. logout is best-effort and never fails on the
de-federation step. How long the daemon waits to resolve the cloud router is
bounded by federation.connect_timeout_secs.
Backend
Section titled “Backend”By default the CLI talks to the prod backend, https://api.peppy.bot. That URL
is stored in the resource_servers block of
~/.peppy/conf/peppy_config.json5 (see Daemon configuration),
seeded on first run and editable in place. To point at a different backend
without editing the file, use --api-url or PEPPY_API_URL.
The URL is resolved in precedence order: --api-url, then PEPPY_API_URL, then
resource_servers.api. Plain http is allowed only for local backends (loopback
/ *.localhost); anything else must be https.
CI and automation
Section titled “CI and automation”For non-interactive use, set PEPPY_API_KEY to a Zitadel service-user personal
access token (PAT). It is used directly as the bearer: no browser, no refresh,
and it is never written to disk. A PAT short-circuits every other credential
source, so CI never opens a browser. If the PAT is revoked, requests start
failing with 401 and you must rotate it. A PAT principal shows up as
kind: "machine" under peppy auth whoami.
Credential storage
Section titled “Credential storage”Tokens live at ~/.peppy/conf/credentials.json5, written owner-only (0600).
The root honours PEPPY_HOME.
Tokens are never printed and Authorization headers are redacted in verbose
output.
Logging out
Section titled “Logging out”peppy auth logoutThis calls POST {api_url}/logout, which denylists the presented access token
across all backend replicas (sub-second), then deletes the local credentials.
The effect is near-immediate for the logged-out token. It revokes only the
token you presented; a session on another device keeps working.
Logout also returns this machine to the local namespace and de-federates its
router, so, like login, it restarts the daemon and wipes the running node
stack, with the same confirmation prompt and --yes bypass (see
Organization federation).
Environment variables
Section titled “Environment variables”| Variable | Purpose |
|---|---|
PEPPY_API_KEY | PAT for non-interactive auth (highest-priority credential). |
PEPPY_API_URL | Override the backend base URL. |
PEPPY_HOME | Override the ~/.peppy data root (also moves the credentials file). |
NO_COLOR | Disable coloured output. |