来源：https://framework.docs.xihanfun.com/packages/hosting-commandline

# XiHan.Framework.Hosting.CommandLine

命令行宿主：在 .NET 通用宿主里把命令行参数翻译成内核调用，内置 `help`、`graph`、`pipeline`、`operations`、`invoke` 命令。适用于运维工具、批处理脚本，以及要以 stdio 给 MCP 客户端当子进程的应用。

| 项 | 内容 |
| --- | --- |
| 包 ID | `XiHan.Framework.Hosting.CommandLine` |
| 环层 | Ring 4（宿主） |
| 能力 | — |
| 特性入口 | —（`AddXiHanCommandLine()` 登记） |
| 配置节 | —；环境变量 `XIHAN_CONFIG_PATH`（挂载的配置目录）、`XIHAN_AUTHORIZATION`（缺省凭据） |
| 依赖 | `XiHan.Framework.Kernel`、`XiHan.Framework.Security.Abstractions`、`XiHan.Framework.Localization.Abstractions`；`Microsoft.Extensions.Hosting`、`Microsoft.Extensions.Configuration.Json`、`Microsoft.Extensions.Logging.Console` |
| AOT | 兼容（`IsAotCompatible`） |
| 稳定性 | Preview |

## 概述

一次进程执行一条命令。`invoke <操作 ID>` 与简写 `<resource> <verb>` 把 `--json`、`--data` 或字段选项拼成载荷，把 `--tenant`、`--correlation`、`--locale`、`--timeout`、`--authorization` 翻译成调用上下文，经完整内核管道调用暴露给命令行（`Expose.CommandLine`）的操作。成功时响应 JSON 写到 stdout，失败时一行 `{"code","detail","traceId"}` 写到 stderr，退出码按错误码的 KIND 段决定。`AddXiHanCommandLine()` 把日志改成只写 stderr，stdout 只有命令输出。

其他包可以登记自己的命令：实现 `ICommand` 后 `AddXiHanCommand<T>()`，`Protocols.Mcp` 就以这种方式提供 `mcp` 命令（MCP 的 stdio 传输）。

## 何时使用

同一份操作契约要在终端、CI 脚本或定时任务里调用时用它；要让 MCP 客户端以子进程方式连接应用时，与 [Protocols.Mcp](./protocols-mcp) 一起用。对外提供网络服务用 [Hosting.AspNetCore](./hosting-aspnetcore)。组合包都不包含本包。

## 安装与启用

```bash
dotnet add package XiHan.Framework.Hosting.CommandLine --prerelease
```

当前是预览版，安装要带 `--prerelease`；从源码或本地包源引用见[快速上手](../quickstart#获取预览包)。

```csharp
using Microsoft.Extensions.Hosting;
using XiHan.Framework.Hosting.CommandLine;
using XiHan.Framework.Profiles.Minimal;

var builder = Host.CreateApplicationBuilder(args);
builder.AddXiHan(xihan => xihan.UseMinimalProfile());
builder.Services.AddXiHanCommandLine();

return await builder.Build().RunXiHanCommandLineAsync(args);
```

## 主要类型

| 类型 | 说明 |
| --- | --- |
| `HostApplicationBuilderConfigurationExtensions` | `AddXiHan(configure)`：先装载 `XIHAN_CONFIG_PATH` 目录（紧接 `appsettings.{环境}.json` 插入），再交给内核装配应用 |
| `CommandLineServiceCollectionExtensions` | `AddXiHanCommandLine()` 登记运行器与内置命令并把日志改到 stderr；`AddXiHanCommand<TCommand>()` 登记命令 |
| `CommandLineHostExtensions` | `RunXiHanCommandLineAsync(args)`：启动宿主、执行命令、停止宿主，返回退出码；Ctrl+C 取消命令 |
| `Commands.ICommand` | 命令：`Name`、`DescriptionKey`（说明的消息键）、`ExecuteAsync(CommandContext)` |
| `Commands.CommandContext` | 解析结果、作用域服务、`Output` / `Error`、取消令牌 |
| `Commands.HelpCommand`、`GraphCommand`、`PipelineCommand`、`OperationsCommand`、`InvokeCommand` | 内置命令 |
| `Parsing.CommandLineParser`、`Parsing.ParsedCommandLine` | 参数解析 |
| `Runtime.CommandLineInvocation` | `Create(context, operationId)` 按选项建调用上下文；`ReservedOptions`；`AuthorizationVariable` = `XIHAN_AUTHORIZATION` |
| `Runtime.CommandLineFailure` | `WriteAsync(...)` 把失败写到 stderr 并给出退出码 |
| `Runtime.CommandLineRunner` | 命令表与分发 |
| `CommandLineExitCodes` | 退出码常量与 `For(error)` |
| `CommandLineErrors` | `HOSTING_VALIDATION_001`、`HOSTING_NOTFOUND_001`、`HOSTING_NOTFOUND_002` |

## 使用示例

```bash
dotnet run --project framework/samples/SimpleCli -- greetings create --name Ada --times 2
dotnet run --project framework/samples/SimpleCli -- invoke greetings.create --json '{"name":"Ada"}' --locale zh-CN
XIHAN_AUTHORIZATION="ApiKey dev-alice-key" dotnet run --project framework/samples/SimpleCli -- greetings create --name Ada
```

自定义命令与选项的完整说明见[命令行宿主](../guide/command-line)。

## 行为与限制

- 解析：第一个非选项记号是命令名；`--name value`、`--name=value`、无值的 `--flag` 记为 `true`；`--` 之后全是位置参数；载荷按 `--json`（须为对象）> `--data <file>`（可写 `@file`）> 字段选项的顺序取，字段选项重复时成数组。
- 字段选项按操作的请求 Schema 写成对应类型（布尔、整数、浮点、数组），转换不了的值留字符串，由 Validate 阶段报 `KERNEL_VALIDATION_003`；`--json` 与 `--data` 的载荷原样进入。操作没有 Schema 时值都是字符串，请求类型要从字符串读数字，序列化上下文需要 `NumberHandling = JsonNumberHandling.AllowReadingFromString`。
- 保留选项 `json`、`data`、`authorization`、`tenant`、`correlation`、`locale`、`timeout`、`help` 不进载荷。
- `--authorization` 与 `XIHAN_AUTHORIZATION` 只作用于 `invoke`；`mcp` 命令的调用以匿名主体执行。
- 命令名重复时 `CommandLineRunner` 构造失败（`ArgumentException`）。

| KIND / 情形 | 退出码 |
| --- | --- |
| 成功 | 0 |
| `VALIDATION` | 2 |
| `NOTFOUND`（含 `HOSTING_NOTFOUND_001` 操作未暴露） | 3 |
| `DENIED` | 4 |
| `CONFLICT` | 5 |
| `UNAVAILABLE` | 6 |
| `TIMEOUT` | 7 |
| `CANCELLED`、Ctrl+C | 8 |
| 其他 | 1 |
| 用法错误（`HOSTING_VALIDATION_001`、`HOSTING_NOTFOUND_002`） | 64 |

## 相关

- [命令行宿主](../guide/command-line)、[操作契约](../guide/operations)
- [Protocols.Mcp](./protocols-mcp)：`mcp` 命令
- [Hosting.AspNetCore](./hosting-aspnetcore)、[Cli 命令行工具](./cli)
- 规范：`spec/protocol/commandline.md`《命令行载体》、RFC-0011《操作契约与 XGI》
