oauth

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 6, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package oauth talks to Anthropic's OAuth token-refresh and usage endpoints using the stored subscription credential (never an API key — API keys force per-request billing and disable subscription mode).

Endpoints (reverse-engineered from Claude Code v2.1.x):

refresh: POST https://platform.claude.com/v1/oauth/token
usage:   GET  https://api.anthropic.com/api/oauth/usage

Index

Constants

View Source
const (
	// ClientID is Claude Code's public OAuth client id.
	ClientID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
)

Variables

View Source
var UserAgent = "claude-cli/2.1.166 (external)"

UserAgent matches the Claude Code CLI's own User-Agent format (`claude-cli/<version> (external)`, from the binary's Io() builder) so the OAuth endpoints treat our polling like the official client. The daemon stamps the detected claude version via SetUserAgentVersion.

Functions

func SetUserAgentVersion

func SetUserAgentVersion(version string)

SetUserAgentVersion sets UserAgent to claude-cli/<version> (external).

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a thin OAuth client. The zero value is not usable; use New.

func New

func New() *Client

New returns a Client with sane timeouts.

func (*Client) Refresh

func (c *Client) Refresh(ctx context.Context, flightKey, refreshToken string) (*TokenResponse, error)

Refresh exchanges a refresh token for a fresh access token. Concurrent calls sharing flightKey collapse to one in-flight request (single-flight), so the daemon never races itself into a refresh-token rotation loop. Pass the account id (or any stable per-account key) as flightKey.

func (*Client) Usage

func (c *Client) Usage(ctx context.Context, accessToken string) (*Usage, error)

Usage fetches the current usage windows using a bearer access token.

type RefreshError

type RefreshError struct {
	Status int
	Body   string
}

RefreshError carries the HTTP status so callers can distinguish a revoked token (4xx -> re-login needed) from a transient failure (5xx/network).

func (*RefreshError) Error

func (e *RefreshError) Error() string

func (*RefreshError) Revoked

func (e *RefreshError) Revoked() bool

Revoked reports whether the error indicates the refresh token is no longer valid (invalid_grant / 400 / 401), meaning the account must be re-logged-in.

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"` // may be empty if not rotated
	ExpiresIn    int64  `json:"expires_in"`    // seconds
	TokenType    string `json:"token_type"`
	Scope        string `json:"scope"`
}

TokenResponse is the refresh endpoint's reply.

func (*TokenResponse) Expiry

func (t *TokenResponse) Expiry(now time.Time) time.Time

Expiry converts expires_in into an absolute time, from now.

type Usage

type Usage struct {
	FiveHour     Window
	SevenDay     Window
	SevenDayOpus Window
}

Usage is the parsed /api/oauth/usage response.

type UsageError

type UsageError struct {
	Status int
	Body   string
}

UsageError carries the HTTP status from a failed usage fetch.

func (*UsageError) Error

func (e *UsageError) Error() string

func (*UsageError) RateLimited

func (e *UsageError) RateLimited() bool

RateLimited reports whether the usage fetch itself was rate-limited (429).

func (*UsageError) Unauthorized

func (e *UsageError) Unauthorized() bool

Unauthorized reports whether the access token was rejected (401) — the caller should refresh and retry.

type Window

type Window struct {
	// Utilization is a fraction in [0,1] (e.g. 0.7 == 70%), as the API reports it.
	Utilization float64
	// ResetsAt is when this window resets. Zero if absent.
	ResetsAt time.Time
	// Present reports whether the API included this window at all.
	Present bool
}

Window is one usage window (5-hour, 7-day, or 7-day-opus).

func (Window) Remaining

func (w Window) Remaining() float64

Remaining returns 100 - Used, clamped to [0,100].

func (Window) Used

func (w Window) Used() float64

Used returns utilization as a 0..100 percentage for scoring/display.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL