# 核心模块设计 — CLI 启动与解析 > 所属项目: free-code .NET 10 重写 > 原始代码来源: `../../src/entrypoints/cli.tsx`, `../../src/screens/REPL.tsx` > 原始设计意图: 解析命令行参数,区分交互式 REPL 模式和一次性 prompt 模式,并处理 daemon/bridge 等特殊运行模式 > 上级文档: [核心模块设计总览](核心模块设计.md) > 交叉参考: [总体概述与技术选型](../总体概述与技术选型/总体概述与技术选型.md) --- ## 概述 CLI 启动模块是整个应用的入口,对应原始 TypeScript 项目的 `cli.tsx`。它的核心职责是在加载任何业务逻辑之前,先判断这次调用属于哪种运行模式,并将控制权交给对应的处理器。 .NET 重写将原始代码中混合在一个文件里的逻辑拆分为三个独立的类: - `Program` — 四阶段启动协调器 - `QuickPathHandler` — 无需 DI 容器的快速路径处理 - `CliCommandBuilder` — 基于 `System.CommandLine` 的命令行定义 --- ## 5.1 入口点 Program.cs `Program.cs` 组织为四个顺序执行的阶段,每一阶段都有明确的失败边界。 **原始设计意图:** 原始 `cli.tsx` 在模块顶层直接调用 Commander.js 解析参数,然后根据 flag 条件决定走哪条路径。.NET 版本将这一隐式流程显式化为四个阶段,并统一使用 `Microsoft.Extensions.Hosting` 管理生命周期。 ```csharp public static class Program { public static async Task Main(string[] args) { // Phase 1: 快速路径(不加载DI容器,零开销) if (QuickPathHandler.TryHandle(args, out var exitCode)) return exitCode; // Phase 2: 构建Host var host = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration(cfg => cfg .AddJsonFile("appsettings.json", optional: true) .AddJsonFile(Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".free-code", "settings.json"), optional: true, reloadOnChange: true)) .ConfigureServices((ctx, services) => { services.AddCoreServices(); services.AddEngine(); services.AddTools(); services.AddCommands(); services.AddApiProviders(); services.AddMcp(); services.AddLsp(); services.AddBridge(); services.AddBusinessServices(); services.AddTasks(); services.AddSkills(); services.AddPlugins(); services.AddFeatures(); services.AddState(); services.AddTerminalUI(); }) .ConfigureLogging(logging => logging .AddConsole() .SetMinimumLevel(LogLevel.Information)) .Build(); // Phase 3: 初始化核心服务 await host.Services.GetRequiredService().InitializeAsync(); // Phase 4: 启动REPL或执行一次性命令 var runner = host.Services.GetRequiredService(); return await runner.RunAsync(args); } } ``` ### 四阶段说明 | 阶段 | 职责 | 失败处理 | |------|------|----------| | Phase 1 | 快速路径检测,无 DI 开销 | 匹配则直接返回,不进入后续阶段 | | Phase 2 | 构建 Host,注册所有服务 | `HostBuilder` 抛出则进程退出 | | Phase 3 | 异步初始化(OAuth 刷新、MCP 连接等) | `InitializeAsync` 可抛出 `AppInitializationException` | | Phase 4 | 启动 REPL 或执行一次性 prompt | `RunAsync` 返回退出码 | `reloadOnChange: true` 设置在 `~/.free-code/settings.json` 上,允许用户在 REPL 运行期间修改配置后立即生效,无需重启。 --- ## 5.2 快速路径处理器 `QuickPathHandler` 对应原始 `cli.tsx` 中散布在文件顶部的 fast-path 条件判断。 **原始设计意图:** 原始代码在 Commander.js 解析之前,用一系列 `process.argv.includes()` 检查来处理特殊 flag,避免触发 React/Ink 的初始化开销。.NET 版本将这些检查集中到一个静态类,并且同样在 DI 容器构建之前执行。 ```csharp public static class QuickPathHandler { public static bool TryHandle(string[] args, out int exitCode) { exitCode = 0; // --version if (args.Contains("--version")) { var ver = Assembly.GetEntryAssembly()! .GetCustomAttribute()! .InformationalVersion; Console.WriteLine($"free-code {ver}"); return true; } // --dump-system-prompt if (args.Contains("--dump-system-prompt")) { var builder = new SystemPromptBuilder(/* minimal config */); Console.WriteLine(builder.BuildDefaultPrompt()); return true; } // MCP daemon mode if (args.Contains("--mcp-daemon")) { exitCode = McpDaemon.Run(args).GetAwaiter().GetResult(); return true; } // Bridge mode if (args.Contains("--bridge")) { exitCode = BridgeMain.Run(args).GetAwaiter().GetResult(); return true; } // Background session mode if (args.Contains("--background-session")) { exitCode = BackgroundSessionRunner.Run(args).GetAwaiter().GetResult(); return true; } // Template mode if (args.Contains("--template")) { exitCode = TemplateRunner.Run(args).GetAwaiter().GetResult(); return true; } return false; } } ``` ### 快速路径 flag 列表 | Flag | 处理器 | 说明 | |------|--------|------| | `--version` | 直接打印 | 从程序集元数据读取版本号 | | `--dump-system-prompt` | `SystemPromptBuilder` | 打印默认 System Prompt,用于调试 | | `--mcp-daemon` | `McpDaemon.Run` | 以 MCP 服务器模式运行,供 IDE 插件调用 | | `--bridge` | `BridgeMain.Run` | IDE 远程控制桥接模式 | | `--background-session` | `BackgroundSessionRunner.Run` | 后台会话模式,供 Agent 工具启动子进程 | | `--template` | `TemplateRunner.Run` | 模板执行模式 | 注意 `--mcp-daemon` 和 `--bridge` 的处理器使用 `.GetAwaiter().GetResult()` 同步等待,因为此时还没有 `async` 上下文可用(`Main` 的 `await` 路径已被 Phase 1 短路)。 --- ## 5.3 CLI 命令定义 (CliCommandBuilder) `CliCommandBuilder` 对应原始 `cli.tsx` 中的 Commander.js 配置,负责定义全局选项和根命令的处理逻辑。 **原始设计意图:** Commander.js 的 `program.option(...).action(...)` 链式 API 被映射到 `System.CommandLine` 的 `RootCommand` + `Option` 模式。两者在概念上完全对应,只是 API 风格不同。 ```csharp public class CliCommandBuilder { public RootCommand Build() { var root = new RootCommand("free-code - The free build of Claude Code"); // 全局选项 var modelOption = new Option("--model", "Override default model"); var verboseOption = new Option("--verbose", "Verbose output"); var resumeOption = new Option("--resume", "Resume session ID"); root.AddGlobalOption(modelOption); root.AddGlobalOption(verboseOption); root.AddGlobalOption(resumeOption); // 一次性 prompt 模式 (-p) var promptOption = new Option("-p", "One-shot prompt (non-interactive)"); root.AddOption(promptOption); root.SetHandler(async (string? prompt, string? model, bool verbose, string? resume) => { if (prompt != null) return await OneShotMode.ExecuteAsync(prompt, model); return await REPLMode.StartAsync(model, verbose, resume); }, promptOption, modelOption, verboseOption, resumeOption); return root; } } ``` ### 选项说明 | 选项 | 类型 | 作用域 | 说明 | |------|------|--------|------| | `--model` | `string?` | 全局 | 覆盖配置文件中的默认模型 | | `--verbose` | `bool` | 全局 | 开启详细日志输出 | | `--resume` | `string?` | 全局 | 恢复指定 session ID 的对话历史 | | `-p` | `string?` | 根命令 | 非交互式一次性 prompt 模式 | `--model`、`--verbose`、`--resume` 作为全局选项注册,子命令也可以访问。`-p` 仅在根命令级别有效,因为子命令有各自的参数结构。 当 `-p` 存在时,走 `OneShotMode.ExecuteAsync` 路径(非交互式,执行完毕后退出)。否则走 `REPLMode.StartAsync` 启动交互式终端 UI。 --- ## 模块间依赖 ``` Program.cs ├── QuickPathHandler (静态,无依赖) │ ├── SystemPromptBuilder (仅 --dump-system-prompt 路径) │ ├── McpDaemon │ ├── BridgeMain │ ├── BackgroundSessionRunner │ └── TemplateRunner │ └── CliCommandBuilder (由 IAppRunner 使用) ├── OneShotMode └── REPLMode ``` --- ## 参考资料 - [核心模块设计总览](核心模块设计.md) - [查询引擎 (QueryEngine)](核心模块设计-查询引擎-QueryEngine.md) - [原始代码映射 — 核心模块](reference/原始代码映射-核心模块.md) - [总体概述与技术选型](../总体概述与技术选型/总体概述与技术选型.md)