BBramaDocs
Browse documentation

Brama CLI command reference

brama subscription refresh

Run the gateway’s credential refresh path now for every usable subscription held for one provider, without the background sweep’s expiry window.

Invocation

brama subscription refresh <PROVIDER> --reason <REASON> [--gateway <ORIGIN> | --gateway-consumer <CONSUMER>] [--bearer-role <ROLE>] [--json]
InputRequired/defaultMeaning
<PROVIDER>requiredProvider whose grants are refreshed, normally codex, claude-code, or kimi.
--reason <REASON>requiredNonempty audit reason recorded beside the verdict.
--gateway <ORIGIN>optionalRefresh the pool of the gateway at this origin instead of this machine's own view; the console bearer is read from stdin.
--gateway-consumer <CONSUMER>optionalResolve that gateway through Stado's service directory as this consumer.
--bearer-role <ROLE>optionalRead the console bearer from the token field of the vault item that plays this role instead of from stdin; no item is named.
--jsonoptional; offPrint JSON instead of labeled lines.

Without a gateway the refresh acts on this machine's own view. The block that empties a pool lives in the gateway's journal, so a refresh run in an operator shell cannot clear it: a gateway can hold one live codex credential while every request answers 503 subscription_reauthorization_required with attempts: 0 — every candidate skipped unasked inside a recorded block — and only a refresh sent to that gateway renews the grant. Naming a gateway posts to its POST /v1/admin/subscription-pool/refresh with the console bearer and prints the gateway's own verdict.

Output and state

The verdict contains provider, attempted, result (refreshed or failed), and detail. The command may rotate OAuth grants, updates the credential usage ledger, and journals completed verdicts with their reason. Retired subscriptions are excluded. It exits 0 only when every attempted credential was obtained; a partial refresh remains a failure and preserves each account's refusal. An inventory failure reports the actual discovery error instead of pretending there are no accounts.

A grant the provider already disowned stays in the ledger as awaiting a sign-in until a sign-in stores a new one. The background sweep, the plan reading sweep and a rejected request do not present that grant to the provider again; the plan reading sweep lists it under awaiting_sign_in with the ledger's cause, and a request path refresh is refused with subscription `<id>` is awaiting a sign-in (<cause>); its grant is not refreshed again until a sign-in stores a new one. This command is the one deliberate retry: it presents every attempted grant again, disowned or not, and quotes the provider's answer.

Refusals

An empty provider is refused with a provider is required; an empty reason with --reason must say why this refresh is being run. No usable row produces a failed verdict whose detail starts no usable `<provider>` subscription is in this deployment's pool. An API-key provider produces `<provider>` subscription credentials are API keys rather than OAuth grants, so no refresh path exists for them: replacing one means storing a new credential in the vault. Provider or credential refusals are quoted in detail; failure exits 1.

A transport failure names the token endpoint and retains its underlying cause. If reading a response fails, the detail also names its HTTP status and the number of bytes received before the failure. Brama does not classify a partial 401 or 403 body as a definitive rejection: that read failure leaves the recorded grant state unchanged. A complete provider refusal still determines whether the credential needs a new sign-in. Malformed successful responses retain the JSON parser's error or name the missing access_token.

Each provider's expiry is read where that provider stores it: Claude Code's claudeAiOauth.expiresAt in milliseconds, Kimi's expires_at in seconds, and Codex's access token's JWT exp. A stored grant whose expiry cannot be read (not UTF-8, not JSON, or a token whose claims cannot be decoded) is refused with <provider> credential expiry cannot be read: <cause> on the refresh path and on a request, instead of being treated as stating no expiry and used until the provider refuses it.

The HTTP refresh verdict carries the same detail. Brama Desktop's Subscription Pool screen, under Credential refresh, puts that verdict in its operation result bar rather than replacing the cause with a generic refresh error. The real OAuth diagnostic journeys describe the native checks and their limits.

See the command group or the CLI tree.