The gpilot CLI authenticates against GraphPilot. Every authenticated session is
scoped to a single organization. The credential the CLI uses (an access
token or an API key) carries that organization, and all commands run against it.
With no flags, the CLI asks how you want to authenticate and walks you through
it. In non-interactive mode it cannot ask, so
it refuses and exits 1 unless you pass --browser, --device or --api-key (or set
GPILOT_TOKEN instead of logging in). You can also pick the method up front:
Browser
gpilot auth login --browser
Opens your browser for an OAuth2 Authorization Code (PKCE) login. The CLI
starts a temporary local callback server, you sign in, and it captures the
result automatically. A request to that callback that does not carry this
login’s state gets an error page, and the login keeps waiting. Best for
everyday use on your own machine.
Device code
gpilot auth login --device
Shows a short code and a URL to open on any device. Best for headless or
remote machines where no browser is available locally.
API key
gpilot auth login --api-key
Authenticates with an organization API key (sk_…). Omit the value to be
prompted securely. Best for automation and shared machines.
A successful login makes the profile it logged into the active one. When that profile still
holds an unexpired login, gpilot auth login says so and does nothing; pass --force to log in
again. Naming the profile with the global --profile option always logs in again.
After a browser or device login, the profile is set to one organization, so the
session is immediately usable, with no extra step:
When you already chose an organization while signing in in the browser, and it is one you
belong to, the CLI takes that choice and asks nothing more.
Otherwise it shows the organizations you belong to and asks which one to work in. Your
selection mints an organization-scoped token and is saved as the profile’s active
organization.
When the account belongs to no organization yet, the login is saved without one, and the CLI
says so and names gpilot organization create as the next step.
✓ Login successful. Profile 'default' is now using organization Acme Corp (acme)
Skip the picker with --org when you already know the slug:
# Or pass the value directly (e.g. from a secret store):
gpilotauthlogin--api-key"$MY_KEY"
API keys are pinned to one organization, so there is no organization picker.
The CLI validates the key against the GraphPilot API, reads the organization it belongs to,
and uses it. With --org, the login is refused when the key belongs to a different
organization. See API keys for how to create an organization key and which
permissions to give it.
For fully non-interactive use (CI/CD), set the key as an environment variable
instead of logging in:
Terminal window
exportGPILOT_TOKEN="sk_…"
gpilot--no-interactivedeploymentlist
When GPILOT_TOKEN is set, it takes precedence over any stored profile.
How long your session lasts depends on the method you used:
Method
Lifetime
Refresh
Browser (--browser)
Short-lived access token (minutes)
Automatic, refreshed on the next command
Device code (--device)
Short-lived access token (minutes)
Automatic, refreshed on the next command
API key (--api-key)
Does not expire
Validated by the server on each use
API key from the environment (GPILOT_TOKEN)
Does not expire
Validated by the server on each use
For browser/device sessions, the access token is intentionally short-lived. You
do not need to log in again when it expires: on the next command, the CLI
detects the expired token, uses the stored refresh token to obtain a new one,
and saves it transparently.
The output adapts to how you authenticated. It shows the profile (except for a
GPILOT_TOKEN session, which uses no profile), the auth method, both verdicts below and the
masked token. The organization is shown once the API has named it, and the user and token
expiry for OAuth logins. Add the global --profile <name> to inspect a specific
profile: gpilot --profile acme auth status.
With --format json (or yaml) it prints one document instead. The token is masked, as in
the pretty output, and fields that do not apply are left out:
false only when the API rejected the credential, or nobody is signed in.
session
The stored state: active, renewable (the access token expired, a refresh token is stored) or expired.
valid
The API’s verdict, true or false. Left out when it was not checked.
validity
valid, invalid, unverified (--offline), unreachable, or none when nobody is signed in.
reason
Why the credential is invalid or unreachable.
method
oauth (browser or device), api_key (stored in the profile), api_key_env (from GPILOT_TOKEN), or none.
expires_in_secs
Seconds left on the stored access token, for an OAuth login.
Two lines answer two different questions, and they can honestly disagree:
Session is read from the stored credential alone, with no network
involved: logged in, logged in (access token expired, renewable), or
logged out (session expired…).
Valid is the API’s verdict on that credential. By default auth statusverifies the credential against the API, so a key you revoked in the portal
is reported as Valid: no and the command exits 3 (see
exit codes). If the API cannot be
reached, the line reads Valid: unknown (…) and the exit code stays zero: an
unreachable API is not a logout.
With nobody signed in (no stored credential and no GPILOT_TOKEN), the command says so and
exits 3.
Pass --offline to skip the check and report the stored state only. That also
avoids spending the single-use refresh token, so it is the safer way to ask
“am I logged in?” repeatedly.
This removes the stored credential for the active profile and leaves the profile
itself in place; gpilot auth logout --all does the same for every profile. To
remove a profile entirely, credential and configuration together, use
gpilot profile delete. See Profiles for working with more
than one identity.