somratpro commited on
Commit
5ee080c
Β·
1 Parent(s): be00cf7

chore: update Claude Code authentication environment variables and configuration to use CLAUDE_CODE_OAUTH_TOKEN

Browse files
Files changed (3) hide show
  1. .env.example +4 -4
  2. Dockerfile +5 -5
  3. start.sh +9 -32
.env.example CHANGED
@@ -48,10 +48,10 @@ PAPERCLIP_DEPLOYMENT_MODE=authenticated
48
  # Claude Code β€” choose one mode or neither:
49
  #
50
  # Subscription mode (Claude Pro/Max β€” no per-token cost):
51
- # 1. Run `claude login` locally to authenticate once
52
- # 2. Copy the token from ~/.claude/.credentials.json
53
- # 3. Paste it here (takes priority over API key if both are set)
54
- # ANTHROPIC_AUTH_TOKEN=your-oauth-token-from-credentials-json
55
  #
56
  # API key mode (pay-per-use):
57
  # ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
48
  # Claude Code β€” choose one mode or neither:
49
  #
50
  # Subscription mode (Claude Pro/Max β€” no per-token cost):
51
+ # Generate a long-lived token (valid 1 year) at:
52
+ # claude.ai β†’ Settings β†’ Claude Code β†’ "Create token"
53
+ # Then set: export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...
54
+ # CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxxxxxxxxxxxxxxxxx
55
  #
56
  # API key mode (pay-per-use):
57
  # ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Dockerfile CHANGED
@@ -58,17 +58,17 @@ RUN npm init -y && npm install express@4 cors morgan
58
  RUN npm install -g @google/gemini-cli @anthropic-ai/claude-code @openai/codex
59
 
60
  # Claude Code wrapper β€” auth mode selection:
61
- # ANTHROPIC_AUTH_TOKEN set β†’ subscription mode (OAuth token, takes priority)
62
- # ANTHROPIC_API_KEY set β†’ API key mode
63
- # Neither set β†’ uses stored OAuth credentials in ~/.claude/
64
- # If both are set, subscription token wins: unset API key to avoid conflict.
65
  # Also drops cloudflare NODE_OPTIONS and caps heap size.
66
  RUN if [ -e /usr/local/bin/claude ]; then \
67
  mv /usr/local/bin/claude /usr/local/bin/claude-real && \
68
  { \
69
  echo '#!/bin/sh'; \
70
  echo 'unset NODE_OPTIONS'; \
71
- echo '[ -n "$ANTHROPIC_AUTH_TOKEN" ] && unset ANTHROPIC_API_KEY'; \
72
  echo 'export NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"'; \
73
  echo 'exec /usr/local/bin/claude-real "$@"'; \
74
  } > /usr/local/bin/claude && \
 
58
  RUN npm install -g @google/gemini-cli @anthropic-ai/claude-code @openai/codex
59
 
60
  # Claude Code wrapper β€” auth mode selection:
61
+ # CLAUDE_CODE_OAUTH_TOKEN set β†’ long-lived subscription OAuth token (sk-ant-oat01-...)
62
+ # takes priority; unset API key to avoid conflict
63
+ # ANTHROPIC_API_KEY set β†’ API key mode (pay-per-use)
64
+ # Neither set β†’ uses stored credentials in ~/.claude/
65
  # Also drops cloudflare NODE_OPTIONS and caps heap size.
66
  RUN if [ -e /usr/local/bin/claude ]; then \
67
  mv /usr/local/bin/claude /usr/local/bin/claude-real && \
68
  { \
69
  echo '#!/bin/sh'; \
70
  echo 'unset NODE_OPTIONS'; \
71
+ echo '[ -n "$CLAUDE_CODE_OAUTH_TOKEN" ] && unset ANTHROPIC_API_KEY'; \
72
  echo 'export NODE_OPTIONS="--max-old-space-size=4096 --no-deprecation --no-warnings"'; \
73
  echo 'exec /usr/local/bin/claude-real "$@"'; \
74
  } > /usr/local/bin/claude && \
start.sh CHANGED
@@ -37,9 +37,10 @@ export PAPERCLIP_ALLOWED_HOSTNAMES="${PAPERCLIP_ALLOWED_HOSTNAMES:-${_ALLOWED}}"
37
  export GEMINI_API_KEY="${GEMINI_API_KEY:-}"
38
  export OPENAI_API_KEY="${OPENAI_API_KEY:-}"
39
  # Anthropic/Claude Code β€” set one or neither:
40
- # ANTHROPIC_AUTH_TOKEN : subscription mode (OAuth token from ~/.claude/.credentials.json)
41
- # ANTHROPIC_API_KEY : API key mode (sk-ant-...)
42
- export ANTHROPIC_AUTH_TOKEN="${ANTHROPIC_AUTH_TOKEN:-}"
 
