leed auth

Five subcommands and one top-level alias, covering the session the CLI holds and the two GitLab tokens your site checkout depends on. This page is flags and outputs; for what a session actually is, where it is stored and how it stays alive, read CLI authentication first.

leed auth login

leed auth login
leed auth login --env staging
leed auth login --email you@example.com
FlagTypeDefaultRequiredHidden from --help?What it does
-e, --env <name>stringthe nearest leed.config.json, else productionNoYesWhich environment to sign in to: production, staging or dev
--browserbooleantrueNoNoUse the browser device-authorization flow. This is the default
--email [email]string—NoNoSwitch to magic-link sign-in. Omit the address to be asked for it

The default flow is the browser device authorization. The CLI prints a verification code, opens your browser at the approval screen, and polls until you confirm:

Environment: staging
Your verification code is: AB12-CD34

Opening browser for authorization...
Waiting for authorization...

Authenticated as Ada Lovelace (you@example.com) on staging
Credentials saved to /home/you/.config/leed/credentials.json

Everything down to “Waiting for authorization…” is narration on stderr; the two closing lines are the command’s result on stdout. Credentials saved to … appears only for a non-production environment, where the path is worth knowing. If the platform’s browser opener is unavailable — a remote shell, a container — the URL is printed for you to open anywhere you are already signed in.

The browser screen you approve on is documented from the CMS side in authorizing devices and clients.

--email switches to a magic-link send, and that is all it does:

Check your email and click the sign-in link.
After clicking the link, run: leed auth login --browser --env production

No session is stored. The email gets you signed in to the CMS in a browser; the CLI still needs the device flow afterwards to obtain its own session. This is the single most common misunderstanding of this command — plan on running leed auth login twice.

--email takes an optional value, so a bare --email prompts for the address rather than failing. With nobody at the terminal it refuses instead of blocking on a stdin that will never answer.

leed login

leed login

The top-level alias for leed auth login. Identical flags, identical behavior, identical output. The only difference is the name it reports in its --json document: login rather than auth.login, so a consumer can match the command line it actually ran.

leed auth logout

leed auth logout
leed auth logout --env staging
FlagTypeDefaultRequiredHidden from --help?What it does
-e, --env <name>stringthe nearest leed.config.json, else productionNoYesWhich environment to sign out of

It asks the CMS to revoke the session, then deletes the stored credentials for that environment. The revoke is best effort and the deletion is not: a laptop that cannot reach the CMS still has to be able to drop its cached token, so a refusal or a network failure is reported as a warning and the credentials go anyway. When that happens the session may remain live on the server until it expires, and re-running the command from a connected machine will still revoke it.

With nothing stored it prints Not logged in to <env>. and reports success — the goal, no session on this machine, already held. Otherwise it prints Logged out of <env>.

It ends only that environment’s session. A machine signed in to both production and staging stays signed in to the other one.

leed auth status

leed auth status

No flags of its own. What it reports depends on where you run it.

  Credentials: /home/you/.config/leed/credentials.json
  ✗ dev: you@example.com (expired Aug 3, 2026)
  ✓ staging: you@example.com (expires Sep 9, 2026)

Every environment this machine holds a session for, one row each. The Credentials: path line appears only when a non-production environment is in play — that is exactly when knowing which file to look in matters.

With nothing stored at all, the whole output is:

  Not authenticated. Run: leed auth login

Symbols mean the same thing in both places, except that session rows never show a warning — a session is either live or it is not.

SymbolMeaningThreshold
✓ValidMore than 7 days remaining
⚠Expiring soon — rotate7 days or fewer remaining (GitLab token rows only)
✗Expired and already failingPast its expiry
?UnknownNo expiry recorded, or one this CLI cannot parse

The token lookup can end four other ways, each replacing both token rows with a single line:

LineWhat happenedWhat to run
Session expired. Run: leed auth login --env <env>The CMS rejected the stored session (401)leed auth login --env <env>
No developer access for this organizationThe account is signed in but not permitted (403)Ask an administrator — see billing and developer access
Could not reach <cms url> (<detail>)The CMS did not answerCheck connectivity, then retry
(no tokens stored yet — run 'leed auth rotate' or rerun the installer)Neither token has ever been issuedleed auth rotate

A separate line, GitLab tokens for <domain> (<env>): not authenticated for this env, means the site targets an environment you hold no session for — sign in to that environment before the tokens can even be asked about.

leed auth rotate

leed auth rotate
leed auth rotate --yes
FlagTypeDefaultRequiredHidden from --help?What it does
-y, --yesbooleanfalseNoNoConfirm without being asked. Required for any unattended run — under --json, or with no interactive terminal

Reissues this site’s two GitLab tokens and writes them where they are used: the @leed registry entry in ~/.bunfig.toml, and the origin URL of the raw-content checkout. Your CMS login session is not touched — you stay signed in, and nothing else changes.

