Spaces:
Running
Running
chore: update Claude Code authentication environment variables and configuration to use CLAUDE_CODE_OAUTH_TOKEN
Browse files- .env.example +4 -4
- Dockerfile +5 -5
- 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 |
-
#
|
| 52 |
-
#
|
| 53 |
-
#
|
| 54 |
-
#
|
| 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 |
-
#
|
| 62 |
-
#
|
| 63 |
-
#
|
| 64 |
-
#
|
| 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 "$
|
| 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 |
-
#
|
| 41 |
-
#
|
| 42 |
-
|
|
|
|
| 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 "${
|
| 72 |
echo "β οΈ WARNING: No LLM provider configured"
|
| 73 |
-
echo " Set at least one of: GEMINI_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
|