Neutrino Docs
API ReferenceCLI Reference

login

Authenticate with the NNO platform

Usage

nno login [options]

Options

NameTypeRequiredDescription
tokenstringNoNNO API token (for CI/non-interactive use)
iam-urlstringNoOverride IAM base URL

Synopsis

nno login authenticates the Neutrino CLI against the NNO IAM service and stores the resulting credentials in ~/.nno/credentials.json. Two modes are supported:

  • Token mode (--token) — for CI/CD pipelines and other non-interactive environments. The provided token is written to the credential file with a 30-day expiry. An optional IAM lookup populates email, platformId, role, and expiresAt from the live session; if IAM is unreachable the token is stored with ci-user as a placeholder.
  • Interactive mode — runs the OAuth 2.0 device-authorization flow (RFC 8628). The CLI requests a device code from IAM, prints a short user code and a verification URL, then polls the token endpoint until the user approves, the code expires, or access is denied.

Examples

CI / non-interactive

export NNO_API_TOKEN=$(op read "op://CI/NNO/api-token")
nno login --token "$NNO_API_TOKEN"

Output:

✔ Authenticated via token

The credential file is written atomically with 0600 mode. The parent ~/.nno/ directory is created on first login (0700), so subsequent nno whoami calls succeed immediately.

Interactive (device flow)

nno login

Output when IAM has the device endpoint enabled:

ℹ Open this URL in your browser:
ℹ   https://console.app.nno.app/activate
╭────────────────╮
│ Code: ABCD-1234 │
╰────────────────╯
ℹ Waiting for authentication...
✔ Authenticated as developer@acme.com

The CLI polls POST /oauth/device/token at the cadence (interval) returned by the device-code response, handling RFC 8628 error states:

Error codeBehaviour
authorization_pendingContinue polling at the current interval
slow_downIncrease polling interval by 5 seconds
expired_tokenExit 1 — re-run nno login to get a new code
access_deniedExit 1 — user declined in browser

Point at a staging IAM endpoint

nno login --iam-url https://iam-stg.svc.nno.app --token "$STAGING_TOKEN"

Credential Storage

PathOwnerMode
~/.nno/current user0700 (created on first login)
~/.nno/credentials.jsoncurrent user0600

Source of truth: packages/cli/src/utils/credentials.ts. The stored schema is:

{
  "token": "string",
  "refreshToken": "string | null",
  "email": "string",
  "platformId": "string | null",
  "role": "string",
  "expiresAt": "ISO 8601 timestamp",
  "iamUrl": "string",
  "audience": "nno-cli"
}

nno logout clears the file in place; nno whoami reads it without modification.

Environment Variables

VariableDescription
NNO_IAM_URLOverride the IAM base URL (same as --iam-url). Checked after the flag; falls back to https://iam.svc.nno.app.

Exit Codes

CodeMeaning
0Login succeeded (token mode or device flow).
1Login failed — IAM unreachable, device code expired, access denied, or unexpected runtime error.

Error Scenarios

ScenarioOutputRemedy
IAM unreachable (interactive)Interactive login is unavailable — cannot reach the NNO IAM service at <url>Use --token or check network
Device endpoint not enabled (HTTP non-2xx)Device login endpoint not available (NNN)Use --token
Device code expiredCode expired. Run: nno loginRe-run nno login
Access denied in browserAccess denied.Re-run and approve in browser
Login polling timeout (5 min)Login timed out. Run: nno loginRe-run nno login

See Also

  • nno whoami — show the currently authenticated user, platform, and role.
  • nno logout — clear the local credential file.
  • Auth Flow — Better Auth, per-platform Workers, and the CLI device-authorization flow.

On this page