mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 12:55:51 +00:00
fix: 修复 USER_TYPE=ant 时 TUI 无法启动的问题
反编译版本中 global.d.ts 声明的全局函数运行时未定义, 通过显式 import、stub 组件和全局 polyfill 修复。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
#!/usr/bin/env bun
|
||||
import { feature } from 'bun:bundle'
|
||||
import { feature } from 'bun:bundle';
|
||||
|
||||
// Bugfix for corepack auto-pinning, which adds yarnpkg to peoples' package.jsons
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects
|
||||
process.env.COREPACK_ENABLE_AUTO_PIN = "0";
|
||||
process.env.COREPACK_ENABLE_AUTO_PIN = '0';
|
||||
|
||||
// Set max heap size for child processes in CCR environments (containers have 16GB)
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level, custom-rules/safe-env-boolean-check
|
||||
if (process.env.CLAUDE_CODE_REMOTE === "true") {
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
const existing = process.env.NODE_OPTIONS || "";
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
process.env.NODE_OPTIONS = existing
|
||||
? `${existing} --max-old-space-size=8192`
|
||||
: "--max-old-space-size=8192";
|
||||
if (process.env.CLAUDE_CODE_REMOTE === 'true') {
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
const existing = process.env.NODE_OPTIONS || '';
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
process.env.NODE_OPTIONS = existing ? `${existing} --max-old-space-size=8192` : '--max-old-space-size=8192';
|
||||
}
|
||||
|
||||
// Harness-science L0 ablation baseline. Inlined here (not init.ts) because
|
||||
@@ -21,19 +19,19 @@ if (process.env.CLAUDE_CODE_REMOTE === "true") {
|
||||
// module-level consts at import time — init() runs too late. feature() gate
|
||||
// DCEs this entire block from external builds.
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
if (feature("ABLATION_BASELINE") && process.env.CLAUDE_CODE_ABLATION_BASELINE) {
|
||||
for (const k of [
|
||||
"CLAUDE_CODE_SIMPLE",
|
||||
"CLAUDE_CODE_DISABLE_THINKING",
|
||||
"DISABLE_INTERLEAVED_THINKING",
|
||||
"DISABLE_COMPACT",
|
||||
"DISABLE_AUTO_COMPACT",
|
||||
"CLAUDE_CODE_DISABLE_AUTO_MEMORY",
|
||||
"CLAUDE_CODE_DISABLE_BACKGROUND_TASKS",
|
||||
]) {
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
process.env[k] ??= "1";
|
||||
}
|
||||
if (feature('ABLATION_BASELINE') && process.env.CLAUDE_CODE_ABLATION_BASELINE) {
|
||||
for (const k of [
|
||||
'CLAUDE_CODE_SIMPLE',
|
||||
'CLAUDE_CODE_DISABLE_THINKING',
|
||||
'DISABLE_INTERLEAVED_THINKING',
|
||||
'DISABLE_COMPACT',
|
||||
'DISABLE_AUTO_COMPACT',
|
||||
'CLAUDE_CODE_DISABLE_AUTO_MEMORY',
|
||||
'CLAUDE_CODE_DISABLE_BACKGROUND_TASKS',
|
||||
]) {
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects, custom-rules/no-process-env-top-level
|
||||
process.env[k] ??= '1';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,262 +40,231 @@ if (feature("ABLATION_BASELINE") && process.env.CLAUDE_CODE_ABLATION_BASELINE) {
|
||||
* Fast-path for --version has zero imports beyond this file.
|
||||
*/
|
||||
async function main(): Promise<void> {
|
||||
const args = process.argv.slice(2);
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
// Fast-path for --version/-v: zero module loading needed
|
||||
if (
|
||||
args.length === 1 &&
|
||||
(args[0] === "--version" || args[0] === "-v" || args[0] === "-V")
|
||||
) {
|
||||
// MACRO.VERSION is inlined at build time
|
||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||
console.log(`${MACRO.VERSION} (Claude Code)`);
|
||||
// Fast-path for --version/-v: zero module loading needed
|
||||
if (args.length === 1 && (args[0] === '--version' || args[0] === '-v' || args[0] === '-V')) {
|
||||
// MACRO.VERSION is inlined at build time
|
||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||
console.log(`${MACRO.VERSION} (Claude Code)`);
|
||||
return;
|
||||
}
|
||||
|
||||
// For all other paths, load the startup profiler
|
||||
const { profileCheckpoint } = await import('../utils/startupProfiler.js');
|
||||
profileCheckpoint('cli_entry');
|
||||
|
||||
// Fast-path for --dump-system-prompt: output the rendered system prompt and exit.
|
||||
// Used by prompt sensitivity evals to extract the system prompt at a specific commit.
|
||||
// Ant-only: eliminated from external builds via feature flag.
|
||||
if (feature('DUMP_SYSTEM_PROMPT') && args[0] === '--dump-system-prompt') {
|
||||
profileCheckpoint('cli_dump_system_prompt_path');
|
||||
const { enableConfigs } = await import('../utils/config.js');
|
||||
enableConfigs();
|
||||
const { getMainLoopModel } = await import('../utils/model/model.js');
|
||||
const modelIdx = args.indexOf('--model');
|
||||
const model = (modelIdx !== -1 && args[modelIdx + 1]) || getMainLoopModel();
|
||||
const { getSystemPrompt } = await import('../constants/prompts.js');
|
||||
const prompt = await getSystemPrompt([], model);
|
||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||
console.log(prompt.join('\n'));
|
||||
return;
|
||||
}
|
||||
if (process.argv[2] === '--claude-in-chrome-mcp') {
|
||||
profileCheckpoint('cli_claude_in_chrome_mcp_path');
|
||||
const { runClaudeInChromeMcpServer } = await import('../utils/claudeInChrome/mcpServer.js');
|
||||
await runClaudeInChromeMcpServer();
|
||||
return;
|
||||
} else if (process.argv[2] === '--chrome-native-host') {
|
||||
profileCheckpoint('cli_chrome_native_host_path');
|
||||
const { runChromeNativeHost } = await import('../utils/claudeInChrome/chromeNativeHost.js');
|
||||
await runChromeNativeHost();
|
||||
return;
|
||||
} else if (feature('CHICAGO_MCP') && process.argv[2] === '--computer-use-mcp') {
|
||||
profileCheckpoint('cli_computer_use_mcp_path');
|
||||
const { runComputerUseMcpServer } = await import('../utils/computerUse/mcpServer.js');
|
||||
await runComputerUseMcpServer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `--daemon-worker=<kind>` (internal — supervisor spawns this).
|
||||
// Must come before the daemon subcommand check: spawned per-worker, so
|
||||
// perf-sensitive. No enableConfigs(), no analytics sinks at this layer —
|
||||
// workers are lean. If a worker kind needs configs/auth (assistant will),
|
||||
// it calls them inside its run() fn.
|
||||
if (feature('DAEMON') && args[0] === '--daemon-worker') {
|
||||
const { runDaemonWorker } = await import('../daemon/workerRegistry.js');
|
||||
await runDaemonWorker(args[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude remote-control` (also accepts legacy `claude remote` / `claude sync` / `claude bridge`):
|
||||
// serve local machine as bridge environment.
|
||||
// feature() must stay inline for build-time dead code elimination;
|
||||
// isBridgeEnabled() checks the runtime GrowthBook gate.
|
||||
if (
|
||||
feature('BRIDGE_MODE') &&
|
||||
(args[0] === 'remote-control' ||
|
||||
args[0] === 'rc' ||
|
||||
args[0] === 'remote' ||
|
||||
args[0] === 'sync' ||
|
||||
args[0] === 'bridge')
|
||||
) {
|
||||
profileCheckpoint('cli_bridge_path');
|
||||
const { enableConfigs } = await import('../utils/config.js');
|
||||
enableConfigs();
|
||||
const { getBridgeDisabledReason, checkBridgeMinVersion } = await import('../bridge/bridgeEnabled.js');
|
||||
const { BRIDGE_LOGIN_ERROR } = await import('../bridge/types.js');
|
||||
const { bridgeMain } = await import('../bridge/bridgeMain.js');
|
||||
const { exitWithError } = await import('../utils/process.js');
|
||||
|
||||
// Auth check must come before the GrowthBook gate check — without auth,
|
||||
// GrowthBook has no user context and would return a stale/default false.
|
||||
// getBridgeDisabledReason awaits GB init, so the returned value is fresh
|
||||
// (not the stale disk cache), but init still needs auth headers to work.
|
||||
const { getClaudeAIOAuthTokens } = await import('../utils/auth.js');
|
||||
if (!getClaudeAIOAuthTokens()?.accessToken) {
|
||||
exitWithError(BRIDGE_LOGIN_ERROR);
|
||||
}
|
||||
const disabledReason = await getBridgeDisabledReason();
|
||||
if (disabledReason) {
|
||||
exitWithError(`Error: ${disabledReason}`);
|
||||
}
|
||||
const versionError = checkBridgeMinVersion();
|
||||
if (versionError) {
|
||||
exitWithError(versionError);
|
||||
}
|
||||
|
||||
// Bridge is a remote control feature - check policy limits
|
||||
const { waitForPolicyLimitsToLoad, isPolicyAllowed } = await import('../services/policyLimits/index.js');
|
||||
await waitForPolicyLimitsToLoad();
|
||||
if (!isPolicyAllowed('allow_remote_control')) {
|
||||
exitWithError("Error: Remote Control is disabled by your organization's policy.");
|
||||
}
|
||||
await bridgeMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude daemon [subcommand]`: long-running supervisor.
|
||||
if (feature('DAEMON') && args[0] === 'daemon') {
|
||||
profileCheckpoint('cli_daemon_path');
|
||||
const { enableConfigs } = await import('../utils/config.js');
|
||||
enableConfigs();
|
||||
const { initSinks } = await import('../utils/sinks.js');
|
||||
initSinks();
|
||||
const { daemonMain } = await import('../daemon/main.js');
|
||||
await daemonMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude ps|logs|attach|kill` and `--bg`/`--background`.
|
||||
// Session management against the ~/.claude/sessions/ registry. Flag
|
||||
// literals are inlined so bg.js only loads when actually dispatching.
|
||||
if (
|
||||
feature('BG_SESSIONS') &&
|
||||
(args[0] === 'ps' ||
|
||||
args[0] === 'logs' ||
|
||||
args[0] === 'attach' ||
|
||||
args[0] === 'kill' ||
|
||||
args.includes('--bg') ||
|
||||
args.includes('--background'))
|
||||
) {
|
||||
profileCheckpoint('cli_bg_path');
|
||||
const { enableConfigs } = await import('../utils/config.js');
|
||||
enableConfigs();
|
||||
const bg = await import('../cli/bg.js');
|
||||
switch (args[0]) {
|
||||
case 'ps':
|
||||
await bg.psHandler(args.slice(1));
|
||||
break;
|
||||
case 'logs':
|
||||
await bg.logsHandler(args[1]);
|
||||
break;
|
||||
case 'attach':
|
||||
await bg.attachHandler(args[1]);
|
||||
break;
|
||||
case 'kill':
|
||||
await bg.killHandler(args[1]);
|
||||
break;
|
||||
default:
|
||||
await bg.handleBgFlag(args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for template job commands.
|
||||
if (feature('TEMPLATES') && (args[0] === 'new' || args[0] === 'list' || args[0] === 'reply')) {
|
||||
profileCheckpoint('cli_templates_path');
|
||||
const { templatesMain } = await import('../cli/handlers/templateJobs.js');
|
||||
await templatesMain(args);
|
||||
// process.exit (not return) — mountFleetView's Ink TUI can leave event
|
||||
// loop handles that prevent natural exit.
|
||||
// eslint-disable-next-line custom-rules/no-process-exit
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Fast-path for `claude environment-runner`: headless BYOC runner.
|
||||
// feature() must stay inline for build-time dead code elimination.
|
||||
if (feature('BYOC_ENVIRONMENT_RUNNER') && args[0] === 'environment-runner') {
|
||||
profileCheckpoint('cli_environment_runner_path');
|
||||
const { environmentRunnerMain } = await import('../environment-runner/main.js');
|
||||
await environmentRunnerMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude self-hosted-runner`: headless self-hosted-runner
|
||||
// targeting the SelfHostedRunnerWorkerService API (register + poll; poll IS
|
||||
// heartbeat). feature() must stay inline for build-time dead code elimination.
|
||||
if (feature('SELF_HOSTED_RUNNER') && args[0] === 'self-hosted-runner') {
|
||||
profileCheckpoint('cli_self_hosted_runner_path');
|
||||
const { selfHostedRunnerMain } = await import('../self-hosted-runner/main.js');
|
||||
await selfHostedRunnerMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for --worktree --tmux: exec into tmux before loading full CLI
|
||||
const hasTmuxFlag = args.includes('--tmux') || args.includes('--tmux=classic');
|
||||
if (
|
||||
hasTmuxFlag &&
|
||||
(args.includes('-w') || args.includes('--worktree') || args.some(a => a.startsWith('--worktree=')))
|
||||
) {
|
||||
profileCheckpoint('cli_tmux_worktree_fast_path');
|
||||
const { enableConfigs } = await import('../utils/config.js');
|
||||
enableConfigs();
|
||||
const { isWorktreeModeEnabled } = await import('../utils/worktreeModeEnabled.js');
|
||||
if (isWorktreeModeEnabled()) {
|
||||
const { execIntoTmuxWorktree } = await import('../utils/worktree.js');
|
||||
const result = await execIntoTmuxWorktree(args);
|
||||
if (result.handled) {
|
||||
return;
|
||||
}
|
||||
// If not handled (e.g., error), fall through to normal CLI
|
||||
if (result.error) {
|
||||
const { exitWithError } = await import('../utils/process.js');
|
||||
exitWithError(result.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For all other paths, load the startup profiler
|
||||
const { profileCheckpoint } = await import("../utils/startupProfiler.js");
|
||||
profileCheckpoint("cli_entry");
|
||||
// Redirect common update flag mistakes to the update subcommand
|
||||
if (args.length === 1 && (args[0] === '--update' || args[0] === '--upgrade')) {
|
||||
process.argv = [process.argv[0]!, process.argv[1]!, 'update'];
|
||||
}
|
||||
|
||||
// Fast-path for --dump-system-prompt: output the rendered system prompt and exit.
|
||||
// Used by prompt sensitivity evals to extract the system prompt at a specific commit.
|
||||
// Ant-only: eliminated from external builds via feature flag.
|
||||
if (feature("DUMP_SYSTEM_PROMPT") && args[0] === "--dump-system-prompt") {
|
||||
profileCheckpoint("cli_dump_system_prompt_path");
|
||||
const { enableConfigs } = await import("../utils/config.js");
|
||||
enableConfigs();
|
||||
const { getMainLoopModel } = await import("../utils/model/model.js");
|
||||
const modelIdx = args.indexOf("--model");
|
||||
const model =
|
||||
(modelIdx !== -1 && args[modelIdx + 1]) || getMainLoopModel();
|
||||
const { getSystemPrompt } = await import("../constants/prompts.js");
|
||||
const prompt = await getSystemPrompt([], model);
|
||||
// biome-ignore lint/suspicious/noConsole:: intentional console output
|
||||
console.log(prompt.join("\n"));
|
||||
return;
|
||||
}
|
||||
if (process.argv[2] === "--claude-in-chrome-mcp") {
|
||||
profileCheckpoint("cli_claude_in_chrome_mcp_path");
|
||||
const { runClaudeInChromeMcpServer } =
|
||||
await import("../utils/claudeInChrome/mcpServer.js");
|
||||
await runClaudeInChromeMcpServer();
|
||||
return;
|
||||
} else if (process.argv[2] === "--chrome-native-host") {
|
||||
profileCheckpoint("cli_chrome_native_host_path");
|
||||
const { runChromeNativeHost } =
|
||||
await import("../utils/claudeInChrome/chromeNativeHost.js");
|
||||
await runChromeNativeHost();
|
||||
return;
|
||||
} else if (
|
||||
feature("CHICAGO_MCP") &&
|
||||
process.argv[2] === "--computer-use-mcp"
|
||||
) {
|
||||
profileCheckpoint("cli_computer_use_mcp_path");
|
||||
const { runComputerUseMcpServer } =
|
||||
await import("../utils/computerUse/mcpServer.js");
|
||||
await runComputerUseMcpServer();
|
||||
return;
|
||||
}
|
||||
// --bare: set SIMPLE early so gates fire during module eval / commander
|
||||
// option building (not just inside the action handler).
|
||||
if (args.includes('--bare')) {
|
||||
process.env.CLAUDE_CODE_SIMPLE = '1';
|
||||
}
|
||||
|
||||
// Fast-path for `--daemon-worker=<kind>` (internal — supervisor spawns this).
|
||||
// Must come before the daemon subcommand check: spawned per-worker, so
|
||||
// perf-sensitive. No enableConfigs(), no analytics sinks at this layer —
|
||||
// workers are lean. If a worker kind needs configs/auth (assistant will),
|
||||
// it calls them inside its run() fn.
|
||||
if (feature("DAEMON") && args[0] === "--daemon-worker") {
|
||||
const { runDaemonWorker } = await import("../daemon/workerRegistry.js");
|
||||
await runDaemonWorker(args[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude remote-control` (also accepts legacy `claude remote` / `claude sync` / `claude bridge`):
|
||||
// serve local machine as bridge environment.
|
||||
// feature() must stay inline for build-time dead code elimination;
|
||||
// isBridgeEnabled() checks the runtime GrowthBook gate.
|
||||
if (
|
||||
feature("BRIDGE_MODE") &&
|
||||
(args[0] === "remote-control" ||
|
||||
args[0] === "rc" ||
|
||||
args[0] === "remote" ||
|
||||
args[0] === "sync" ||
|
||||
args[0] === "bridge")
|
||||
) {
|
||||
profileCheckpoint("cli_bridge_path");
|
||||
const { enableConfigs } = await import("../utils/config.js");
|
||||
enableConfigs();
|
||||
const { getBridgeDisabledReason, checkBridgeMinVersion } =
|
||||
await import("../bridge/bridgeEnabled.js");
|
||||
const { BRIDGE_LOGIN_ERROR } = await import("../bridge/types.js");
|
||||
const { bridgeMain } = await import("../bridge/bridgeMain.js");
|
||||
const { exitWithError } = await import("../utils/process.js");
|
||||
|
||||
// Auth check must come before the GrowthBook gate check — without auth,
|
||||
// GrowthBook has no user context and would return a stale/default false.
|
||||
// getBridgeDisabledReason awaits GB init, so the returned value is fresh
|
||||
// (not the stale disk cache), but init still needs auth headers to work.
|
||||
const { getClaudeAIOAuthTokens } = await import("../utils/auth.js");
|
||||
if (!getClaudeAIOAuthTokens()?.accessToken) {
|
||||
exitWithError(BRIDGE_LOGIN_ERROR);
|
||||
}
|
||||
const disabledReason = await getBridgeDisabledReason();
|
||||
if (disabledReason) {
|
||||
exitWithError(`Error: ${disabledReason}`);
|
||||
}
|
||||
const versionError = checkBridgeMinVersion();
|
||||
if (versionError) {
|
||||
exitWithError(versionError);
|
||||
}
|
||||
|
||||
// Bridge is a remote control feature - check policy limits
|
||||
const { waitForPolicyLimitsToLoad, isPolicyAllowed } =
|
||||
await import("../services/policyLimits/index.js");
|
||||
await waitForPolicyLimitsToLoad();
|
||||
if (!isPolicyAllowed("allow_remote_control")) {
|
||||
exitWithError(
|
||||
"Error: Remote Control is disabled by your organization's policy.",
|
||||
);
|
||||
}
|
||||
await bridgeMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude daemon [subcommand]`: long-running supervisor.
|
||||
if (feature("DAEMON") && args[0] === "daemon") {
|
||||
profileCheckpoint("cli_daemon_path");
|
||||
const { enableConfigs } = await import("../utils/config.js");
|
||||
enableConfigs();
|
||||
const { initSinks } = await import("../utils/sinks.js");
|
||||
initSinks();
|
||||
const { daemonMain } = await import("../daemon/main.js");
|
||||
await daemonMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude ps|logs|attach|kill` and `--bg`/`--background`.
|
||||
// Session management against the ~/.claude/sessions/ registry. Flag
|
||||
// literals are inlined so bg.js only loads when actually dispatching.
|
||||
if (
|
||||
feature("BG_SESSIONS") &&
|
||||
(args[0] === "ps" ||
|
||||
args[0] === "logs" ||
|
||||
args[0] === "attach" ||
|
||||
args[0] === "kill" ||
|
||||
args.includes("--bg") ||
|
||||
args.includes("--background"))
|
||||
) {
|
||||
profileCheckpoint("cli_bg_path");
|
||||
const { enableConfigs } = await import("../utils/config.js");
|
||||
enableConfigs();
|
||||
const bg = await import("../cli/bg.js");
|
||||
switch (args[0]) {
|
||||
case "ps":
|
||||
await bg.psHandler(args.slice(1));
|
||||
break;
|
||||
case "logs":
|
||||
await bg.logsHandler(args[1]);
|
||||
break;
|
||||
case "attach":
|
||||
await bg.attachHandler(args[1]);
|
||||
break;
|
||||
case "kill":
|
||||
await bg.killHandler(args[1]);
|
||||
break;
|
||||
default:
|
||||
await bg.handleBgFlag(args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for template job commands.
|
||||
if (
|
||||
feature("TEMPLATES") &&
|
||||
(args[0] === "new" || args[0] === "list" || args[0] === "reply")
|
||||
) {
|
||||
profileCheckpoint("cli_templates_path");
|
||||
const { templatesMain } =
|
||||
await import("../cli/handlers/templateJobs.js");
|
||||
await templatesMain(args);
|
||||
// process.exit (not return) — mountFleetView's Ink TUI can leave event
|
||||
// loop handles that prevent natural exit.
|
||||
// eslint-disable-next-line custom-rules/no-process-exit
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Fast-path for `claude environment-runner`: headless BYOC runner.
|
||||
// feature() must stay inline for build-time dead code elimination.
|
||||
if (
|
||||
feature("BYOC_ENVIRONMENT_RUNNER") &&
|
||||
args[0] === "environment-runner"
|
||||
) {
|
||||
profileCheckpoint("cli_environment_runner_path");
|
||||
const { environmentRunnerMain } =
|
||||
await import("../environment-runner/main.js");
|
||||
await environmentRunnerMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for `claude self-hosted-runner`: headless self-hosted-runner
|
||||
// targeting the SelfHostedRunnerWorkerService API (register + poll; poll IS
|
||||
// heartbeat). feature() must stay inline for build-time dead code elimination.
|
||||
if (feature("SELF_HOSTED_RUNNER") && args[0] === "self-hosted-runner") {
|
||||
profileCheckpoint("cli_self_hosted_runner_path");
|
||||
const { selfHostedRunnerMain } =
|
||||
await import("../self-hosted-runner/main.js");
|
||||
await selfHostedRunnerMain(args.slice(1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast-path for --worktree --tmux: exec into tmux before loading full CLI
|
||||
const hasTmuxFlag =
|
||||
args.includes("--tmux") || args.includes("--tmux=classic");
|
||||
if (
|
||||
hasTmuxFlag &&
|
||||
(args.includes("-w") ||
|
||||
args.includes("--worktree") ||
|
||||
args.some((a) => a.startsWith("--worktree=")))
|
||||
) {
|
||||
profileCheckpoint("cli_tmux_worktree_fast_path");
|
||||
const { enableConfigs } = await import("../utils/config.js");
|
||||
enableConfigs();
|
||||
const { isWorktreeModeEnabled } =
|
||||
await import("../utils/worktreeModeEnabled.js");
|
||||
if (isWorktreeModeEnabled()) {
|
||||
const { execIntoTmuxWorktree } =
|
||||
await import("../utils/worktree.js");
|
||||
const result = await execIntoTmuxWorktree(args);
|
||||
if (result.handled) {
|
||||
return;
|
||||
}
|
||||
// If not handled (e.g., error), fall through to normal CLI
|
||||
if (result.error) {
|
||||
const { exitWithError } = await import("../utils/process.js");
|
||||
exitWithError(result.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect common update flag mistakes to the update subcommand
|
||||
if (
|
||||
args.length === 1 &&
|
||||
(args[0] === "--update" || args[0] === "--upgrade")
|
||||
) {
|
||||
process.argv = [process.argv[0]!, process.argv[1]!, "update"];
|
||||
}
|
||||
|
||||
// --bare: set SIMPLE early so gates fire during module eval / commander
|
||||
// option building (not just inside the action handler).
|
||||
if (args.includes("--bare")) {
|
||||
process.env.CLAUDE_CODE_SIMPLE = "1";
|
||||
}
|
||||
|
||||
// No special flags detected, load and run the full CLI
|
||||
const { startCapturingEarlyInput } = await import("../utils/earlyInput.js");
|
||||
startCapturingEarlyInput();
|
||||
profileCheckpoint("cli_before_main_import");
|
||||
const { main: cliMain } = await import("../main.jsx");
|
||||
profileCheckpoint("cli_after_main_import");
|
||||
await cliMain();
|
||||
profileCheckpoint("cli_after_main_complete");
|
||||
// No special flags detected, load and run the full CLI
|
||||
const { startCapturingEarlyInput } = await import('../utils/earlyInput.js');
|
||||
startCapturingEarlyInput();
|
||||
profileCheckpoint('cli_before_main_import');
|
||||
const { main: cliMain } = await import('../main.jsx');
|
||||
profileCheckpoint('cli_after_main_import');
|
||||
await cliMain();
|
||||
profileCheckpoint('cli_after_main_complete');
|
||||
}
|
||||
|
||||
// eslint-disable-next-line custom-rules/no-top-level-side-effects
|
||||
|
||||
Reference in New Issue
Block a user