source dump of claude code
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 183 lines 6.2 kB view raw
1import memoize from 'lodash-es/memoize.js' 2import { homedir } from 'os' 3import { join } from 'path' 4 5// Memoized: 150+ callers, many on hot paths. Keyed off CLAUDE_CONFIG_DIR so 6// tests that change the env var get a fresh value without explicit cache.clear. 7export const getClaudeConfigHomeDir = memoize( 8 (): string => { 9 return ( 10 process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), '.claude') 11 ).normalize('NFC') 12 }, 13 () => process.env.CLAUDE_CONFIG_DIR, 14) 15 16export function getTeamsDir(): string { 17 return join(getClaudeConfigHomeDir(), 'teams') 18} 19 20/** 21 * Check if NODE_OPTIONS contains a specific flag. 22 * Splits on whitespace and checks for exact match to avoid false positives. 23 */ 24export function hasNodeOption(flag: string): boolean { 25 const nodeOptions = process.env.NODE_OPTIONS 26 if (!nodeOptions) { 27 return false 28 } 29 return nodeOptions.split(/\s+/).includes(flag) 30} 31 32export function isEnvTruthy(envVar: string | boolean | undefined): boolean { 33 if (!envVar) return false 34 if (typeof envVar === 'boolean') return envVar 35 const normalizedValue = envVar.toLowerCase().trim() 36 return ['1', 'true', 'yes', 'on'].includes(normalizedValue) 37} 38 39export function isEnvDefinedFalsy( 40 envVar: string | boolean | undefined, 41): boolean { 42 if (envVar === undefined) return false 43 if (typeof envVar === 'boolean') return !envVar 44 if (!envVar) return false 45 const normalizedValue = envVar.toLowerCase().trim() 46 return ['0', 'false', 'no', 'off'].includes(normalizedValue) 47} 48 49/** 50 * --bare / CLAUDE_CODE_SIMPLE — skip hooks, LSP, plugin sync, skill dir-walk, 51 * attribution, background prefetches, and ALL keychain/credential reads. 52 * Auth is strictly ANTHROPIC_API_KEY env or apiKeyHelper from --settings. 53 * Explicit CLI flags (--plugin-dir, --add-dir, --mcp-config) still honored. 54 * ~30 gates across the codebase. 55 * 56 * Checks argv directly (in addition to the env var) because several gates 57 * run before main.tsx's action handler sets CLAUDE_CODE_SIMPLE=1 from --bare 58 * — notably startKeychainPrefetch() at main.tsx top-level. 59 */ 60export function isBareMode(): boolean { 61 return ( 62 isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE) || 63 process.argv.includes('--bare') 64 ) 65} 66 67/** 68 * Parses an array of environment variable strings into a key-value object 69 * @param envVars Array of strings in KEY=VALUE format 70 * @returns Object with key-value pairs 71 */ 72export function parseEnvVars( 73 rawEnvArgs: string[] | undefined, 74): Record<string, string> { 75 const parsedEnv: Record<string, string> = {} 76 77 // Parse individual env vars 78 if (rawEnvArgs) { 79 for (const envStr of rawEnvArgs) { 80 const [key, ...valueParts] = envStr.split('=') 81 if (!key || valueParts.length === 0) { 82 throw new Error( 83 `Invalid environment variable format: ${envStr}, environment variables should be added as: -e KEY1=value1 -e KEY2=value2`, 84 ) 85 } 86 parsedEnv[key] = valueParts.join('=') 87 } 88 } 89 return parsedEnv 90} 91 92/** 93 * Get the AWS region with fallback to default 94 * Matches the Anthropic Bedrock SDK's region behavior 95 */ 96export function getAWSRegion(): string { 97 return process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-1' 98} 99 100/** 101 * Get the default Vertex AI region 102 */ 103export function getDefaultVertexRegion(): string { 104 return process.env.CLOUD_ML_REGION || 'us-east5' 105} 106 107/** 108 * Check if bash commands should maintain project working directory (reset to original after each command) 109 * @returns true if CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR is set to a truthy value 110 */ 111export function shouldMaintainProjectWorkingDir(): boolean { 112 return isEnvTruthy(process.env.CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR) 113} 114 115/** 116 * Check if running on Homespace (ant-internal cloud environment) 117 */ 118export function isRunningOnHomespace(): boolean { 119 return ( 120 process.env.USER_TYPE === 'ant' && 121 isEnvTruthy(process.env.COO_RUNNING_ON_HOMESPACE) 122 ) 123} 124 125/** 126 * Conservative check for whether Claude Code is running inside a protected 127 * (privileged or ASL3+) COO namespace or cluster. 128 * 129 * Conservative means: when signals are ambiguous, assume protected. We would 130 * rather over-report protected usage than miss it. Unprotected environments 131 * are homespace, namespaces on the open allowlist, and no k8s/COO signals 132 * at all (laptop/local dev). 133 * 134 * Used for telemetry to measure auto-mode usage in sensitive environments. 135 */ 136export function isInProtectedNamespace(): boolean { 137 // USER_TYPE is build-time --define'd; in external builds this block is 138 // DCE'd so the require() and namespace allowlist never appear in the bundle. 139 if (process.env.USER_TYPE === 'ant') { 140 /* eslint-disable @typescript-eslint/no-require-imports */ 141 return ( 142 require('./protectedNamespace.js') as typeof import('./protectedNamespace.js') 143 ).checkProtectedNamespace() 144 /* eslint-enable @typescript-eslint/no-require-imports */ 145 } 146 return false 147} 148 149// @[MODEL LAUNCH]: Add a Vertex region override env var for the new model. 150/** 151 * Model prefix → env var for Vertex region overrides. 152 * Order matters: more specific prefixes must come before less specific ones 153 * (e.g., 'claude-opus-4-1' before 'claude-opus-4'). 154 */ 155const VERTEX_REGION_OVERRIDES: ReadonlyArray<[string, string]> = [ 156 ['claude-haiku-4-5', 'VERTEX_REGION_CLAUDE_HAIKU_4_5'], 157 ['claude-3-5-haiku', 'VERTEX_REGION_CLAUDE_3_5_HAIKU'], 158 ['claude-3-5-sonnet', 'VERTEX_REGION_CLAUDE_3_5_SONNET'], 159 ['claude-3-7-sonnet', 'VERTEX_REGION_CLAUDE_3_7_SONNET'], 160 ['claude-opus-4-1', 'VERTEX_REGION_CLAUDE_4_1_OPUS'], 161 ['claude-opus-4', 'VERTEX_REGION_CLAUDE_4_0_OPUS'], 162 ['claude-sonnet-4-6', 'VERTEX_REGION_CLAUDE_4_6_SONNET'], 163 ['claude-sonnet-4-5', 'VERTEX_REGION_CLAUDE_4_5_SONNET'], 164 ['claude-sonnet-4', 'VERTEX_REGION_CLAUDE_4_0_SONNET'], 165] 166 167/** 168 * Get the Vertex AI region for a specific model. 169 * Different models may be available in different regions. 170 */ 171export function getVertexRegionForModel( 172 model: string | undefined, 173): string | undefined { 174 if (model) { 175 const match = VERTEX_REGION_OVERRIDES.find(([prefix]) => 176 model.startsWith(prefix), 177 ) 178 if (match) { 179 return process.env[match[1]] || getDefaultVertexRegion() 180 } 181 } 182 return getDefaultVertexRegion() 183}