Documentation
¶
Overview ¶
Package planusage reports how much of the Claude and Codex plans the person has left, for the app's settings. See README.md.
Index ¶
Constants ¶
const ( // SampleInterval is how often History reads the plans while the daemon // runs. SampleInterval = 15 * time.Minute // HistoryRetention is how long a sample is kept. HistoryRetention = 90 * 24 * time.Hour )
const ( // CacheTTL is how long a result serves without asking again. CacheTTL = 5 * time.Minute // MinRefresh is the shortest time between two reads, even on demand. MinRefresh = 60 * time.Second )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Claude ¶
type Claude struct {
// Credential finds Claude Code's token; nil reads its stored credential.
Credential func(ctx context.Context) (Credential, error)
// Client makes the request; nil uses a client that refuses redirects.
Client *http.Client
// URL overrides the endpoint in tests.
URL string
Now func() time.Time
// contains filtered or unexported fields
}
Claude asks Anthropic for the usage of the plan Claude Code is signed in to.
func (*Claude) Read ¶
Read never refreshes the token: that would rotate Claude Code's credential. A failure that should pass (the endpoint limits the rate, is down or cannot be reached) serves the last reading for up to staleFor, and after a 429 the endpoint is left alone for a while: asking again only keeps the limit.
type Codex ¶
type Codex struct {
// Home is CODEX_HOME; empty means $CODEX_HOME, else ~/.codex.
Home string
// Credential finds Codex's sign-in; nil reads Home's auth.json.
Credential func(ctx context.Context) (CodexCredential, error)
// Client makes the request; nil uses a client that refuses redirects.
Client *http.Client
// URL overrides the endpoint in tests.
URL string
Now func() time.Time
}
Codex asks Codex's usage endpoint with the ChatGPT sign-in Codex stored, and otherwise (an API key sign-in, an expired token, no network) reads the newest rate-limit snapshot Codex wrote to its session files.
type CodexCredential ¶
type CodexCredential struct {
Token string
AccountID string
ExpiresAt time.Time // zero when unknown
}
CodexCredential is the ChatGPT sign-in Codex stored. Like Claude's token it never leaves this package: it is not logged, stored, serialised or put in an error.
func StoredCodexCredential ¶
func StoredCodexCredential(home string) (CodexCredential, error)
StoredCodexCredential reads $CODEX_HOME/auth.json. A sign-in with an API key has no ChatGPT token, and so no plan to read.
type Credential ¶
type Credential struct {
Token string
ExpiresAt time.Time // zero when unknown
// Plan is the plan's name as Anthropic sells it ("Pro", "Max 5x",
// "Team Premium"), from what Claude Code recorded with the token; empty
// when it did not say.
Plan string
}
Credential is the access token Claude Code stored. It never leaves this package: it is not logged, stored, serialised or put in an error.
func StoredCredential ¶
func StoredCredential(ctx context.Context) (Credential, error)
StoredCredential reads Claude Code's credential: on macOS the Keychain item first, then $CLAUDE_CONFIG_DIR/.credentials.json (default ~/.claude/.credentials.json).
type History ¶
type History struct {
Path string
Service *Service
Now func() time.Time
// Interval defaults to SampleInterval.
Interval time.Duration
// contains filtered or unexported fields
}
History samples the plans periodically and keeps readings in the application database, for the analytics page's plan usage over time. Only figures are kept: no token, account or plan name. A reading is stored when its figure changed, when its window reset, or an hour after the last stored one; older than HistoryRetention it is dropped.
type Plan ¶
type Plan struct {
Provider string `json:"provider"`
Available bool `json:"available"`
Reason string `json:"reason,omitempty"`
Plan string `json:"plan,omitempty"`
Windows []Window `json:"windows"`
FetchedAt time.Time `json:"fetched_at"`
}
Plan is the usage of one provider's plan, or why it is unavailable.
type Sample ¶
type Sample struct {
At time.Time `json:"at"`
Provider string `json:"provider"`
Window string `json:"window"`
UsedPercent float64 `json:"used_percent"`
ResetsAt *time.Time `json:"resets_at,omitempty"`
}
Sample is one reading of one window: when the figure was true (the snapshot's time, which for Codex is its last turn), and how much was used.
type Service ¶
type Service struct {
Sources []Source
Now func() time.Time
// contains filtered or unexported fields
}
Service caches the plans of its sources.
func NewService ¶
func NewService() *Service
NewService reads Claude Code's usage endpoint and Codex's session files.
type Source ¶
Source reads one provider's usage. A failure is reported as an unavailable Plan whose Reason is a fixed sentence, never an error carrying upstream text.
type Window ¶
type Window struct {
// Name is "5-hour", "weekly", "weekly Opus", ... or the window length for
// a Codex window of another size.
Name string `json:"name"`
// UsedPercent is nil when the window's reset passed after the snapshot,
// so its old figure no longer applies.
UsedPercent *float64 `json:"used_percent"`
// ResetsAt is nil when the source did not say.
ResetsAt *time.Time `json:"resets_at"`
// Reset reports that the window reset after the snapshot was taken.
Reset bool `json:"reset,omitempty"`
}
Window is one usage window of a plan.