Skip to content

Files and storage

claude-code-proxy separates configuration and credentials from runtime state.

Platform Configuration root State root
macOS, Linux, Windows native builds ${XDG_CONFIG_HOME:-<home>/.config}/claude-code-proxy ${XDG_STATE_HOME:-<home>/.local/state}/claude-code-proxy
Docker /var/lib/claude-code-proxy/config /var/lib/claude-code-proxy/state/claude-code-proxy

<home> is HOME, falling back to USERPROFILE. The current native resolver uses these XDG-style paths on all three platforms; Windows builds do not automatically select APPDATA or LOCALAPPDATA. The notation above describes defaults, not Windows shell syntax.

CCP_CONFIG_DIR replaces the configuration root for the current process, including legacy credential and Kimi device identity fallback and logout. It does not change the state root. Set XDG_STATE_HOME separately when logs and captures must also be isolated. Without an explicit override, legacy credential migration remains available.

config.json lives directly under the configuration root. See Configuration for its schema and precedence.

Provider logins are saved to <configuration-root>/<provider>/auth.json. On macOS, Codex and Cursor can also read older proxy-owned Keychain entries when no CCP_CONFIG_DIR override is set:

  • claude-code-proxy.codex
  • claude-code-proxy.cursor

The credential file takes precedence over a Keychain entry. The current implementation saves new or refreshed credentials to files; Keychain writes are unavailable in its compatibility mode. File-backed credentials are written with restrictive permissions where supported. Linux and Windows use the same provider file layout without this macOS compatibility lookup.

When CCP_CONFIG_DIR is set, file-backed provider credentials use <CCP_CONFIG_DIR>/<provider>/auth.json, including Codex and Cursor on macOS. CCP_CURSOR_AUTH_TOKEN bypasses Cursor’s local credential store for that process.

OpenCode Go is the exception: it reads its API key from CCP_OPENCODE_API_KEY, OPENCODE_API_KEY, or opencode.apiKey in config.json and does not create a provider auth store.

The proxy owns these credentials independently of native Codex, Grok, and Cursor Agent stores.

Use a dedicated CCP_CONFIG_DIR for an independent proxy instance, including a container deployment, and authenticate that profile explicitly. The root must remain writable because token refresh replaces credential files atomically. Keep Kimi’s device ID with its login.

A Linux container cannot use the host’s macOS Keychain directly. A read-only credential mount also cannot persist refreshed tokens. Avoid running host and container proxies against the same writable login files: refresh coordination is currently in process, so independent processes can race when rotating tokens. Prefer one credential writer per profile.

Kimi stores a persistent UUID at <configuration-root>/kimi/device_id for file-backed setups. It is bound into the Kimi token and must remain paired with that login.

proxy.log lives under the state root. It uses JSON Lines and rotates at 20 MiB. Known credential keys, including authorization, access tokens, refresh tokens, ID tokens, and account headers, are redacted before writing.

When running under a service manager, configure stdout and stderr destinations there; the proxy does not create a separate service.log.

errors/ under the state root contains JSON files for failed proxy responses. A request_failed log event includes errorFile, which points to the complete redacted payload.

Error payloads are safer to share than raw traffic captures, but inspect their prompt-derived content and paths before publishing them.

Set CCP_TRAFFIC_LOG=1 to create captures under traffic/ in the state root. Requests are grouped by Claude Code session and request sequence. A request directory can include:

  • inbound Anthropic request and metadata
  • translated upstream request
  • upstream URL and redacted headers
  • raw or decoded upstream events
  • translated downstream events and response
  • transport or reducer error details

Event filenames use monotonic sequence numbers so lexical order preserves emission order.

Traffic captures preserve content. Header and token redaction does not remove prompts, source code, tool definitions, tool inputs, tool results, images, or provider output. Treat the entire directory as sensitive user data.

Enable capture only for a focused reproduction, keep the directory local, and delete it after the investigation.

The active configuration root contains these setup files:

File Purpose
ui-access.json Private management bearer key, reused across restarts
session-profile.json Versioned four-role selections and client session preferences, saved atomically
ui-runtime.json Running instance address and version
ui-instance.lock Single server ownership of this profile
ui-key.lock Coordination between CLI bootstrap and server key creation

Provider credentials retain the files described above. Docker stores configuration under /var/lib/claude-code-proxy/config and application state under /var/lib/claude-code-proxy/state/claude-code-proxy, in one named profile volume. Protect backups of that volume as credentials. See Docker setup and updates for recreation, image replacement, and volume removal behavior.