It must be run from inside a site directory. Anywhere else it stops with “This command must be run from inside a leed-managed site directory.” and the hint to cd into the folder containing leed.config.json.

Because the previous tokens stop working the moment the new pair is issued, it asks first:

Rotate this site's GitLab tokens? The current tokens stop working, and ~/.bunfig.toml
and the raw-content .git/config are rewritten.

A successful run prints a three-line summary:

✓ GitLab credentials rotated
  Bunfig:    /home/you/.bunfig.toml
  Git repo:  /home/you/leed/example.com/raw-content
  Expires:   11/30/2026

  Your CMS login session was not touched. No re-authentication needed.

The bunfig write has three outcomes, and the summary line tells you which one you got. written — the fresh token was stored, and the path is printed plain. unchanged — the file already held exactly this token. skipped-env-var — your @leed entry points at an environment variable you manage yourself, so it was deliberately left alone; the path is annotated (skipped — uses environment variable) and followed by:

  Your bunfig references an env var, so we left it alone. The rotated
  registry token is stored on the backend; if your env var points at a
  personal access token you manage yourself, no action needed.

Two failures are worth recognizing. A 401 is “Session expired or invalid. Run: leed auth login --env”. A 403 is “You don’t have developer access to this organization.” — you are signed in and not permitted, so re-authenticating will not help; an administrator has to grant the developer override. And if the token was issued but the git remote could not be rewritten, the command exits 1 pointing at leed site init, which is the supported repair — re-running leed site init re-points the origin URL with a fresh token.

Rotation is scoped to one site. If you develop several, run it in each.

leed auth reset

leed auth reset
leed auth reset --all-sessions
FlagTypeDefaultRequiredHidden from --help?What it does
--all-sessionsbooleanoffNoNoAlso revoke your sessions on other devices, rather than this one alone
-y, --yesbooleanfalseNoNoConfirm without being asked. Required for any unattended run

The order of operations is fixed, and it explains the failure modes:

  1. Confirm — before the site context, the credentials or the network, so a refusal leaves everything exactly as it found it.
  2. Rotate the GitLab tokens, while the session is still valid. Revoking first would make this step fail with a 401.
  3. Write the results — the bunfig entry, then the raw-content origin URL.
  4. Revoke and sign out — the other devices’ sessions when --all-sessions was given, then this one — and delete the local credentials regardless of whether the server was reachable.

A remote that could not be rewritten in step 3 does not abort step 4. You asked for your credentials to stop working, and that has to happen even when a local file could not be updated. The run still succeeds, with a warning naming the .git/config that kept the stale token and telling you to re-run leed site init or fix the origin URL by hand.

✓ Credentials reset
  Bunfig:    /home/you/.bunfig.toml
  Git repo:  /home/you/leed/example.com/raw-content
  CMS login: revoked (all devices)

  You will need to re-authenticate. Run: leed auth login --env staging

Revoking other sessions is the same operation the CMS offers on sessions, connected accounts and API tokens.

Choosing between rotate and reset

leed auth rotateleed auth reset
GitLab registry token (~/.bunfig.toml)ReissuedReissued
GitLab raw-content token (.git/config)ReissuedReissued
CMS login sessionUntouchedRevoked
Sessions on other devicesUntouchedRevoked with --all-sessions
Local credentials fileUntouchedDeleted for that environment
Re-login required afterwardsNoYes

Rotate for hygiene, for a token leed auth status shows expiring, and when git fetch or a CLI update starts failing with an authorization error. Reset for a lost or compromised machine, or a credential you believe has leaked.

JSON output

The five commands report as auth.login, auth.logout, auth.status, auth.rotate and auth.reset; the alias reports as login. Envelope, warnings and the full code list are on machine-readable output.

{
  "environment": "staging",
  "customer": "example-com",
  "rawContentRepo": "/home/you/leed/example.com/raw-content",
  "bunfig": { "path": "/home/you/.bunfig.toml", "status": "written" },
  "tokensExpireAt": "2026-11-30T00:00:00.000Z",
  "tokensExpireAtLabel": "11/30/2026",
  "cmsSessionPreserved": true
}

These commands can produce not_authenticated, auth_expired, permission_denied, not_a_site_repo, network_error and external_command_failed. login refuses under --json with interactive_input_required; rotate and reset refuse with confirmation_required unless --yes is given. auth status never fails for a state it can describe — a rejected session, a missing developer override and an unreachable CMS are all successful status reports carrying the reason.

Notes worth carrying

The credentials file holds a refreshToken field that is always empty and reserved. It is not a working refresh token; the CLI refreshes by round-tripping its access token instead.

The raw-content origin URL that rotate, reset and init write embeds the token in plain text — https://access-token:<token>@gitlab.com/…. Copying a site folder to a shared machine copies a live credential with it.

leed auth is one of four command groups; the whole tree with its global options is at CLI command reference. Both files these commands rewrite are cataloged on leed.config.json, files and environment, and a token that has quietly expired shows up first as an authentication failure in the git workflow.

ESC