cctop reads local files that Claude Code and Codex already write, plus a small number of free, read-only API calls. It touches OAuth tokens only to the extent required to make those reads. This document states exactly what it does and does not do, because a tool that sits next to your credentials should be auditable.
| Source | Purpose |
|---|---|
~/.claude*/sessions/<pid>.json, transcripts, stats-cache.json |
live sessions, tokens, cost, activity |
~/.codex/sessions/** rollout files, ps |
live Codex sessions and stats |
GET https://api.anthropic.com/api/oauth/usage |
real Claude usage limits (the endpoint /usage uses) |
GET https://chatgpt.com/backend-api/codex/usage |
real Codex usage limits |
macOS Keychain item Claude Code-credentials-<hash>, or ~/.claude*/.credentials.json |
the OAuth token used to authenticate the two GETs above |
~/.codex/auth.json |
the token used to authenticate the Codex usage GET |
All of it is read-only. The two usage GETs are plain reads that consume no message quota.
- It reads the token for an account only from that account's own store (its per-config-dir Keychain service or its own credentials file), never from a shared default, so one account can never be authenticated with another's token. The usage response's organization is additionally verified against the account.
- The token is placed in the
Authorizationheader of the usage GET and used nowhere else. - The token is never logged, printed, written to disk by cctop, included in
--jsonoutput, or transmitted anywhere except the provider's own API (api.anthropic.com/chatgpt.com) that issued it.
cctop is read-only except for explicit actions you invoke:
- Account provisioning (
add-account, theakey): creates a new~/.claude-Ndirectory; with--aliasappends one shell-rc line (after backing the file up); with--fromcopies an allowlist of user config (CLAUDE.md,settings.json,commands/agents/skills/hooks/output-styles) — never credentials, identity (.claude.json), or session state. It never deletes, overwrites, or edits existing lines. - Token refresh (automatic near expiry and on a 401, or the
Rkey): runsclaude mcp listfor an account so the Claude Code binary itself renews its own token at startup (a quota-free, non-interactive command). cctop does not write the credential; it delegates to the tool that owns it. Automatic attempts are bounded (a failed refresh backs off and goes quiet until a real/loginchanges the stored expiry) and can be disabled withauto_refresh_tokens = false. - Session resume (
Enterin history search): hands the terminal toclaude --resume/codex resumefor the selected session, withCLAUDE_CONFIG_DIRpinned to the session's own account. The search itself is a read-only ripgrep scan of the transcript files; any new conversation content is written by the resumed tool, never by cctop.
There is deliberately no delete, logout, or credential-writing path in cctop's own code.
This is a personal project; open an issue for anything that looks wrong. If you find a genuine credential-handling flaw, please report it privately first.