Skip to content

Getting Access

WarmHub handles sign-up and sign-in through a hosted login flow — there are no credentials to configure locally. The first time you sign in, your account is created automatically.

There is no separate registration step. The first time you log in (via the CLI or web app), WarmHub creates your account. Supported sign-in methods include:

  • Email and password
  • Google
  • GitHub
  • SSO (SAML/OIDC) — if configured for your organization

Your identity works across the CLI, web app, SDK, and HTTP API.

First-time sign-in also provisions a personal org for you automatically — a namespace you own where you can create repos immediately without waiting to be added to a team org. WarmHub picks the slug as follows:

  1. GitHub login — if you signed in with GitHub (or your identity exposes a GitHub login), WarmHub prefers that login as your personal org slug.
  2. Adoption — if you already own an org whose name matches your GitHub login, WarmHub adopts it as your personal org rather than creating a duplicate.
  3. Suffixing — if the preferred slug is taken by someone else, WarmHub appends a numeric suffix (alice-2, alice-3, …).
  4. Fallback — if no usable login is available, the slug falls back to user-<id> derived from your user ID.

Personal orgs are regular orgs in every other respect — you own them, you can create repos and invite members, and they appear in wh org list. Two constraints apply:

  • Rename. Personal orgs linked to a GitHub login (including fallback slugs) can’t be renamed with wh org rename. Personal orgs without a linked GitHub login (SSO or email-only) can be renamed normally.
  • Reserved names. The following slugs are reserved and rejected on create and rename (case-insensitive): admin, api, billing, blog, docs, help, login, public, settings, signup, status, support, system, warmhub, www. This applies to all orgs, not just personal ones.
Terminal window
wh auth login

This opens your browser for a device authorization flow:

  1. The CLI displays a verification URL and one-time code.
  2. Your browser opens to the login page.
  3. You authenticate and confirm the code.
  4. The CLI receives a token and saves it to ~/.warmhub/auth.json.

Tokens auto-refresh in the background for active device-flow sessions. You should only need to log in once per machine.

If your session is invalidated (for example, revoked server-side or an expired refresh token), the CLI surfaces a Session expired error and prompts you to run wh auth login again.

Non-interactive environments (CI, containers, headless servers):

For automation, use a personal access token via the WH_TOKEN environment variable instead of interactive login. See the wh token commands for creating tokens.

If you need to pipe a raw JWT (e.g., from another auth system):

Terminal window
echo "$JWT" | wh auth login --with-token

Piped tokens cannot auto-refresh — you’ll need to provide a new one when it expires. PATs are the preferred approach for most non-interactive use cases.

You can manage multiple credential sets with the --profile (-P) flag. Each profile stores its own tokens and the API endpoint used at login time.

Terminal window
# Log in with a named profile (e.g., for a separate account)
wh auth login --profile work
wh auth login --profile personal
# Use a profile for any command
wh thing list --repo myorg/myrepo --profile work
# Or set via environment variable
export WH_PROFILE=work
wh thing list --repo myorg/myrepo

Without --profile or WH_PROFILE, all commands use the default profile. Each profile remembers the API URL it was logged in with — that stored URL applies when the profile is active, unless you override it with --api-url. The WARMHUB_API_URL environment variable is the fallback when no profile is loaded (for example, on a fresh machine before login).

Terminal window
wh auth status

Shows all profiles with their identity, auth method (device flow, piped token, or WH_TOKEN environment variable), token expiry, and API endpoint. Use --profile <name> to check a specific profile.

Terminal window
wh auth logout

Removes the default profile’s saved tokens from ~/.warmhub/auth.json. Use --profile <name> to log out a specific profile. Other profiles are not affected. If WH_TOKEN is set as an environment variable, unset it separately.

For scripts and automation, set WH_TOKEN to a personal access token or JWT:

Terminal window
export WH_TOKEN=eyJhbGciOi...
wh thing list # authenticates automatically

WH_TOKEN takes precedence over saved credentials from wh auth login. The CLI checks for it on every command.

All API requests authenticate via Bearer tokens in the Authorization header. WarmHub supports three token types:

TypeObtained viaUse caseExpires
Session JWTwh auth login or web app sign-inInteractive useShort-lived (auto-refreshes)
Personal access tokenwh token create or SDK client.token.createScripts, CI/CD, integrations30 days default, 1 year max
MCP OAuth tokenAutomatic (OAuth flow in MCP client)MCP clients (Claude, Cursor, etc.)Session-based

All token types share a unified validation model — they go through the same server-side JWT verification and permission checking.

See Personal Access Tokens for creating and managing PATs.

Repositories are either public or private. Visibility is set at creation time and can be changed by org administrators.

PublicPrivate
Read (queries, HEAD, history)Anyone — no auth requiredAuthenticated, repo:read permission
Write (commits, shape mutations)Authenticated, repo:write permissionAuthenticated, repo:write permission
Manage (subscriptions, credentials)Authenticated, repo:configure permissionAuthenticated, repo:configure permission
Anonymous requestsReturn data normallyReturn 404

All writes require authentication regardless of visibility. Private reads require repo:read permission on the target repo — sign-in alone is not enough; you need to be a member of the repo’s org. PATs can narrow what a member is allowed to access, but they don’t grant access on their own. Cross-repo reads to a private target apply the same check, so a canonical wh:org/repo/... wref only resolves when you can read the target repo.