Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Per-profile state lives under `~/.clauth/`. On Unix that whole tree is owner-onl
| `~/.clauth/profiles/<name>/credentials.json.staged` | a refreshed OAuth pair waiting to land in `credentials.json` | file `0600` |
| `~/.clauth/profiles/<name>/auth.spent.json` | fingerprints of the last 64 refresh tokens clauth traded in, never a token | file `0600` |
| `~/.clauth/profiles/<name>/mcp-logins.json` | Claude Code's MCP-server OAuth logins, parked here whenever the profile stores no Claude login of its own and merged back once it regains one. Live bearer credentials, minted against each server and belonging to no Claude account | file `0600`, dirs `0700` |
| `~/.clauth/mcp-sync-state.json` | what the MCP login sync saw on its last pass: per source and per MCP server, which login it held, as a truncated SHA-256 of that login's token, and which logins were signed out; never a token. One that does not read is renamed `mcp-sync-state.json.corrupt-<epoch_ms>` before the next save | file `0600` |
| `~/.clauth/profiles/<name>/session-token.json` | long-lived `claude setup-token` login, if captured (sessions run on this; no refresh token), plus the keys Claude Code saved beside it while `preserve_non_login_keys` is on (a design login, which carries a refresh token of its own, read from Claude Code 2.1.283) | file `0600`, dirs `0700` |
| `~/.clauth/profiles/<name>/session-token.static.json` | the `claude setup-token` mint a rolling token superseded, kept so `clauth static-token <p>` (or a dead chain) can restore it, with the keys the sidecar held beside it at that point (a design login, which carries a refresh token of its own, and MCP-server logins, which can carry one; read from Claude Code 2.1.283) | file `0600`, dirs `0700` |
| `~/.clauth/profiles/<name>/quarantine/<ts>-<seq>.<basename>` | credential files moved aside before repair, kept as evidence — a mis-filled sidecar (`….session-token.json`, which by definition carries a refresh token: that is what made it a mis-fill) or a backup slot whose content was not a mint (`….session-token.static.json`). Evidence can hold live credentials, which is why the dir is `0700`, why nothing prunes it automatically, and why it lives under the profile so `clauth delete` removes it with everything else that account owns | file `0600`, dir `0700` |
Expand Down Expand Up @@ -69,6 +70,7 @@ clauth reads that item before every write (to carry your MCP-server logins acros
- A switch rewrites three files: `~/.claude/.credentials.json`, parts of `~/.claude/settings.json` (the `env` block, the top-level `model` key, `apiKeyHelper`), and `~/.claude.json`, whose stale account-identity block is dropped so Claude Code re-derives identity from the new token.
- The rest of `~/.claude/` is left alone. On macOS the switch writes the Keychain item above as well, because Claude Code reads the Keychain before the file there.
- Inside `~/.clauth/` a switch writes the incoming profile's store (the MCP-server logins it carries) and, with `preserve_non_login_keys` on, the outgoing profile's store, which takes what Claude Code saved beside that account's login. The daemon's and the TUI's start relink save into the active profile's store the same way. A switch normally also writes `~/.clauth/base-env.json` (the row above), which names the account it left active and holds your own `settings.json` values under custom env keys an account's `[env]` replaced.
- With `sync_mcp_logins` on (the default), the daemon also writes the store of every profile that keeps a Claude login or MCP logins in it, its `mcpOAuth` key only, when another store, a parked login, a running session's credentials file or (macOS) its per-session Keychain item holds a newer MCP-server login, and when it removes from that store a login one of those signed out of; on macOS a swap's hand-off does the same from the session's item. A profile with no such store (an api-key or third-party account) gets none. Neither writes a store a running session reads through its link, a Claude Code background job included, nor the store a running session's copy mirrors on a host without symlinks, nor the store of a session whose own file waits for the watchdog to copy it back, while that session runs, and neither writes anything while Claude Code's job list or clauth's live-session list cannot be read.
- `clauth login <name> --codex` is the one write into codex's own tree: it replaces `~/.codex/auth.json` with a symlink onto that profile's store (staged beside it and renamed over), so your codex and every clauth session share one chain; deleting the profile removes that link and says so. On a host without symlinks the file is copied instead and your codex keeps a second live copy of the chain, which clauth tells you at capture time.

## Network activity
Expand Down
Loading
Loading