Skip to content

Instantly share code, notes, and snippets.

@Prajwalsrinvas
Created February 17, 2026 12:17
Show Gist options
  • Select an option

  • Save Prajwalsrinvas/cacbb728c4ea06c3bc1676608d3c72dc to your computer and use it in GitHub Desktop.

Select an option

Save Prajwalsrinvas/cacbb728c4ea06c3bc1676608d3c72dc to your computer and use it in GitHub Desktop.
Claude Code Credentials: Read & Write Tokens on Every OS

Claude Code Credentials: Read & Write Tokens on Every OS

Claude Code stores OAuth tokens differently per platform. Here's how to access them manually.

Where Tokens Live

Platform Storage Location
macOS Encrypted Keychain Service: Claude Code-credentials
Linux JSON file ~/.claude/.credentials.json
Windows (WSL) JSON file ~/.claude/.credentials.json (inside WSL)
Windows (native) JSON file %USERPROFILE%\.claude\.credentials.json

Note: On macOS, Claude Code actively deletes ~/.claude/.credentials.json and migrates credentials into the Keychain. Don't expect the file to persist on Mac.

Token Format

All platforms store the same JSON structure:

{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-...",
    "refreshToken": "sk-ant-ort01-...",
    "expiresAt": 1748276587173,
    "scopes": ["user:inference", "user:profile"]
  }
}

macOS

Read:

security find-generic-password -s "Claude Code-credentials" -w

Write:

security add-generic-password -U -s "Claude Code-credentials" -a "$USER" -w '{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-YOUR_TOKEN",
    "refreshToken": "sk-ant-ort01-YOUR_REFRESH_TOKEN",
    "expiresAt": 1748276587173,
    "scopes": ["user:inference", "user:profile"]
  }
}'

Delete:

security delete-generic-password -s "Claude Code-credentials"

If you're SSH'd into a Mac, you may need to unlock the Keychain first:

security unlock-keychain ~/Library/Keychains/login.keychain-db

Linux

Read:

cat ~/.claude/.credentials.json

Write:

mkdir -p ~/.claude
cat > ~/.claude/.credentials.json << 'EOF'
{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-YOUR_TOKEN",
    "refreshToken": "sk-ant-ort01-YOUR_REFRESH_TOKEN",
    "expiresAt": 1748276587173,
    "scopes": ["user:inference", "user:profile"]
  }
}
EOF
chmod 600 ~/.claude/.credentials.json
chmod 700 ~/.claude

Delete:

rm ~/.claude/.credentials.json

Windows (Native / PowerShell)

Read:

Get-Content "$env:USERPROFILE\.claude\.credentials.json"

Write:

New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude" | Out-Null
@'
{
  "claudeAiOauth": {
    "accessToken": "sk-ant-oat01-YOUR_TOKEN",
    "refreshToken": "sk-ant-ort01-YOUR_REFRESH_TOKEN",
    "expiresAt": 1748276587173,
    "scopes": ["user:inference", "user:profile"]
  }
}
'@ | Set-Content "$env:USERPROFILE\.claude\.credentials.json"

Delete:

Remove-Item "$env:USERPROFILE\.claude\.credentials.json"

For Windows via WSL, follow the Linux instructions inside your WSL distro.


Alternative: Environment Variable

Skip credential files entirely by exporting the token:

export CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-YOUR_TOKEN"

⚠️ This silently overrides any stored credentials. If you set this once and forget, you'll get confusing auth errors months later when the token expires.

Alternative: Long-Lived Tokens (setup-token)

For CI/CD and headless environments:

claude setup-token

This opens a browser for OAuth, then outputs a long-lived token you can export as CLAUDE_CODE_OAUTH_TOKEN. Useful for GitHub Actions, Docker containers, and remote servers.


Why Would You Do This?

  • Docker / Devcontainers — Containers can't access the macOS Keychain. Export the token from your host and inject it into the container via credentials.json or CLAUDE_CODE_OAUTH_TOKEN.
  • SSH into macOS — SSH sessions can't reach the Keychain by default. Either unlock the keychain (security unlock-keychain) or write a credentials.json manually.
  • CI/CD Pipelines — GitHub Actions, GitLab CI, etc. need a token injected as a secret. Use claude setup-token to generate a long-lived one.
  • Multi-machine sync — Copy credentials across dev machines without re-authenticating on each.
  • Debugging auth issues — When Claude Code says "Missing API key" but you just logged in, inspecting the raw token helps pinpoint the problem (wrong service name, expired token, env var override, etc.).
  • Backup before reinstall — Save your token before nuking ~/.claude so you can restore without re-auth.

Quick Reference: macOS ↔ Docker Workflow

A common pattern for running Claude Code in containers from a Mac host:

# 1. Extract token from macOS Keychain
CREDS=$(security find-generic-password -s "Claude Code-credentials" -w)

# 2. Inject into container
docker run -it \
  -e CLAUDE_CODE_OAUTH_TOKEN="$(echo $CREDS | jq -r '.claudeAiOauth.accessToken')" \
  your-claude-container

# OR mount as a file
echo "$CREDS" > /tmp/claude-creds.json
docker run -it \
  -v /tmp/claude-creds.json:/root/.claude/.credentials.json:ro \
  your-claude-container

Last verified: Feb 2026 · Claude Code v2.1.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment