Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
5.2 kB · 146 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147/** * Shared utilities for spawning teammates across different backends. */
import { getChromeFlagOverride, getFlagSettingsPath, getInlinePlugins, getMainLoopModelOverride, getSessionBypassPermissionsMode,} from '../../bootstrap/state.js'import { quote } from '../bash/shellQuote.js'import { isInBundledMode } from '../bundledMode.js'import type { PermissionMode } from '../permissions/PermissionMode.js'import { getTeammateModeFromSnapshot } from './backends/teammateModeSnapshot.js'import { TEAMMATE_COMMAND_ENV_VAR } from './constants.js'
/** * Gets the command to use for spawning teammate processes. * Uses TEAMMATE_COMMAND_ENV_VAR if set, otherwise falls back to the * current process executable path. */export function getTeammateCommand(): string { if (process.env[TEAMMATE_COMMAND_ENV_VAR]) { return process.env[TEAMMATE_COMMAND_ENV_VAR] } return isInBundledMode() ? process.execPath : process.argv[1]!}
/** * Builds CLI flags to propagate from the current session to spawned teammates. * This ensures teammates inherit important settings like permission mode, * model selection, and plugin configuration from their parent. * * @param options.planModeRequired - If true, don't inherit bypass permissions (plan mode takes precedence) * @param options.permissionMode - Permission mode to propagate */export function buildInheritedCliFlags(options?: { planModeRequired?: boolean permissionMode?: PermissionMode}): string { const flags: string[] = [] const { planModeRequired, permissionMode } = options || {}
// Propagate permission mode to teammates, but NOT if plan mode is required // Plan mode takes precedence over bypass permissions for safety if (planModeRequired) { // Don't inherit bypass permissions when plan mode is required } else if ( permissionMode === 'bypassPermissions' || getSessionBypassPermissionsMode() ) { flags.push('--dangerously-skip-permissions') } else if (permissionMode === 'acceptEdits') { flags.push('--permission-mode acceptEdits') }
// Propagate --model if explicitly set via CLI const modelOverride = getMainLoopModelOverride() if (modelOverride) { flags.push(`--model ${quote([modelOverride])}`) }
// Propagate --settings if set via CLI const settingsPath = getFlagSettingsPath() if (settingsPath) { flags.push(`--settings ${quote([settingsPath])}`) }
// Propagate --plugin-dir for each inline plugin const inlinePlugins = getInlinePlugins() for (const pluginDir of inlinePlugins) { flags.push(`--plugin-dir ${quote([pluginDir])}`) }
// Propagate --teammate-mode so tmux teammates use the same mode as leader const sessionMode = getTeammateModeFromSnapshot() flags.push(`--teammate-mode ${sessionMode}`)
// Propagate --chrome / --no-chrome if explicitly set on the CLI const chromeFlagOverride = getChromeFlagOverride() if (chromeFlagOverride === true) { flags.push('--chrome') } else if (chromeFlagOverride === false) { flags.push('--no-chrome') }
return flags.join(' ')}
/** * Environment variables that must be explicitly forwarded to tmux-spawned * teammates. Tmux may start a new login shell that doesn't inherit the * parent's env, so we forward any that are set in the current process. */const TEAMMATE_ENV_VARS = [ // API provider selection — without these, teammates default to firstParty // and send requests to the wrong endpoint (GitHub issue #23561) 'CLAUDE_CODE_USE_BEDROCK', 'CLAUDE_CODE_USE_VERTEX', 'CLAUDE_CODE_USE_FOUNDRY', // Custom API endpoint 'ANTHROPIC_BASE_URL', // Config directory override 'CLAUDE_CONFIG_DIR', // CCR marker — teammates need this for CCR-aware code paths. Auth finds // its own way via /home/claude/.claude/remote/.oauth_token regardless; // the FD env var wouldn't help (pipe FDs don't cross tmux). 'CLAUDE_CODE_REMOTE', // Auto-memory gate (memdir/paths.ts) checks REMOTE && !MEMORY_DIR to // disable memory on ephemeral CCR filesystems. Forwarding REMOTE alone // would flip teammates to memory-off when the parent has it on. 'CLAUDE_CODE_REMOTE_MEMORY_DIR', // Upstream proxy — the parent's MITM relay is reachable from teammates // (same container network). Forward the proxy vars so teammates route // customer-configured upstream traffic through the relay for credential // injection. Without these, teammates bypass the proxy entirely. 'HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy', 'NO_PROXY', 'no_proxy', 'SSL_CERT_FILE', 'NODE_EXTRA_CA_CERTS', 'REQUESTS_CA_BUNDLE', 'CURL_CA_BUNDLE',] as const
/** * Builds the `env KEY=VALUE ...` string for teammate spawn commands. * Always includes CLAUDECODE=1 and CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, * plus any provider/config env vars that are set in the current process. */export function buildInheritedEnvVars(): string { const envVars = ['CLAUDECODE=1', 'CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1']
for (const key of TEAMMATE_ENV_VARS) { const value = process.env[key] if (value !== undefined && value !== '') { envVars.push(`${key}=${quote([value])}`) } }
return envVars.join(' ')}