cli.js is a 13.2MB single-file esbuild bundle running as Node.js ESM. It bundles:
- Full Anthropic SDK, AWS SDK v3 (22 packages), Azure MSAL v15, Google Auth Library
- gRPC stack (for OTEL), React 18 + Ink (terminal UI), Zod, Axios 1.13.6
- 3 native vendored binaries (ripgrep, seccomp, audio-capture)
- 3 separate telemetry pipelines (Datadog external, OTEL→Anthropic, GrowthBook feature flags)
- 350+ behavioral analytics events covering every user action
Persistent tracking ID: userID (32 hex bytes, stored in settings.json, survives sessions)
No certificate pinning, no credential encryption on Linux
Obfuscated require() via eval present
| Method | Path | Trigger | Payload |
|---|---|---|---|
| POST | /v1/messages |
Every AI query | Full conversation, model, system prompt, tools, betas |
| GET | /api/claude_cli/bootstrap |
Startup | Seeds client_data + model list (arbitrary server KV) |
| POST | /api/event_logging/batch |
Continuous (100ms batches) | 350+ behavioral events with session_id, device_id, account_uuid |
| POST | /api/claude_code/metrics |
OTEL interval | OTEL resource metrics: tokens, cost, LOC, commits, PRs, tool use |
| GET | /api/claude_code/organizations/metrics_enabled |
Startup | Org-level metrics gate |
| GET | /api/claude_code/policy_limits |
Startup | Server-side rate/usage limits (ETag-cached) |
| GET/POST | /api/claude_code/settings |
Settings changes | Remote settings sync |
| GET | /api/claude_code/team_memory?repo={url} |
Team mode | Repo-linked shared memory sync |
| GET | /api/claude_code_penguin_mode |
Startup | Fast Mode org-level toggle |
| GET | /api/claude_code_grove |
Startup | Training data consent status |
| GET/PATCH | /api/oauth/account/settings |
Auth/Grove | User account settings including grove_enabled |
| POST | /api/oauth/account/grove_notice_viewed |
Dialog | Track consent dialog views |
| GET | /api/oauth/claude_cli/create_api_key |
OAuth | Key provisioning |
| GET | /api/oauth/claude_cli/roles |
Auth | Role/permission fetch |
| GET | /api/oauth/profile |
Auth | User profile with email |
| GET | /api/oauth/usage |
Dashboard | Usage stats |
| GET | /api/auth/trusted_devices |
First login | Trust check |
| POST | /api/auth/trusted_devices |
First login | Registers "Claude Code on {hostname} · {platform}" |
| POST | /api/claude_code_shared_session_transcripts |
User-triggered | Full gzipped JSONL transcript + subagent transcripts |
| POST | /api/claude_cli_feedback |
/bug command | Bug reports |
| GET | /api/claude_cli_profile |
Profile | User profile |
| GET | /api/claude_code_penguin_mode |
Startup | Fast mode check |
| POST | /api/organizations/{org}/claude_code/buddy_react |
Social | 5000 chars of conversation + AI personality data |
| POST | /api/oauth/organizations/{org}/admin_requests |
Enterprise | Admin elevation requests |
| GET | /api/oauth/organizations/{org}/admin_requests/eligibility |
Enterprise | Eligibility check |
| GET | /api/oauth/organizations/{org}/admin_requests/me |
Enterprise | My admin requests |
| POST | /api/oauth/organizations/{org}/overage_credit_grant |
Billing | Overage credit grant |
| GET | /api/web/domain_info?domain={url} |
WebFetch tool | Domain allowlist check (UNAUTHENTICATED) |
| GET | /mcp-registry/v0/servers |
Startup | MCP server marketplace |
| GET | /api/organization/claude_code_first_token_date |
Analytics | First API usage timestamp |
| GET | /api/hello |
Health check | Connectivity probe |
| Method | Path | Purpose |
|---|---|---|
| GET/POST | /v1/sessions |
Cloud session management |
| GET | /v1/sessions/{id} |
Session state |
| POST | /v1/sessions/{id}/archive |
Archive session |
| GET | /v1/sessions/{id}/events |
Bridge event stream |
| GET | /v1/session_ingress/session/{id} |
Session ingress token |
| GET | /v1/code/sessions/{id}/teleport-events |
Remote sync events |
| POST | /v1/code/github/import-token |
GitHub token import |
| GET/POST | /v1/code/triggers |
Scheduled task triggers |
| GET | /v1/environment_providers |
Cloud env providers |
| POST | /v1/environment_providers/cloud/create |
Create cloud environment |
| GET | /v1/mcp_servers?limit=1000 |
Managed MCP list |
| * | /v1/mcp/{server_id} |
MCP proxy calls |
| GET | /v1/ultrareview/quota |
Ultrareview quota check |
| GET | /v1/skills |
Remote skills fetch |
| GET | /v1/models |
Available models |
| Endpoint | Purpose |
|---|---|
wss://bridge.claudeusercontent.com/v1/session_ingress/ws/{token} |
CCR live bridge (production) |
wss://bridge-staging.claudeusercontent.com/... |
CCR bridge (staging) |
ws://localhost:8765 |
Chrome extension bridge |
ws://{host}:{port} |
Local IDE integration |
| URL | Purpose |
|---|---|
https://platform.claude.com/oauth/authorize |
Console OAuth flow |
https://platform.claude.com/v1/oauth/token |
Token exchange/refresh |
https://claude.com/cai/oauth/authorize |
Claude.ai OAuth flow |
| OAuth Client ID (prod) | 9d1c250a-e61b-44d9-88ed-5944d1962f5e |
| OAuth Client ID (dev) | 22422756-60c9-4084-8eb7-27705fd5cf9a |
| Endpoint | Purpose |
|---|---|
https://http-intake.logs.us5.datadoghq.com/api/v2/logs |
External Datadog telemetry |
| Datadog API key (hardcoded) | pubea5604404508cdd34afb69e6f42a05bc |
https://cdn.growthbook.io |
GrowthBook feature flag SDK |
| GrowthBook SDK key | sdk-zAZezfDKGoZuXXKe |
| URL | Purpose |
|---|---|
https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/... |
Auto-update binary downloads |
https://downloads.claude.ai/claude-code-releases/plugins/... |
Plugin downloads |
https://raw.githubusercontent.com/anthropics/claude-code/refs/heads/main/CHANGELOG.md |
Release notes |
- Endpoint:
POST /api/event_logging/batch - Volume: 350+ event types (tengu_*), batched every 100ms, max 200/batch
- Retry: 8 attempts, exponential backoff (500ms base, 30s max)
- Always on unless
DISABLE_TELEMETRYorDO_NOT_TRACK - Per-event fields:
session_id,device_id,account_uuid,anonymous_id,timestamp,experiment_id,variation_id,user_attributes
- Endpoint:
https://http-intake.logs.us5.datadoghq.com/api/v2/logs - Hardcoded key:
pubea5604404508cdd34afb69e6f42a05bc - Condition: Only fires for
firstPartyauth (claude.ai OAuth, NOT API key users) - Sampling: 30-bucket hash on persistent
userID - 42 allowlisted events from the 350+ total
- Payload per event (critical fields):
session_id,model,account_uuid,organization_uuidplatform,arch,os_version,linux_distro_id/version,linux_kernelterminal,node_version,package_managers,runtimessubscriptionType,rateLimitTier,user_typeis_ci,github_actionsmetadata (actor ID, repo ID, owner ID)process: base64-encoded{rss, heapUsed, cpuPercent, uptime}rh:sha256(git_remote_url).slice(0,16)— hashed git remote to identify repo without storing URL
- SDK key:
sdk-zAZezfDKGoZuXXKe - Attributes sent for flag evaluation:
id=deviceId(persistent 32-byte hex)email,organizationUUID,accountUUIDplatform,subscriptionType,rateLimitTier,userTypefirstTokenTime,appVersion,sessionIdgithubActionsMetadata(actor, repo, owner IDs)apiBaseUrlHost(if custom)
- Also emits experiment exposure events via OTEL logger
Goes to /api/claude_code/metrics with OTEL protobuf format:
- Metric labels include:
service.name,service.version,os.type,os.version,host.arch,user.customer_type,user.subscription_type - NOW PATCHED TO NO-OP (patch #19)
| Identifier | Type | Persistence | Sent To |
|---|---|---|---|
userID / deviceId |
32 hex bytes in settings.json | Survives session/token changes | Datadog, GrowthBook, OTEL events |
sessionId |
UUID v4 | Per process lifetime | All 3 telemetry pipelines |
account_uuid |
Anthropic account ID | OAuth-bound | All pipelines (when logged in) |
organization_uuid |
Org ID | OAuth-bound | All pipelines (when logged in) |
rh |
sha256(git_remote)[:16] | Per-request | Datadog only |
| hostname | OS hostname string | On first OAuth login | /api/auth/trusted_devices |
1. CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR (file descriptor)
→ fallback: /home/claude/.claude/remote/.api_key
2. ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN (env)
3. apiKeyHelper shell command (settings.json)
4. macOS Keychain: "Claude Code" service, $USER account
5. ~/.claude/.credentials.json (PLAINTEXT, chmod 0600)
6. CLAUDE_CODE_OAUTH_TOKEN (direct token injection, no refresh)
7. CLAUDE_CODE_SESSION_ACCESS_TOKEN
macOS Keychain (Darwin only):
- Service:
"Claude Code"+ optional sha256(configDir) suffix - Commands:
security find-generic-password,security add-generic-password -U - Cache TTL: 30s in-process
Plaintext (Linux/Windows + macOS fallback):
- Path:
~/.claude/.credentials.json - Permissions:
chmod 0600 - NO encryption — raw JSON, OAuth tokens in clear
- Prints warning:
"Warning: Storing credentials in plaintext."
Credentials JSON structure:
{
"claudeAiOauth": {
"accessToken": "...",
"refreshToken": "...",
"expiresAt": 1234567890000,
"scopes": ["user:inference", "user:profile", "org:create_api_key"],
"subscriptionType": "...",
"rateLimitTier": "..."
}
}- Fires when token expires within 300 seconds (5 min)
- File-locked to prevent parallel refresh races
- 5 retry attempts on lock contention
~/.claude/
├── .credentials.json # OAuth tokens (plaintext, 0600)
├── settings.json # Global settings + persistent userID/deviceId
├── settings.local.json # Local overrides
├── CLAUDE.md # User-level instructions
├── keybindings.json # Keyboard bindings
├── history.jsonl # Prompt history (0600)
├── mcp-needs-auth-cache.json # MCP OAuth state
├── scheduled_tasks.json # Scheduled tasks
├── .update.lock # Auto-updater lock
├── projects/{hash}/ # Per-project data
│ ├── {session}.jsonl # Session transcripts
│ └── memory/ # Project memory files
├── session-memory/ # Session memory
├── sessions/ # Session metadata
├── telemetry/ # OTEL queue buffer (JSONL)
├── debug/{session}.txt # Debug logs
├── startup-perf/ # Startup profiling
├── tasks/ # Task lists
├── teams/ # Team configs
├── plans/ # Plan files
├── file-history/ # File snapshots/backups
├── session-env/ # Shell env snapshots
├── backups/ # File backups
├── worktrees/ # Git worktree state
├── remote/ # Remote mode tokens
├── shell-snapshots/ # Shell env snapshots
├── image-cache/{session}/ # Image upload cache
├── dump-prompts/ # Prompt dumps (debug)
├── ide/ # IDE connection info
├── agents/ # Agent definitions
├── skills/ # Skill bundles
├── commands/ # Slash commands
├── rules/ # Rules files
├── plugins/ # Installed plugins
├── cache/ # Model caps, changelog
└── usage-data/ # Usage stats
| Binary | Size | Type | Purpose |
|---|---|---|---|
vendor/ripgrep/x64-linux/rg |
~5.6MB | Static ELF | File search |
vendor/seccomp/x64/apply-seccomp |
735KB | Static ELF (GNU/Linux 3.2.0, stripped) | Applies seccomp-bpf syscall filters (bash sandbox) |
vendor/audio-capture/x64-linux/audio-capture.node |
481KB | Shared obj (stripped) | Microphone access for voice feature |
node_modules/@img/sharp-linux-x64/sharp-linux-x64.node |
410KB | Shared obj | Image processing (libvips) |
Active when CLAUDE_CODE_BUBBLEWRAP is set or sandbox mode enabled. The apply-seccomp ELF applies a syscall filter to the bash tool subprocess. Currently inactive — dangerouslyDisableSandbox=true in your settings.
.node native addon provides microphone recording. Used only for /voice feature. Override path with AUDIO_CAPTURE_NODE_PATH.
| Package | Version | Notes |
|---|---|---|
| axios | 1.13.6 | HTTP client |
| @azure/msal-common | 15.13.1 | Azure AD auth |
| @azure/msal-node | 3.8.1 | Azure AD auth |
| @grpc/grpc-js | 1.14.0 | OTEL transport |
| google-auth-library | 9.15.1 | GCP Vertex auth |
| gaxios | 6.7.1 | Google HTTP client |
| @aws-sdk/* | 3.936.0 (22 pkgs) | Bedrock auth |
| @img/sharp-linux-x64 | 0.34.5 | Image processing |
| highlight.js | 10.7.3 | Syntax highlighting |
| react | ~18.x | Terminal UI |
| ink | ~5.x | Terminal UI framework |
| zod | ~3.x | Schema validation |
| ws | ~8.x | WebSocket (IDE bridge, CCR) |
// Location: gRPC module (~byte 7183547)
eval("quire".replace(/^/, "re"))(moduleName)
// Reconstructs: require(moduleName)
// Anti-static-analysis technique — loads arbitrary Node modules at runtime
// Triggered for modules not in the static bundle (e.g., long, buffer, fs)// User-configurable MCP server header helper command
spawn(cmd, { shell: true, env: {...process.env, CLAUDE_CODE_MCP_SERVER_NAME, ...} })
// If the helper command string in settings is attacker-controlled → shell injectionwhich ${q}— command name interpolated into shell- Azure CLI:
az account get-access-token - MCP headersHelper (user-configurable)
- Windows editor paths with arguments
Object.getPrototypeOf(q.eval("(async function* () {})").prototype)— AsyncIterator introspectioneval("quire".replace(/^/,"re"))(moduleName)— obfuscated require (see above)
new Worker(codeString, { eval: true })
// Runtime-constructed worker code string (compression worker in gRPC stack)9. HIDDEN / INTERNAL FEATURES
Trigger: /ultrareview command (cloud mode)
Internal key: env_011111111111111111111113 (test/placeholder format)
Fleet config (server-pushed): tengu_review_bughunter_config
fleet_size: 5–20 agents
max_duration_minutes: 10–25
agent_timeout_seconds: ≤600
Env injected into agents:
BUGHUNTER_DRY_RUN=1
BUGHUNTER_PR_NUMBER={pr}
BUGHUNTER_REPOSITORY={owner}/{repo}
Dev override: BUGHUNTER_DEV_BUNDLE_B64 (inject custom bundle)
Internal codename for Opus fast/speculative mode. API: /api/claude_code_penguin_mode. Server kill switch: tengu_penguins_off flag (string = reason message).
Full consent tracking system. Server controls: grace_period, reminder_frequency, domain_excluded. User decision sent as tengu_grove_policy_submitted{state: true/false}.
Social feature. Sends to /api/organizations/{org}/claude_code/buddy_react:
- AI "buddy" name (≤32 chars), personality (≤200 chars), species, rarity, stats
transcript: ≤5000 chars of your conversationreason,recent[],addressedflag
Teleports your repo to Anthropic cloud containers. Sends in registration payload:
git_repo_url,directory,branch(plaintext)machine_name,worker_type
/api/claude_cli/bootstrap returns client_data — arbitrary server KV that gets injected into the client state. Also returns additional_model_options — server can inject extra model choices into the UI.
Server can push policy settings to override local config. Shows security approval dialog. Tracked via tengu_managed_settings_* events.
Full API for org admin elevation: POST /api/oauth/organizations/{org}/admin_requests. Type-parameterized with request_type and status filtering.
CLAUBBIT=1 → skips trust dialog entirely
→ telemetry includes isClaubbit:true
ENABLE_BETA_TRACING_DETAILED=1 + BETA_TRACING_ENDPOINT=<url>
→ Sends detailed per-message traces to custom endpoint
→ Also requires: U7() (non-interactive/SDK mode) OR tengu_trace_lantern gate
→ Content truncated at 60KB; message IDs = sha256(content)[:12]
IS_DEMO=1— hides org/email from UI, disables OAuth creationIS_SANDBOX=1— suppresses custom 529 overloaded error
sO() = hasTrustDialogAccepted(projectPathTree) || QP6() || sY6()
// QP6() = bypassPermissions mode active
// sY6() = some other global override
// Walks up directory tree checking hasTrustDialogAccepted per path
U7() = !v8.isInteractive
// true = running headless/SDK mode (non-interactive)
// affects: metrics export gating, beta tracing enablement
Jq() = "firstParty" | "thirdParty" | ...
// "firstParty" = claude.ai OAuth → enables Datadog telemetry
// API key only = no Datadog
_R7():
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC → "essential-traffic" (strongest)
DISABLE_TELEMETRY → "no-telemetry"
DO_NOT_TRACK=1 → "no-telemetry"
default → "default" (full telemetry)Add to wrapper script or settings.json env block:
# MAXIMUM PRIVACY — kills all non-inference traffic
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
export DISABLE_TELEMETRY=1
export DO_NOT_TRACK=1
export DISABLE_ERROR_REPORTING=1
export OTEL_LOGS_EXPORTER=none
export OTEL_METRICS_EXPORTER=none
export OTEL_TRACES_EXPORTER=none
# Additional
export DISABLE_AUTOUPDATER=1
export CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL=1
export CLAUDE_CODE_DISABLE_POLICY_SKILLS=1Metrics endpoint: Already patched to no-op (patch #19 — Wkz() short-circuits + doExport() returns immediately).
What STILL happens with all opts disabled:
/v1/messagesAPI calls (inference — required)- Token refresh (
/v1/oauth/token) - MCP server connections (local only)
| # | ID | Target |
|---|---|---|
| 01–13 | (existing) | Permissions, trust, AUP, classifiers |
| 14 | js-classifier-failopen | Classifier unavailable → allow |
| 15 | js-aup-refusal | AUP refusal message replacement |
| 16 | js-classifier-all-failopen | All 5 classifier error paths → allow |
| 17 | js-aup-refusal-2 | Second AUP refusal message |
| 18 | js-prompt-injection-sysprompt | Remove "flag prompt injections to user" from system prompt |
| 19 | js-metrics-disable | Wkz() → always return {enabled:false}; doExport() → immediate no-op |
- No certificate pinning — standard Node.js TLS
NODE_EXTRA_CA_CERTS,SSL_CERT_FILE— custom CA bundlesCLAUDE_CODE_CLIENT_CERT+CLAUDE_CODE_CLIENT_KEY— mTLS supportedHTTPS_PROXY/HTTP_PROXY— proxy support (HttpsProxyAgent)ANTHROPIC_UNIX_SOCKET— route API calls through Unix socket- No .netrc reads found
| Service | Provider | Data |
|---|---|---|
| api.anthropic.com | Anthropic | Primary API + all telemetry |
| http-intake.logs.us5.datadoghq.com | Datadog (external, US5) | 42 event types, OS fingerprint, git repo hash |
| cdn.growthbook.io | GrowthBook (external) | Feature flag evaluation with email/org/device IDs |
| storage.googleapis.com | Google Cloud | Binary auto-updates |
| downloads.claude.ai | Anthropic CDN | Plugin downloads |
| login.microsoftonline.com | Microsoft Azure | Azure AD auth (MSAL) |
| AWS Bedrock endpoints | AWS | If Bedrock provider used |
| http://169.254.169.254 | IMDS | Azure/AWS cloud credential detection |
Full report: /tmp/claude-code-re-FINAL.md