Skip to content

Security

github-actions[bot] edited this page Aug 8, 2026 · 5 revisions

Security

This page covers where your logins sit and how they move between accounts. The trust model, every host clauth contacts, the update verification chain, and vulnerability reporting live in SECURITY.md.

Where credentials live

Path Holds
~/.clauth/profiles/<name>/credentials.json that account's OAuth token pair
~/.clauth/profiles/<name>/session-token.json a long-lived claude setup-token login, when captured
~/.clauth/profiles/<name>/config.toml the endpoint API key, for endpoint accounts

Every file clauth writes is 0600 and every directory 0700 on Unix, created that way rather than chmod'd afterwards, and re-tightened on each launch. Windows falls back to the default user-profile ACLs, which clauth does not loosen. Writes are atomic: temp file, fsync, rename. A rotation caught mid-write lands as credentials.json.pending and is promoted only once it is durable.

An endpoint account's API key reaches Claude Code through apiKeyHelper, so it never lands in settings.json.

What a switch touches

File Change
~/.claude/.credentials.json repointed at the target profile's stored login
~/.claude/settings.json the env block, the top-level model key, apiKeyHelper
~/.claude.json the stale account-identity block is dropped, so Claude Code re-derives identity from the new token

Nothing else moves. Hooks, permissions, status line, projects, plugins, MCP servers, and token stats are all left where they are.

Per-platform behavior

Where Claude Code reads its login from is platform-split, and assuming Linux behavior on a Mac is the trap.

  • Linux. The plaintext credentials file only, re-read whenever its modification time moves. clauth stamps that time explicitly on every swap, so a live session follows the new account.
  • macOS. The Keychain first, the file only on a miss, and Claude Code deletes the file once it migrates tokens into the Keychain. The file swap alone is cosmetic there, so clauth mirrors each fresh login into the Claude Code-credentials Keychain item as well. That item is namespaced per config dir, so a clauth start runtime and a bare claude never share one. clauth writes that item and never reads it back.
  • Windows. No symlinks and no Keychain: the swap is a file copy, read directly.

macOS is why clauth login exists at all. Claude Code's own /login under a custom config dir writes only a per-config-dir Keychain item, leaving the profile's credentials file empty.

Session isolation

clauth start <profile> builds that session its own CLAUDE_CONFIG_DIR under the profile directory, so identity, settings, and billing caches never leak between accounts running at once. The tree is torn down when the session ends. --isolated goes further and drops your global memory, plugins, and hooks, keeping only the account's auth.

Token rotation

clauth rotates each account's OAuth pair ahead of expiry, early enough that a running claude never reaches its own refresh threshold. Set Config tab rotation to lazy to refresh only after a request is rejected.

Refresh tokens are single-use. The active account shares one chain with the running claude, and whichever side refreshes first revokes the other, so clauth never bets on winning that race: when Claude Code rotates first, clauth adopts its fresher pair from the file mirror rather than spending a revoked token. That adoption is identity-guarded, so a login belonging to a different account is never captured unattended. A double-spend costs the loser one rejected request, never the account.

A refresh that fails terminally quarantines the account as auth broken. It is then excluded from every chain walk and refused as a switch target, since installing a dead token would sign out every running session. clauth login <name>, or any later successful refresh, clears it.

Account-change detection

If Claude Code logged into a different account while clauth was closed, the next launch asks before overwriting anything: keep the stored login, capture the live one as a new profile, or discard it. Config tab on mismatch picks an answer up front.

Switching things off

Switch Effect
CLAUTH_NO_UPDATE=1 no background update check, no self-replacement
CLAUTH_NO_COMPLETIONS=1 no first-run completions prompt
auto_start = false (the default) clauth sends no inference of its own
an empty fallback_chain (the default) clauth never switches accounts on its own
allow extra usage off (the default) clauth never spends pay-as-you-go money

Found something exploitable? Report it privately through the repo's Security → Report a vulnerability.

Clone this wiki locally