43
  export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
44
 
45
  mkdir -p "${PAPERCLIP_HOME}"
@@ -68,9 +69,9 @@ if [ -z "${PAPERCLIP_AGENT_JWT_SECRET:-}" ]; then
68
  fi
69
 
70
  # ── Validate LLM providers ───────────────────────────────────────────────────
71
- if [ -z "${GEMINI_API_KEY:-}" ] && [ -z "${ANTHROPIC_API_KEY:-}" ] && [ -z "${ANTHROPIC_AUTH_TOKEN:-}" ] && [ -z "${OPENAI_API_KEY:-}" ]; then
72
  echo "⚠️ WARNING: No LLM provider configured"
73
- echo " Set at least one of: GEMINI_API_KEY, ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, OPENAI_API_KEY"
74
  echo " Agents will fail to run without an LLM provider"
75
  echo ""
76
  fi
@@ -292,37 +293,13 @@ cleanup() {
292
  }
293
  trap cleanup SIGTERM SIGINT
294
 
295
- # ── Claude Code credentials ──────────────────────────────────────────────────
296
- # ANTHROPIC_AUTH_TOKEN may not reach the claude subprocess if Paperclip spawns
297
- # with a restricted env. Writing ~/.claude/.credentials.json bypasses that β€”
298
- # Claude Code reads OAuth tokens directly from the filesystem.
299
- if [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ]; then
300
- mkdir -p /home/paperclip/.claude
301
- python3 -c "
302
- import json, os
303
- creds = {
304
- 'claudeAiOauth': {
305
- 'accessToken': os.environ['ANTHROPIC_AUTH_TOKEN'],
306
- 'refreshToken': '',
307
- 'expiresAt': 9999999999999,
308
- 'scopes': ['user:inference']
309
- }
310
- }
311
- with open('/home/paperclip/.claude/.credentials.json', 'w') as f:
312
- json.dump(creds, f)
313
- "
314
- chmod 600 /home/paperclip/.claude/.credentials.json
315
- chown -R paperclip:paperclip /home/paperclip/.claude
316
- fi
317
-
318
  # ── Codex API key config ─────────────────────────────────────────────────────
 
 
319
  if [ -n "${OPENAI_API_KEY:-}" ]; then
320
  mkdir -p /home/paperclip/.codex
321
- cat > /home/paperclip/.codex/config.toml <<TOMLEOF
322
  forced_login_method = "api"
323
-
324
- [model_providers.openai]
325
- experimental_bearer_token = "${OPENAI_API_KEY}"
326
  TOMLEOF
327
  chmod 600 /home/paperclip/.codex/config.toml
328
  chown -R paperclip:paperclip /home/paperclip/.codex
 
37
  export GEMINI_API_KEY="${GEMINI_API_KEY:-}"
38
  export OPENAI_API_KEY="${OPENAI_API_KEY:-}"
39
  # Anthropic/Claude Code β€” set one or neither:
40
+ # CLAUDE_CODE_OAUTH_TOKEN : long-lived OAuth token (sk-ant-oat01-..., 1 year)
41
+ # Generate at: claude.ai/settings β†’ "Claude Code" β†’ "Create token"
42
+ # ANTHROPIC_API_KEY : API key mode (sk-ant-api03-..., pay-per-use)
43
+ export CLAUDE_CODE_OAUTH_TOKEN="${CLAUDE_CODE_OAUTH_TOKEN:-}"
44
  export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
45
 
46
  mkdir -p "${PAPERCLIP_HOME}"
 
69
  fi
70
 
71
  # ── Validate LLM providers ───────────────────────────────────────────────────
72
+ if [ -z "${GEMINI_API_KEY:-}" ] && [ -z "${ANTHROPIC_API_KEY:-}" ] && [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ] && [ -z "${OPENAI_API_KEY:-}" ]; then
73
  echo "⚠️ WARNING: No LLM provider configured"
74
+ echo " Set at least one of: GEMINI_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_API_KEY, OPENAI_API_KEY"
75
  echo " Agents will fail to run without an LLM provider"
76
  echo ""
77
  fi
 
293
  }
294
  trap cleanup SIGTERM SIGINT
295
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  # ── Codex API key config ─────────────────────────────────────────────────────
297
+ # forced_login_method="api" tells codex to read OPENAI_API_KEY from env.
298
+ # Note: [model_providers.openai] is a reserved built-in β€” cannot override it.
299
  if [ -n "${OPENAI_API_KEY:-}" ]; then
300
  mkdir -p /home/paperclip/.codex
301
+ cat > /home/paperclip/.codex/config.toml <<'TOMLEOF'
302
  forced_login_method = "api"
 
 
 
303
  TOMLEOF
304
  chmod 600 /home/paperclip/.codex/config.toml
305
  chown -R paperclip:paperclip /home/paperclip/.codex