- 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.
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
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.
Codes expire after 10 minutes and are single-use.
Headless machines
Signing out
~/.9p/auth.json. Any BYOK key
in that file is preserved.
BYOK
Set an OpenRouter key and 9p calls OpenRouter directly:~/.9p/auth.json
Environment variables
Environment variables take precedence over~/.9p/auth.json, which makes them
the right choice for CI.
Resolution order:
NINEP_API_URL+NINEP_TOKEN~/.9p/auth.json(apiUrl+token)OPENROUTER_API_KEY~/.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.9p login again rather than failing mid-task.
Credential file
~/.9p/auth.json, created with 0600:
9p logout from any machine to
revoke that refresh token.
