Files and storage
claude-code-proxy separates configuration and credentials from runtime state.
Directory roots
Section titled “Directory roots”| Platform | Configuration root | State root |
|---|---|---|
| macOS | ~/.config/claude-code-proxy |
${XDG_STATE_HOME:-~/.local/state}/claude-code-proxy |
| Linux | ${XDG_CONFIG_HOME:-~/.config}/claude-code-proxy |
${XDG_STATE_HOME:-~/.local/state}/claude-code-proxy |
| Windows | %APPDATA%/claude-code-proxy |
%LOCALAPPDATA%/claude-code-proxy |
Windows falls back to %USERPROFILE%/AppData/Roaming and %USERPROFILE%/AppData/Local when the corresponding environment variable is absent.
CCP_CONFIG_DIR replaces the configuration root for the current process. It does not change the state root.
Configuration
Section titled “Configuration”config.json lives directly under the configuration root. See Configuration for its schema and precedence.
Provider credentials
Section titled “Provider credentials”On macOS, Codex and Cursor use Keychain services:
claude-code-proxy.codexclaude-code-proxy.cursor
Kimi and Grok use <configuration-root>/<provider>/auth.json on every platform. Codex and Cursor use the same file layout on Linux and Windows. File-backed credentials are written with restrictive permissions where supported.
When CCP_CONFIG_DIR is set, every provider uses <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.
The proxy owns these credentials independently of native Codex, Grok, and Cursor Agent stores.
Kimi device ID
Section titled “Kimi device ID”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.
Structured log
Section titled “Structured log”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.
A Homebrew service also writes service.log under the state root.
Failed responses
Section titled “Failed responses”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.
Traffic captures
Section titled “Traffic captures”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.
Enable capture only for a focused reproduction, keep the directory local, and delete it after the investigation.