Feature Flags (Build-Time)

Description

Claude Code uses build-time feature flags to gate entire subsystems, tools, commands, and code paths. The mechanism centers on a feature(name) function imported from the bun:bundle module. In production Bun builds, feature() calls resolve to compile-time boolean constants, and Bun's bundler performs dead-code elimination (DCE): code inside inactive if (feature('FLAG')) branches is stripped entirely from the output, including any string literals, require() calls, and GrowthBook flag references those branches contain. This prevents Anthropic-internal feature names from leaking into external builds.

In development, the bun:bundle import is intercepted by a Bun preload plugin (scripts/bun-plugin-shims.ts) that resolves it to src/shims/bun-bundle.ts. This shim maintains a FEATURE_FLAGS map where each flag reads from an environment variable (e.g., CLAUDE_CODE_PROACTIVE) via the envBool() helper, defaulting to false. For the esbuild-based production build (scripts/build-bundle.ts), bun:bundle is aliased to the same shim file.

The codebase contains approximately 91 distinct feature flags referenced via feature() calls. Flags gate behavior at multiple levels: CLI entrypoint routing, slash-command registration, tool availability, system prompt composition, keybinding registration, UI component rendering, and module-level conditional require() imports.

Two-layer gating pattern

Many features use a two-layer gating pattern: a build-time feature() check (eliminates dead code) wrapping a runtime GrowthBook/Statsig check (controls rollout and kill-switch). The code comments refer to a "positive ternary pattern" where the feature check is written as return feature('X') ? runtimeCheck() : false rather than if (!feature('X')) return; ..., because the negative pattern fails to eliminate inline string literals from external builds.

Flag categories

Always-on subsystem flags (registered in the shim with env-var fallbacks):

Flag Env var What it gates
PROACTIVE CLAUDE_CODE_PROACTIVE Proactive agent mode: SleepTool, proactive prompts, auto-mode notifications
KAIROS CLAUDE_CODE_KAIROS Always-on assistant mode: daily-log prompts, session resume, assistant module, BriefTool, SendUserFileTool, PushNotificationTool, channel notifications
KAIROS_BRIEF CLAUDE_CODE_KAIROS_BRIEF Brief-mode subset of Kairos: BriefTool visibility, brief-only rendering, keybindings
KAIROS_GITHUB_WEBHOOKS CLAUDE_CODE_KAIROS_GITHUB_WEBHOOKS GitHub PR subscription via SubscribePRTool
BRIDGE_MODE CLAUDE_CODE_BRIDGE_MODE IDE bridge / Remote Control: bridge commands, REPL bridge, entitlement checks (requires claude.ai subscription + GrowthBook gate tengu_ccr_bridge)
DAEMON CLAUDE_CODE_DAEMON Background daemon worker: --daemon-worker CLI path, remote-control server command
VOICE_MODE CLAUDE_CODE_VOICE_MODE Voice I/O: voice commands, push-to-talk keybinding, STT streaming, VoiceIndicator, voice integration hooks (requires Anthropic OAuth)
AGENT_TRIGGERS CLAUDE_CODE_AGENT_TRIGGERS Scheduled/triggered actions: CronCreateTool, CronDeleteTool, CronListTool, cron scheduler, cron jitter config
MONITOR_TOOL CLAUDE_CODE_MONITOR_TOOL MonitorTool for streaming background process events
COORDINATOR_MODE CLAUDE_CODE_COORDINATOR_MODE Multi-agent coordinator: coordinator module, in-process teammate tools, session mode matching (also requires CLAUDE_CODE_COORDINATOR_MODE env var at runtime)
ABLATION_BASELINE hardcoded false Harness-science ablation: sets env vars to disable thinking, compaction, auto-memory, background tasks. Always off in external builds.
DUMP_SYSTEM_PROMPT CLAUDE_CODE_DUMP_SYSTEM_PROMPT --dump-system-prompt CLI flag for prompt sensitivity evals
BG_SESSIONS CLAUDE_CODE_BG_SESSIONS Background sessions: ps, logs, attach, kill, --bg/--background CLI commands
HISTORY_SNIP CLAUDE_CODE_HISTORY_SNIP SnipTool, /force-snip command, history snipping in message rendering
WORKFLOW_SCRIPTS CLAUDE_CODE_WORKFLOW_SCRIPTS WorkflowTool, /workflows command, bundled workflow initialization
CCR_REMOTE_SETUP CLAUDE_CODE_CCR_REMOTE_SETUP /web remote-setup command
EXPERIMENTAL_SKILL_SEARCH CLAUDE_CODE_EXPERIMENTAL_SKILL_SEARCH Skill search in system prompt, skill index cache clearing, attachment skill search
ULTRAPLAN CLAUDE_CODE_ULTRAPLAN /ultraplan command
TORCH CLAUDE_CODE_TORCH /torch command
UDS_INBOX CLAUDE_CODE_UDS_INBOX Unix domain socket inbox, ListPeersTool, /peers command
FORK_SUBAGENT CLAUDE_CODE_FORK_SUBAGENT /fork command (replaces fork as alias for /branch)
BUDDY CLAUDE_CODE_BUDDY CompanionSprite UI, buddy notifications, buddy prompt injection
MCP_SKILLS CLAUDE_CODE_MCP_SKILLS MCP skill fetching, skill-based resource discovery
REACTIVE_COMPACT CLAUDE_CODE_REACTIVE_COMPACT Reactive compaction in auto-compact and /compact

