-
Notifications
You must be signed in to change notification settings - Fork 5
Configuration
Two files, both TOML, both safe to hand-edit while clauth runs (it reloads on external change):
-
~/.clauth/profiles.tomlfor everything program-wide: profile order, the active marker, the fallback chain, appearance, the scheduler. -
~/.clauth/profiles/<name>/config.tomlfor one account: endpoint, key, env, model routing, its chain settings.
Every key below has a TUI equivalent on the Setup, Fallback, or Config tab (Interface and keys).
Claude Pro / Max / Team / Enterprise. Leave base_url blank. clauth captures the OAuth token from your session or mints one through clauth login, then detects the plan tier from Anthropic's profile endpoint.
API endpoint. Set base_url, and api_key if the endpoint wants one. Works against the Anthropic API or any compatible proxy. The key is handed to Claude Code through apiKeyHelper rather than written into settings.json.
Long-lived setup token. clauth login <name> --setup-token stores a claude setup-token mint as session-token.json. Sessions run on that static login, which never races clauth's token refresher. The Setup tab then shows a token row counting down to the re-mint.
The token outranks the profile's OAuth pair at every switch for as long as it exists, so a later clauth login <name> updates only what clauth polls usage with. clauth static-token <name> --clear drops it and puts the OAuth login back in front of sessions — the full exit: the preserved mint backup and the rolling_token flag go with it, so nothing re-creates a sidecar afterwards.
A mint is a narrower credential than a /login session: it carries user:inference and user:sessions:claude_code and no refresh token, against the five scopes a browser login stores. Claude Code turns off anything gated on the wider set, Claude in Chrome by name. Clear the token if you want those features back — or arm clauth rolling-token <name>, which has the daemon re-stamp the sidecar from the profile's own usage chain: still no refresh token in front of sessions, but the chain's full scope set and plan stamp, so plan-gated models work. The superseded mint waits at session-token.static.json and the bare clauth static-token <name> puts it back.
Three providers get typed usage panels:
| Provider | Base URL | Shows |
|---|---|---|
| DeepSeek | https://api.deepseek.com |
balance rows per currency: total, granted, topped up |
| Z.ai | https://api.z.ai |
percentage bars per limit window (5h / 7d / 30d), per-tool rows, plan level, 7-day per-model token totals |
| Alibaba Model Studio | the four Qwen preset endpoints below | a 7d bar carrying your tier's absolute allowance, a 5h bar when the API reports one, plan tier, subscription status and days left |
Any other endpoint is scanned best-effort: clauth probes a short list of usage paths on the origin your key already authorizes, and renders whatever percentage or balance shapes come back. Those panels carry a "looks wrong? report it" line, since the shape is guessed. An endpoint that returns nothing usable stops being polled until you press r.
For those three, open provider console in the TUI action menu (Interface and keys) opens the page the account's key is minted on. The pages, if you would rather go directly:
| Endpoint | Page |
|---|---|
| DeepSeek | https://platform.deepseek.com/api_keys |
| Z.ai | https://z.ai/manage-apikey/apikey-list |
| Alibaba Token Plan, international | https://modelstudio.console.alibabacloud.com/ap-southeast-1?tab=plan#/efm/subscription/overview |
| Alibaba Token Plan, mainland China | https://bailian.console.aliyun.com/cn-beijing?tab=plan#/efm/subscription/overview |
| Alibaba Coding Plan, international | https://modelstudio.console.alibabacloud.com/ap-southeast-1/?tab=globalset#/efm/coding_plan |
| Alibaba Coding Plan, mainland China | https://bailian.console.aliyun.com/cn-beijing/?tab=plan#/efm/subscription/coding-plan |
Alibaba gets four rows because Token Plan and Coding Plan are separate products with separate quotas, sold on two consoles that do not share accounts. Take the key from the page matching the endpoint you configured, or your calls bill against a plan you did not mean. The key is the sk-sp-… one on your plan's own page, not a workspace key from the general api-key page, which is billed pay-as-you-go instead of drawing your plan's quota.
An AccessKey pair from the RAM console is a different thing again and clauth has no use for one. It cannot read a Solo plan's quota (measured, on the signed OpenAPI), so nothing here asks for one.
Alibaba is the one provider whose api key cannot read its own quota: every quota endpoint ignores the key outright. Those panels run on a separate console session instead. clauth login <account> on a Model Studio account opens the Alibaba console in your browser and stores the session it hands back as a [console] table in that account's config.toml. Nothing else on the account changes. The console returns an api key and an endpoint alongside the session, both scoped to a workspace rather than to your plan and billed separately from it, so clauth discards them.
The 48-hour clock runs from your aliyun console sign-in, so it is already ticking by the time clauth login captures the session. Running the login again inherits whatever is left of that window, which can be minutes; sign in to the Alibaba console afresh first if you want a full one. Once it lapses, clauth stops polling that account: the Usage tab reads console login expired, run clauth login and clauth list marks it (login expired). Polling resumes the moment a new session lands on disk, with no restart.
An account with no api key at all still gets its usage panel, since the quota rides the console session. It just cannot run Claude Code until you add a key.
The Setup tab's re-login row runs this same console flow on a Model Studio account, so the shell is no longer the only route to it. Starting one from nothing is still two steps, because the console a session comes from is read off the endpoint: give the account a Qwen preset first, then log in.
Per account, on the Setup tab or in config.toml:
[models]
default = "opusplan" # preset alias or a full model id
opus = "claude-opus-4-5-20251101" # ANTHROPIC_DEFAULT_OPUS_MODEL
sonnet = "claude-sonnet-4-5-20250929" # ANTHROPIC_DEFAULT_SONNET_MODEL
haiku = "claude-haiku-4-5-20251001" # ANTHROPIC_DEFAULT_HAIKU_MODEL
fable = "claude-fable-5" # ANTHROPIC_DEFAULT_FABLE_MODEL
subagent = "claude-sonnet-4-5-20250929" # CLAUDE_CODE_SUBAGENT_MODELdefault lands as the top-level model key in settings.json; the rest ride in its env block. A switch or a clauth start applies whichever account you land on.
A preset is a named base_url + [models] pair you can stamp onto any account from the Setup tab's a menu. Six ship built in:
| Preset | Endpoint |
|---|---|
DeepSeek |
https://api.deepseek.com/anthropic |
Z.ai |
https://api.z.ai/api/anthropic |
Qwen-TokenPlan-Intl |
https://token-plan.ap-southeast-1.maas.aliyuncs.com/apps/anthropic |
Qwen-TokenPlan-CN |
https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic |
Qwen-CodingPlan-Intl |
https://coding-intl.dashscope.aliyuncs.com/apps/anthropic |
Qwen-CodingPlan-CN |
https://coding.dashscope.aliyuncs.com/apps/anthropic |
DeepSeek and Z.ai set the endpoint plus a base model, leaving the tier rows yours to pin afterwards. The four Alibaba ones fill every row instead, because those endpoints reject a Claude model id outright rather than serving something for it, so any alias left unpinned fails on use. All six leave the api key alone; pick the region your plan was bought in, since a key issued for one is not accepted by the other. Once a preset is stamped on, open provider console in the same menu opens that endpoint's own key page (above).
save as preset stores the focused account's own endpoint and models under a name you type, in ~/.clauth/presets/<name>.json:
{ "base_url": "https://api.example/anthropic", "models": { "default": "my-model" } }apply preset opens the picker, built-ins first. Applying replaces the account's endpoint and its whole [models] block, so a tier the preset leaves unset is cleared rather than kept; the picker warns and names the fields first when the account already carries any. The account's own api key is never touched, and a preset never carries one. d in the picker deletes a saved preset; the built-ins have no file and stay.
The 5h window opens on a real inference call. clauth's own token refresh does not trip it, so an account can read 0% while the clock has yet to start.
auto_start = true # per profile; older spelling kick_timer still readsclauth then sends a 1-token Haiku ping on launch and on each refresh tick while no window is running. On a cold start it fetches usage before the first ping, so it never fires over a window that might already be live. That costs a fraction of a cent and it is a real billed /v1/messages call under your own token. Default off, OAuth accounts only.
If the messages limiter is blocking Claude Code, a live 5h window will not clear it. clauth re-tests with the same ping on the poll cadence and can rotate the chain around an account whose ping keeps getting rejected.
| Key | Type | Default | Controls |
|---|---|---|---|
active_profile |
string | none | the account currently linked into ~/.claude
|
profiles |
list | [] |
display order |
fallback_chain |
list | [] |
ordered chain members (Auto-switch) |
refresh_interval_ms |
int | 90000 |
usage poll cadence, 10 s to 1 h |
refresh_spent_accounts |
bool | true |
keep polling accounts at 100% |
preemptive_rotation |
bool | true |
rotate OAuth ahead of expiry; false waits for a rejection |
weekly_switch_threshold |
float | 98.0 |
chain-wide 7d exhaustion line, 50-100 |
burn_aware_switching |
bool | false |
project usage forward instead of comparing to the threshold |
burn_switch_floor_pct |
float | 98.0 |
earliest point burn-aware may switch, 90-100 |
burn_horizon_cap_ms |
int | 60000 |
how far ahead burn-aware projects |
wrap_off |
bool | false |
switch off all accounts once the chain is out of quota |
spend_budget_switching |
bool | false |
master switch for pay-as-you-go fallback |
switch_off_when_budget_spent |
bool | true |
switch off once the spend ceiling is used up |
auto_rescue |
bool | false |
lift an isolated run's transcripts into the global store before teardown |
default_divergence |
string | none | auto-resolve a credential mismatch: Overwrite, NewProfile, Discard
|
theme |
string | auto |
full or compatible
|
reset_display |
string | relative |
relative, clock, both
|
clock_format |
string | 24h |
24h or 12h
|
show_estimates |
bool | true |
burn estimates on the Usage tab |
show_pace |
bool | false |
ideal-pace marker on usage bars |
count_cache |
bool | false |
count cache tokens in the Tokens totals |
auth_broken |
list | [] |
accounts quarantined after a permanent OAuth rejection; clauth writes this |
| Key | Type | Default | Controls |
|---|---|---|---|
base_url |
string | none | API endpoint; unset means an OAuth account |
api_key |
string | none | key for that endpoint |
auto_start |
bool | false |
the 1-token window-opening ping (alias kick_timer) |
disabled |
bool | false |
hide from auto-switch, polling, and the status feed |
fallback_threshold |
float | 95.0 |
5h utilization % that switches away from this account |
weekly_threshold |
float | chain value | per-account override of the 7d line, 50-100 |
check_weekly |
bool | true |
count the aggregate weekly window against this account |
check_scoped |
bool | true |
count per-model weekly windows against this account |
last_resort |
bool | false |
the chain's parking spot |
preferred |
bool | false |
the home account clauth returns to once it is clear |
max_auto_spend |
float | 0.0 |
dollar ceiling on pay-as-you-go fallback |
bell_threshold |
float | none | 5h % that fires a bell toast |
rolling_token |
bool | false |
daemon re-stamps the sidecar from the usage chain; set by clauth rolling-token, cleared by clauth static-token (bare or --clear) |
[env] |
table | {} |
extra environment variables merged into settings.json while active |
[models] |
table | {} |
default, opus, sonnet, haiku, fable, subagent
|
[console] |
table | {} |
Alibaba Model Studio usage session: token, site (international / domestic), region (ap-southeast-1 / cn-beijing). clauth login writes it (above) |
last_resort and preferred are radio toggles across the chain: marking one clears it everywhere else, and no account can be both.
~/.clauth/
profiles.toml # everything in the table above
price_cache.json # LiteLLM model prices for the cost lens
status_cache.json # status.claude.com incident feed
status.json # the daemon's published snapshot (see Daemon)
clauth.log, daemon.log # event lines from the TUI and the daemon
completions/ # generated shell completion scripts
jobs/<id>.json # backgrounded delegate jobs, GC'd after an hour
live_sessions/<sid>.json # one row per live `clauth start` session
profiles/
work/
config.toml # everything in the table above
credentials.json # OAuth snapshot (.pending while a rotation is mid-write)
session-token.json # long-lived setup-token login, when captured
session-token.static.json # the mint a rolling token superseded, kept for the restore
usage_cache.json # last-known utilization and plan
usage_history.jsonl # 2 days of samples, feeding burn-aware switching
third_party_cache.json
third_party_auth.json# set while the usage login is expired; a hash, never the credential
account_id.json # which account this is, so a re-login can be told apart
profile_fetched.json # when the plan tier was last read
kick_block.json # messages-limiter block state
throughput_cache.json# observed delegate tokens/sec per model
runtime-<sid>/ # one CLAUDE_CONFIG_DIR tree per live session
runtime-isolated-<sid>/
sessions-<sid>/ # that session's PID file, flock-held while it runs
Lock files (.lock, clauthd.lock, usage-fetch.lock) sit alongside. Everything clauth owns is 0600, every directory 0700, re-tightened on each launch.
Deleting any *_cache.json, usage_history.jsonl, third_party_auth.json, or status.json costs you history and nothing else. Deleting credentials.json or session-token.json signs that profile out.
The -<sid> suffix appears only where the OS grants symlinks. Windows without symlink privilege builds the runtime tree by copying ~/.claude/, so every session of one profile shares a single unsuffixed runtime/ instead of paying for a copy each.
Start here
Reference
Headless
Help