Authentication
district login stores one session per environment. Sessions for different environments coexist. A second login for the same environment replaces the stored session. Each session names one organization, and district org select changes it.
district login
district login [--production | --staging | --dev] [--api <origin>] [--no-browser] [--organization <id>]
Runs the device authorization grant (RFC 8628). The command prints a URL and a code, opens the URL in the browser, waits for the confirmation, selects an organization, and stores the session. It then records the environment as the current environment: every later command that takes no remote URL uses it when no environment flag is passed.
District creates an organization for every account shortly after sign-up. For an account created shortly before login, the organization list can be empty. The command then waits under the indicator Preparing the account: it reads the list again every 2 seconds for up to 60 seconds, and continues with the selection rules below as soon as the list contains an organization. After 60 seconds it prints This account has no organization yet. District creates one shortly after sign-up. Run district login again in a minute, or open the District dashboard once to finish setting up the account., stores no session, and exits 1.
Flags
| Flag | Description | Default |
|---|
--production | --staging | --dev | The environment to sign in to. Pass one at most. | production |
--api <origin> | A district-api origin for --staging or --dev: a preview deployment or a second local API. The value must be an http or https origin with no path. | the environment's origin |
--no-browser | Prints the URL and opens nothing. | false |
--organization <id> | The organization to act in, by id or by name. Without it, the selection rules below apply: one organization is selected without asking, and several prompt on a terminal and fail without one. | - |
Each environment has a default district-api origin:
| Environment | Origin |
|---|
production | https://api.platform.district.net |
staging | https://api.platform.district-staging.net |
dev | https://api.platform.district.net.test (placeholder: pass the checkout origin from slot/status with --api) |
--api applies to --staging and --dev. The override is stored with the environment. A later login for the same environment without --api removes it. The command rejects --api with production, because that origin is constant.
Output
$ district login --staging
Open https://…/device and confirm the code XVGT-PBQF.
Logged in to staging as khoi@example.com in District Inc (org_01K2…)
The command prints Open the URL above in a browser. when the browser launcher exits non-zero. The first login also offers the companion choice once, and Enter skips it.
Exit codes
| Exit code | Meaning |
|---|
| 0 | The session is stored. |
| 1 | The confirmation was refused or expired, the account has no organization after 60 seconds, several organizations are available and no terminal can select one, or WorkOS answered with a token that names another organization. No session is stored. |
district org list
district org list [--production | --staging | --dev]
Prints one line per organization the session can act in, in ascending name order, with * on the organization the session is scoped to. The lines go to stdout. An account that belongs to no organization prints one sentence to stderr, so stdout stays empty when piped.
Flags
| Flag | Description |
|---|
--production | --staging | --dev | The environment to act in. Pass one at most. Without a flag, the command uses the environment that the last district login recorded, or production. |
Output
$ district org list
Acme Supply (org_01K2…)
* District Inc (org_01K2…)
Exit codes
| Exit code | Meaning |
|---|
| 0 | The list was printed. An account with no organization also exits 0. |
| 1 | The session is gone or was refused, or district-api did not answer. |
district org select
district org select [<organization>] [--production | --staging | --dev]
Changes the organization the session acts in. The command exchanges the stored refresh token, so it needs no second browser confirmation. It prints Now acting in <name> (<id>) to stderr.
Arguments
| Argument | Description |
|---|
[<organization>] | The organization to act in, by id or by name. Without it, the selection rules below apply. |
Flags
| Flag | Description |
|---|
--production | --staging | --dev | The environment to act in. Pass one at most. Without a flag, the command uses the environment that the last district login recorded, or production. |
Output
$ district org select "Acme Supply"
Now acting in Acme Supply (org_01K2…)
Exit codes
| Exit code | Meaning |
|---|
| 0 | The session now names the organization. |
| 1 | No organization was selected after three attempts, the argument names no organization or several, several organizations are available and no terminal can select one, or the session is gone or was refused. |
district org create
district org create <name> [--production | --staging | --dev]
Creates another organization, in addition to the one District creates for every account at sign-up, makes the caller its Owner with a General workspace, and switches the session to it. The command needs a signed-in session for the environment; the organization that session names does not matter. The command prints the name and the org_ id on stdout, and Now acting in <name> (<id>) on stderr. A request that district-api answered 503 or did not answer is repeated with the same creation key, so a repeat cannot create a second organization.
Arguments
| Argument | Description |
|---|
<name> | The organization name, 1 to 120 characters after trimming. Organization names are not unique. |
Flags
| Flag | Description |
|---|
--production | --staging | --dev | The environment to act in. Pass one at most. Without a flag, the command uses the environment that the last district login recorded, or production. |
Output
$ district org create "Acme Supply"
created Acme Supply (org_01K2…)
Now acting in Acme Supply (org_01K2…)
Exit codes
| Exit code | Meaning |
|---|
| 0 | The organization exists and the session names it. |
| 1 | district-api refused the name, did not finish the create after three attempts, or the session is gone or was refused. |
| 2 | The command line names two environments. |
Selecting an organization
district login and district org select apply these rules:
- The command selects the one organization without a prompt.
- The command prompts for an organization when stderr is a terminal and several organizations are available. The prompt asks for a number and accepts three attempts.
--organization <id> on district login, or the positional argument of district org select, selects one without a prompt. An id or a name is accepted.- Several organizations and no terminal is a failure. The message names the exact command that selects one, with the flag of the environment, such as
district login --staging --organization <id>. This applies to every session with no terminal, including a CI job. - An account with no organization fails with
This account has no organization yet. District creates one shortly after sign-up. Run district login again in a minute, or open the District dashboard once to finish setting up the account.. district login waits up to 60 seconds for the organization that sign-up creates first; district org select fails at once.
district whoami
district whoami [--production] [--staging] [--dev] [--offline]
Shows the values that the credential helper would use. For each environment it prints one block: the email of the stored session, the organization the session is scoped to, the access-token expiry, the district-api origin with (default) or (override from config), the WorkOS client id, and the answer of a live viewer query against district-api. An environment with no session prints one session: line with the district login hint for it. The header of the current environment ends with (current).
Flags
| Flag | Description | Default |
|---|
--production, --staging, --dev | The environments to report. Any combination. Without a flag, the command reports every environment. | - |
--offline | Skips the district-api call and reports the stored state only. | false |
Output
$ district whoami --staging --offline
staging (current)
session: khoi@example.com
organization: org_01K2…
access token: expires 2026-08-29T18:40:00Z (in 54 min)
api origin: https://api.platform.district-staging.net (default)
workos app: client_01M0VXCE6XT24NPJZGAAEJ97N5
Exit codes
| Exit code | Meaning |
|---|
| 0 | Every block was printed. An environment with no session is not a failure. |
| 1 | A live call failed for an environment that has a session. Every block is printed first. |