Additional flags found only via feature() calls in source (not in the shim -- likely defined in internal Bun build configs or added after the shim snapshot):

AGENT_MEMORY_SNAPSHOT, AGENT_TRIGGERS_REMOTE, ALLOW_TEST_VERSIONS, ANTI_DISTILLATION_CC, AUTO_THEME, AWAY_SUMMARY, BASH_CLASSIFIER, BREAK_CACHE_COMMAND, BUILDING_CLAUDE_APPS, BUILTIN_EXPLORE_PLAN_AGENTS, BYOC_ENVIRONMENT_RUNNER, CACHED_MICROCOMPACT, CCR_AUTO_CONNECT, CCR_MIRROR, CHICAGO_MCP, COMMIT_ATTRIBUTION, COMPACTION_REMINDERS, CONNECTOR_TEXT, CONTEXT_COLLAPSE, COWORKER_TYPE_TELEMETRY, DIRECT_CONNECT, DOWNLOAD_USER_SETTINGS, ENHANCED_TELEMETRY_BETA, EXTRACT_MEMORIES, FILE_PERSISTENCE, HARD_FAIL, HISTORY_PICKER, HOOK_PROMPTS, IS_LIBC_GLIBC, IS_LIBC_MUSL, KAIROS_CHANNELS, KAIROS_DREAM, KAIROS_PUSH_NOTIFICATION, LODESTONE, MCP_RICH_OUTPUT, MEMORY_SHAPE_TELEMETRY, MESSAGE_ACTIONS, NATIVE_CLIENT_ATTESTATION, NATIVE_CLIPBOARD_IMAGE, NEW_INIT, OVERFLOW_TEST_TOOL, PERFETTO_TRACING, POWERSHELL_AUTO_MODE, PROMPT_CACHE_BREAK_DETECTION, QUICK_SEARCH, REVIEW_ARTIFACT, RUN_SKILL_GENERATOR, SELF_HOSTED_RUNNER, SHOT_STATS, SKILL_IMPROVEMENT, SLOW_OPERATION_LOGGING, SSH_REMOTE, STREAMLINED_OUTPUT, TEAMMEM, TEMPLATES, TERMINAL_PANEL, TOKEN_BUDGET, TRANSCRIPT_CLASSIFIER, TREE_SITTER_BASH, TREE_SITTER_BASH_SHADOW, ULTRATHINK, UNATTENDED_RETRY, UPLOAD_USER_SETTINGS, VERIFICATION_AGENT, WEB_BROWSER_TOOL

How flags gate code

Flags control behavior at several architectural layers:

  1. CLI entrypoint routing (src/entrypoints/cli.tsx): Flags like DAEMON, BRIDGE_MODE, BG_SESSIONS, and DUMP_SYSTEM_PROMPT gate entire CLI subcommands before the main application loads.

  2. Slash-command registration (src/commands.ts): Each flag-gated command uses a conditional require() that resolves to null when the flag is off. The command array filters out nulls.

  3. Tool availability (src/tools.ts, src/constants/tools.ts): Tools like MonitorTool, WorkflowTool, SnipTool, ListPeersTool, CronCreateTool, SendUserFileTool, WebBrowserTool, and TerminalCaptureTool are conditionally require()'d and included in tool lists only when their flag is active.

  4. System prompt composition (src/constants/prompts.ts): Prompt sections for proactive behavior, brief mode, and skill search are conditionally included based on flag state.

  5. Keybinding registration (src/keybindings/defaultBindings.ts): Push-to-talk (VOICE_MODE), brief-mode shortcuts (KAIROS/KAIROS_BRIEF), and terminal toggle (TERMINAL_PANEL) are conditionally added.

  6. Module-level conditional require (throughout): The dominant pattern is const Foo = feature('FLAG') ? require('./Foo.js').Foo : null, which ensures the entire module subtree is eliminated by DCE when the flag is off.

  7. UI component rendering (src/components/): Components like CompanionSprite (BUDDY), ChannelsNotice (KAIROS_CHANNELS), WebBrowserPanel (WEB_BROWSER_TOOL), and VoiceIndicator (VOICE_MODE) are conditionally rendered or entirely skipped.

Relationship to process.env.USER_TYPE

A parallel gating mechanism uses process.env.USER_TYPE (set to "external" via define in the build config). This gates Anthropic-internal ("ant") tools and packages (e.g., REPLTool, SuggestBackgroundPRTool, @ant/* packages) and is handled by esbuild's define replacements rather than the bun:bundle feature system. Both mechanisms achieve DCE but serve different purposes: USER_TYPE separates internal vs. external builds, while feature flags control incremental feature rollout.

Key claims

Relations

Sources