Skip to main content
9p supports two modes:
  • Platform: metered through 9th Protocol, credits and plan limits apply.
  • BYOK: your own OpenRouter key, calls go direct, we meter nothing.

Creating an account

Three ways, all landing in the same account:

GitHub

One click, identity only, no repo scopes.

Email link

We email a link. No password to choose or forget.

Password

Classic email and password.
Sign in with GitHub requests user:email and nothing else. Repository access is a separate, explicit connector, signing in never asks for your code. If you already have a password account on the same verified GitHub email, signing in with GitHub links the two rather than creating a duplicate. Email links expire after 15 minutes and work once. Requesting a link for an address with no account creates one on first use.

Platform: 9p login

9p asks the API for a code pair, shows you a short code, and opens https://app.9thprotocol.com/device. Approve it there and the CLI receives tokens. This is the OAuth 2.0 Device Authorization Grant (RFC 8628) - your password is never typed into or seen by the terminal.
Only approve a code you just generated yourself. Approving a code someone else sent you gives their machine full access to your account and credits. 9th Protocol will never ask you to approve a code on someone else’s behalf.
Codes expire after 10 minutes and are single-use.

Headless machines

Prompts for an API URL and an access token from the dashboard. Use this on servers and containers with no browser.

Signing out

Revokes the refresh token server-side and clears ~/.9p/auth.json. Any BYOK key in that file is preserved.

BYOK

Set an OpenRouter key and 9p calls OpenRouter directly:
Or store it so it persists:
~/.9p/auth.json
In BYOK mode there are no plan locks, so every model OpenRouter offers is available and the Auto router picks from its full ladder. Your key stays on your machine; the system prompt is assembled locally.

Environment variables

Environment variables take precedence over ~/.9p/auth.json, which makes them the right choice for CI. Resolution order:
  1. NINEP_API_URL + NINEP_TOKEN
  2. ~/.9p/auth.json (apiUrl + token)
  3. OPENROUTER_API_KEY
  4. ~/.9p/auth.json (openrouterApiKey)

Token lifetime

Access tokens last 15 minutes; refresh tokens last 30 days and rotate on every use. 9p refreshes automatically when a stored token is close to expiry and writes the rotated pair back to ~/.9p/auth.json.
Tokens supplied via NINEP_TOKEN are not refreshed, 9p doesn’t own their lifecycle. For long-running automation, prefer 9p login on the machine, or mint a fresh token per run.
If a refresh fails (expired or revoked), 9p stops and tells you to run 9p login again rather than failing mid-task.

Credential file

~/.9p/auth.json, created with 0600:
Treat it like an SSH key. If it leaks, run 9p logout from any machine to revoke that refresh token.