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.