Skip to content

Signing in

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.

Terminal window
gpilot auth login

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:

Terminal window
gpilot auth login --browser --org acme
Terminal window
# Prompted securely (input hidden):
gpilot auth login --api-key
# Or pass the value directly (e.g. from a secret store):
gpilot auth login --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
export GPILOT_TOKEN="sk_…"
gpilot --no-interactive deployment list

When GPILOT_TOKEN is set, it takes precedence over any stored profile.

How long your session lasts depends on the method you used:

MethodLifetimeRefresh
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 expireValidated by the server on each use
API key from the environment (GPILOT_TOKEN)Does not expireValidated 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.

Terminal window
gpilot auth status
# or the top-level shortcut:
gpilot whoami
ℹ Authentication Status
────────────────────────────────────────
Profile: default
Method: Browser / device (OAuth)
Session: logged in
Valid: yes
User: ada@example.com (Ada Lovelace)
Organization: acme (org_01J…)
Token: eyJh****c2Fk
Expires in: 0h 4m

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:

{
"authenticated": true,
"session": "active",
"valid": true,
"validity": "valid",
"method": "oauth",
"profile": "default",
"user": "ada@example.com (Ada Lovelace)",
"organizations": [{ "slug": "acme", "id": "org_01J…" }],
"token": "eyJh****c2Fk",
"expires_in_secs": 240
}
FieldValues
authenticatedfalse only when the API rejected the credential, or nobody is signed in.
sessionThe stored state: active, renewable (the access token expired, a refresh token is stored) or expired.
validThe API’s verdict, true or false. Left out when it was not checked.
validityvalid, invalid, unverified (--offline), unreachable, or none when nobody is signed in.
reasonWhy the credential is invalid or unreachable.
methodoauth (browser or device), api_key (stored in the profile), api_key_env (from GPILOT_TOKEN), or none.
expires_in_secsSeconds 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 status verifies 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.

Browser/device sessions can switch the active organization without logging in again:

Terminal window
gpilot organization select acme

This re-mints an organization-scoped token for the chosen organization. API-key sessions are pinned to their organization and cannot switch.

Terminal window
gpilot auth logout

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.

  • Profiles: keep several logins side by side.
  • API keys: create the key a CI job logs in with.
  • CLI overview: GPILOT_TOKEN and the other environment variables.