symfonic.core.grok_credentials¶
grok_credentials ¶
Grok credential store — auto-load + auto-refresh of the grok CLI token.
DEV/TEST USE ONLY. Reads the plaintext OAuth credential file written by a
grok login (~/.grok/auth.json, or $GROK_HOME/auth.json) and yields
an always-valid short-lived access token, refreshing transparently against
auth.x.ai when the cached token is within expiry_skew_seconds of
expiry.
File shape (as written by grok login)¶
.. code-block:: json
{"https://auth.x.ai::<uuid>": {
"key": "<882-char JWT access token>",
"refresh_token": "<86-char rotating refresh token>",
"expires_at": "2026-10-20T09:57:05.096631Z",
"oidc_client_id": "<the CLI's public client id>",
"...": "other profile fields, preserved verbatim"
}}
The store uses the FIRST entry carrying a non-empty key. The refresh
grant reuses the entry's own oidc_client_id — no client identity is
embedded here, so there is nothing to rotate when xAI rotates theirs.
Side effect (deliberate and necessary)¶
The xAI OAuth refresh_token ROTATES: each refresh returns a NEW
refresh_token and INVALIDATES the previous one. To keep the developer's
grok login working, the rotated token MUST be written back to the
credential file in its native shape (key / refresh_token /
expires_at). This module therefore mutates the local credential file
on refresh. The write is atomic (temp file + os.replace) and guarded by
an exclusive file lock so a concurrent grok refresh cannot corrupt the
file or race the rotation.
Tokens are NEVER logged; only a short non-leaking fingerprint is emitted.
GrokCredentialError ¶
Bases: RuntimeError
Raised when a Grok subscription token cannot be resolved or refreshed.
GrokCredentialStore ¶
GrokCredentialStore(credentials_path: Path | None = None, *, token_url: str = _DEFAULT_TOKEN_URL, expiry_skew_seconds: int = 300)
Yields an always-valid grok CLI access token, refreshing as needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials_path
|
Path | None
|
Override the credential file. Defaults to the
|
None
|
token_url
|
str
|
OAuth token endpoint. Defaults to |
_DEFAULT_TOKEN_URL
|
expiry_skew_seconds
|
int
|
Refresh this many seconds BEFORE the cached
token's |
300
|
Source code in src/symfonic/core/grok_credentials.py
access_token ¶
Return a valid access token, refreshing if within the skew window.
Source code in src/symfonic/core/grok_credentials.py
peek_access_token ¶
Return the cached token without refreshing; None if unavailable.
For logging / fingerprinting at construction time — must never raise or trigger a network refresh.
Source code in src/symfonic/core/grok_credentials.py
default_credentials_path ¶
Resolve the grok CLI credential file path.
Precedence: GROK_OAUTH_CREDENTIALS_FILE override, then
$GROK_HOME/auth.json (the CLI's own relocation knob), then
~/.grok/auth.json.