How Claude HUD Determines Usage Rate Limits from the Anthropic OAuth API
Claude HUD determines usage rate limits by querying the Anthropic OAuth /api/oauth/usage endpoint, parsing utilization percentages for 5-hour and 7-day windows, and caching results with exponential backoff for 429 responses.
Claude HUD is an open-source terminal enhancement that displays real-time token consumption against Anthropic subscription tiers. This article explains how the tool determines usage rate limits from the Anthropic OAuth API, including credential management, caching strategies, and tier-specific limit detection.
Detecting Custom API Endpoints
Before querying usage data, Claude HUD verifies it is communicating with the official Anthropic endpoint. In src/usage-api.ts, the isUsingCustomApiEndpoint function checks for the environment variables ANTHROPIC_BASE_URL and ANTHROPIC_API_BASE_URL (lines 60-71).
If a custom endpoint is detected, the HUD skips the OAuth usage API entirely because the endpoint only functions against Anthropic's official servers. This prevents unnecessary authentication errors for users running local or proxy endpoints.
The OAuth Usage Data Flow
Cache Validation and Lock Acquisition
Claude HUD implements a resilient caching system to avoid excessive API calls across short-lived processes. The readCacheState and readCache functions (lines 48-78) check a file-based cache stored in .usage-cache.json.
If the cache is stale, tryAcquireCacheLock (lines 98-136) attempts to create a lock file (.usage-cache.lock) to prevent parallel API requests from multiple HUD instances. If the lock is busy, waitForFreshCache pauses briefly to allow another process to refresh the data.
Credential Loading from macOS Keychain
When cache misses occur, the HUD loads OAuth credentials using the readCredentials function in src/usage-api.ts (lines 690-808). The implementation prioritizes the macOS Keychain for secure storage, falling back to a legacy JSON credential file only when necessary.
The function extracts the access_token and subscriptionType (values like max, pro, or team). The getPlanName function (lines 812-820) normalizes these raw strings into human-readable plan names (Max, Pro, Team). For users authenticating with API keys only (no OAuth subscription), getPlanName returns null, signaling the HUD to suppress the usage display.
Calling the Anthropic OAuth Usage Endpoint
With valid credentials, the fetchUsageApi function (lines 983-1015) sends an HTTPS GET request to /api/oauth/usage with the OAuth bearer token and the required header anthropic-beta: oauth-2025-04-20.
The API response includes:
five_hour.utilization: Percentage of the 5-hour token allocation consumedseven_day.utilization: Percentage of the 7-day token allocation consumed- Reset timestamps for both windows
Claude HUD parses these percentages to determine usage rate limits relative to the subscriber's specific tier caps, which are enforced server-side but reported as utilization rates.
Handling Rate Limits and Exponential Backoff
When the Anthropic API returns a 429 "rate-limited" response, Claude HUD implements robust error handling and backoff logic. The fetchUsageApi function parses the Retry-After header to determine the wait duration.
The cache stores a rateLimitedCount that drives an exponential back-off sequence: 60 seconds → 120 seconds → 240 seconds → maximum 5 minutes. During backoff periods, the HUD continues displaying the most recent valid usage data with a "syncing" indicator, ensuring users retain visibility into their consumption even when live updates are temporarily suspended.
Tier-Specific Limit Determination
Claude HUD determines usage rate limits for different subscriber tiers using the same API fields across all plan types:
-
Max, Pro, and Team tiers: All utilize
five_hour.utilizationandseven_day.utilizationpercentages. The HUD displays both metrics as progress bars, coloring them green, yellow, or red based on proximity to 100%. The specific token caps differ server-side by tier, but the HUD only receives and displays the percentage consumed. -
API-key-only users: When
getPlanNamereturnsnull(indicating no OAuth subscription), the HUD skips the usage line entirely. TheshowUsageconfiguration defaults tofalsefor these users, preventing unnecessary API calls.
Implementation Examples
Fetching Usage Data Programmatically
You can invoke the same usage detection logic that Claude HUD uses internally:
import { getUsage } from './usage-api.js';
(async () => {
const usage = await getUsage();
if (!usage) {
console.log('No OAuth usage data available – likely an API-key user');
return;
}
console.log(`Plan: ${usage.planName}`);
console.log(`5-hour window: ${usage.fiveHour}% (resets ${usage.fiveHourResetAt})`);
console.log(`7-day window: ${usage.sevenDay}% (resets ${usage.sevenDayResetAt})`);
if (usage.apiError) {
console.warn('API warning:', usage.apiError);
}
})();
This executes the full pipeline including cache checks, credential loading from the macOS Keychain, and the Anthropic API request with the anthropic-beta: oauth-2025-04-20 header.
Simulating Rate-Limit Scenarios
To test the exponential backoff logic without hitting actual limits:
import { getUsage, clearCache } from './usage-api.js';
// Reset to pristine state
clearCache();
// Mock fetch that always returns 429
const mockFetch = async () => ({
data: null,
error: 'rate-limited',
retryAfterSec: 30,
});
(async () => {
const usage = await getUsage({ fetchApi: mockFetch });
console.log('Rate-limited result:', usage);
// Displays cached data with apiUnavailable flag
// Backoff counter increments in cache for exponential delay
})();
This demonstrates how fetchUsageApi handles non-200 responses and how getUsage stores the rateLimitedCount to calculate increasing delays (60s → 120s → 240s → 300s max).
Disabling Usage Display via Configuration
To prevent the HUD from querying usage data entirely:
{
"display": {
"showUsage": false
}
}
When showUsage is set to false in .claude-hud/config.json, the main function in src/index.ts (lines 61-70) skips the getUsage call entirely, eliminating network requests and cache lookups.
Summary
- Custom endpoint detection: Claude HUD checks
ANTHROPIC_BASE_URLandANTHROPIC_API_BASE_URLinisUsingCustomApiEndpointto skip OAuth queries when using unofficial endpoints. - Secure credential storage: The tool reads OAuth tokens and subscription types from the macOS Keychain via
readCredentials, mapping raw types to plan names withgetPlanName. - Resilient caching: File-based caching with
.usage-cache.jsonand lock files prevents API hammering, whilewaitForFreshCachecoordinates concurrent HUD processes. - Anthropic API integration: The
fetchUsageApifunction queries/api/oauth/usagewith theanthropic-beta: oauth-2025-04-20header to retrievefive_hourandseven_dayutilization percentages. - Rate limit handling: 429 responses trigger exponential backoff (60s to 300s) using
Retry-Afterheaders andrateLimitedCount, with graceful degradation to stale cache data. - Tier-agnostic display: All subscription tiers (Max, Pro, Team) use the same utilization fields; the HUD displays percentages rather than absolute token counts, hiding the display entirely for API-key-only users.
Frequently Asked Questions
How does Claude HUD authenticate with the Anthropic OAuth API?
Claude HUD authenticates using OAuth credentials stored in the macOS Keychain, accessed via the readCredentials function in src/usage-api.ts. The function retrieves the access token and subscription type, then includes the token as a Bearer token in the Authorization header when calling the /api/oauth/usage endpoint. If Keychain access fails, it falls back to a legacy JSON credential file.
Why does Claude HUD show percentages instead of absolute token counts?
The Anthropic OAuth /api/oauth/usage endpoint returns utilization data as percentages (five_hour.utilization and seven_day.utilization) rather than raw token numbers. Claude HUD displays these percentages as progress bars because the specific token caps vary by subscription tier (Max, Pro, Team) and are enforced server-side. The percentages provide a normalized view of consumption relative to each tier's specific limits.
What happens when the Anthropic API rate-limits the usage endpoint?
When the API returns a 429 status code, the fetchUsageApi function parses the Retry-After header and stores a rateLimitedCount in the cache. Claude HUD implements exponential backoff starting at 60 seconds, doubling with each subsequent failure (120s, 240s) up to a maximum of 5 minutes. During backoff, the HUD continues displaying the most recent valid cached data with a "syncing" indicator to maintain visibility.
Can I use Claude HUD with a custom Anthropic API proxy?
Yes, but usage tracking will be disabled. The isUsingCustomApiEndpoint function in src/usage-api.ts detects custom endpoints by checking for ANTHROPIC_BASE_URL or ANTHROPIC_API_BASE_URL environment variables. When these are present, the HUD skips the OAuth usage API entirely because the endpoint only functions against Anthropic's official servers, preventing authentication errors while still providing the core HUD functionality.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →