Skip to content
Air-Cloud docs

Logging in

Every command that calls the Air-Cloud API acts as the account you logged in to. aircloud whoami names it.

Logging in as a Builder

aircloud login --account acme

aircloud login opens your browser to authorize the CLI. On a machine without a browser, use the device grant: the CLI prints a URL and a code, and you authorize on any browser.

aircloud login --device

--account takes the account slug you chose at signup; the CLI remembers the last one in config.json. --region selects the region whose API to use when your CLI knows several.

The first login of a new account asks for the verification code mailed to the address at signup: no token is issued before the address is verified.

While it waits for you, the CLI prints the login URL (or the device code and its page) again every 30 seconds. It gives up after five minutes, saying so; --timeout sets another wait:

aircloud login --device --timeout 15m

A product is authorized separately, the first time a command acts on it: aircloud release create does it before its first upload, and aircloud products authorize <slug> does it without releasing anything.

When a command needs the API and the CLI holds no session, it refuses with auth.session_missing; when the session has expired and nothing can renew it, with auth.session_expired. Both name the login to run, and neither contacts the platform first (see Rules and error codes).

aircloud logout revokes the cached tokens, deletes the keychain entry, and forgets the session.

Several accounts on one machine

Log in to each account once; each keeps its own session. A product folder names the account and region it belongs to — aircloud new and aircloud products authorize write account and region into its aircloud.toml — so a command run in that folder acts as that account, with no new login. Outside a product folder, commands act as the selected account:

aircloud accounts list
aircloud accounts use acme

aircloud accounts list shows every logged-in account with its region and marks the selected one with *. The first login selects its account; later logins do not change the selection, and say so. Every command that calls the API prints what it acts as on stderr — aircloud: acting as account acme in lab1 — so a switch is never silent. AIRCLOUD_TOKEN, or a service-account login, takes precedence over every account session.

Where the session lives

The CLI keeps one session per account and region: short-lived access tokens, and their expiry, in ~/.config/aircloud/sessions/<region>/<account>.json (or under $XDG_CONFIG_HOME/aircloud/), readable only by you. It never writes a long-lived credential there. Logging in to another account, or in another region, leaves every other session intact; the first login selects the account commands act as, and a later one does not change that selection. A service-account login is kept apart, in service-account.json.

A session.json left by an earlier CLI is not read: commands refuse and ask you to run aircloud logout, which forgets it, and then to log in again.

A Builder login's refresh token is kept only in the operating system's keychain: the macOS Keychain, or the freedesktop Secret Service on Linux (reached over D-Bus). With it the CLI renews its access tokens silently. A session stays usable while you use the CLI at least every two weeks, and asks you to authorize again once a month at the latest.

Without a keychain

When no keychain is reachable — a Linux machine with no D-Bus session, a container, CI — the CLI says so once and keeps the refresh token only in memory, for the command that is running. Nothing long-lived is written, so once the access token expires the next command refuses with auth.session_expired and you log in again. For an unattended machine, log in as a service account instead (below).

macOS: one new login after each upgrade

The macOS Keychain ties the refresh token's entry to the binary that wrote it. An upgrade replaces the binary, so the new one cannot read the old entry: it deletes it and asks you to log in once more. No keychain dialog appears. After that one login, renewal is silent again until the next upgrade.

Service accounts: CI and headless machines

A service account is a product's own identity, with a key file instead of a browser login. It is the path for CI and for a headless Linux machine without a keychain.

Create it from a Builder login, in the product directory. The CLI generates the key pair and sends only the public key; the private key is written to the file --out names, readable by you alone, and never reaches the platform:

aircloud service-accounts create --org-path /ci --scopes tenant:deploy --out ci-key.json

--org-path is the node the account acts at, at or below yours, and --scopes is a subset of your own scopes; a service account can never create another. Every key expires: at --expires-at (an RFC 3339 instant) when you give one, else at the platform's ceiling, and the CLI prints the expiry and the account's user id.

Copy the key file to the machine, keeping it readable by its owner alone, and log in there:

aircloud login --service-account ci-key.json

The CLI reads the key file where it is and never copies it. Before the key expires, register a new one, and retire the old one at once with --revoke-key:

aircloud service-accounts rotate <user> --out ci-key-2.json
aircloud service-accounts rotate <user> --revoke-key <key-id> --out ci-key-2.json

aircloud service-accounts list shows the accounts you may manage — those at or below your node whose scopes you hold — with each one's node, scopes, key expiry and creator. aircloud service-accounts delete <user> revokes an account and every key it holds.