anthropicapi

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package anthropicapi implements the ports.PlanUsageSource interface by calling Anthropic's OAuth-protected /api/oauth/usage endpoint with the access token that Claude Code CLI stores locally.

Auth source priority on macOS:

  1. Keychain service "Claude Code-credentials" (account = current user)
  2. ~/.claude/.credentials.json (file fallback)

On non-Darwin platforms only the file source is consulted.

The package is intentionally self-contained: no third-party deps, no CGo; stdlib net/http and os/exec only.

Index

Constants

This section is empty.

Variables

View Source
var ErrCredentialsNotFound = errors.New("anthropicapi: credentials not found")

ErrCredentialsNotFound is returned by loaders when neither source had credentials. The package-level Fetch path translates this to ports.ErrPlanUsageUnavailable.

View Source
var ErrInvalidGrant = errors.New("anthropicapi: invalid_grant — re-authentication required")

ErrInvalidGrant is the terminal refresh failure: the refresh_token has been revoked or expired beyond recovery. Translated to ports.ErrPlanUsageAuth at the package boundary.

Functions

func HumanTier

func HumanTier(raw string) string

HumanTier maps the raw rateLimitTier string ("max_5x", "pro", "team_max", "ultra_pro", ...) into a short human label. Unknown values are title-cased verbatim.

Mapping rules (most-specific first):

  • "max" or "max_<x>" → "Max" / "Max <x>" (preserve the multiplier)
  • contains "ultra" → "Ultra"
  • contains "team" → "Team"
  • contains "enterprise" → "Enterprise"
  • contains "max" → "Max" (fallback for things like "team_max")
  • contains "pro" → "Pro"

func SaveCredentials

func SaveCredentials(c Credentials) error

SaveCredentials writes refreshed credentials back to the file location so other clyde processes (and a long-running clyde session) can pick up the new tokens.

It is ONLY called when the credentials were read from the file in the first place (credSource == sourceFile). Keychain is strictly read-only from clyde: when tokens originate in the Keychain we never refresh and never write here, because writing the file copy would be ineffective (the next read is Keychain-first on macOS) and rotating the Keychain-shared refresh token could log the user out of the Claude Code CLI. See the refresh policy in client.go.

Best-effort: errors from the write are returned so callers can decide whether to surface them, but the in-memory Credentials remain valid.

Types

type Client

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

Client implements ports.PlanUsageSource by combining:

  • Credentials loading (file + Keychain)
  • OAuth refresh when the access token is expired or rejected
  • GET /api/oauth/usage with the Bearer token

A single Client instance is safe for concurrent use; the credentials cache + refresh path are guarded by a mutex.

func NewClient

func NewClient() *Client

NewClient returns a Client with sensible defaults — a 10s timeout HTTP client and the system clock.

func NewClientWithDeps

func NewClientWithDeps(httpClient *http.Client, now func() time.Time) *Client

NewClientWithDeps returns a Client with custom HTTP client + clock — the hook tests use to inject httptest.Server URLs and a deterministic clock.

func (*Client) Fetch

func (c *Client) Fetch(ctx context.Context) (ports.PlanUsage, error)

Fetch implements ports.PlanUsageSource. It returns the current plan-quota snapshot, refreshing the access token transparently if needed.

Translation rules (adapter → port):

  • ErrCredentialsNotFound → ports.ErrPlanUsageUnavailable
  • ErrInvalidGrant → ports.ErrPlanUsageAuth
  • HTTP 401 after refresh → ports.ErrPlanUsageAuth
  • everything else → wrapped raw error

type Credentials

type Credentials struct {
	AccessToken   string
	RefreshToken  string
	ExpiresAt     time.Time
	Scopes        []string
	RateLimitTier string
}

Credentials is the OAuth state Claude Code persists.

Fields mirror the on-disk schema:

{
  "claudeAiOauth": {
    "accessToken":   "sk-ant-oat...",
    "refreshToken": "...",
    "expiresAt":    1704067200000,        // ms epoch
    "scopes":       ["user:profile","user:inference"],
    "rateLimitTier": "max_5x"
  }
}

func LoadCredentials

func LoadCredentials() (Credentials, error)

LoadCredentials reads OAuth state from Keychain (preferred on macOS) or the ~/.claude/.credentials.json file fallback.

Returns ErrCredentialsNotFound when neither source has credentials.

func (Credentials) Expired

func (c Credentials) Expired(now time.Time) bool

Expired reports whether the access token is past its expiry, allowing a small skew so we refresh slightly before the actual deadline.

Jump to

Keyboard shortcuts

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