XiHan.Framework.Cli
命令行工具 xihan(.NET 工具包,RFC-0016):pack 从应用清单 xihan.app.json 生成 Dockerfile、Kustomize、Compose 与 Aspire 产物,graph / pipeline / operations / invoke 转发给应用自己的命令行宿主,migrate 提供按来源版本选规则集的源码迁移机制,mcp 以 stdio 给编码助手提供框架离线知识库(包与特性清单、配置键与缺省值、文档)。适用于本地开发与 CI 里的打包与诊断,以及让 AI 编码工具按工具版本查证框架。
| 项 | 内容 |
|---|---|
| 包 ID | XiHan.Framework.Cli |
| 环层 | 工具链 |
| 能力 | — |
| 特性入口 | —(命令名 xihan,PackAsTool) |
| 配置节 | — |
| 依赖 | XiHan.Framework.Hosting.CommandLine(解析、帮助、失败输出、退出码)、XiHan.Framework.Localization.InMemory(文案)、XiHan.Framework.Protocols.Mcp(mcp 的协议与 stdio 传输,带入 ASP.NET Core 共享框架);Microsoft.CodeAnalysis.CSharp(migrate 的语法树) |
| AOT | 不适用(以框架依赖的 .NET 工具运行) |
| 稳定性 | Preview |
概述
xihan 用 Hosting.CommandLine 的解析器、帮助与失败输出:失败时把 Problem JSON 写到 stderr,退出码按错误码的 KIND 段映射(命令行宿主)。文案按 --locale 或当前 UI 区域协商,内置与框架相同的 10 种区域。工具包的公开面只有消息键常量 CliMessages,命令本身是 internal 的,不作为库使用。
| 命令 | 说明 |
|---|---|
pack | 从 xihan.app.json 生成部署产物,逐行输出写出的文件 |
graph / pipeline / operations / invoke | 转发给应用的命令行宿主 |
migrate <来源版本> | 按来源版本的规则集改写源码;当前没有登记任何规则集 |
mcp | 以 stdio 提供框架离线知识库的 MCP 服务,三个只读 tool:xihan_framework_info、xihan_framework_config、xihan_framework_search |
setup --client <claude|cursor|vscode|codex> | 把 mcp 服务与使用技能写进编码助手的项目配置 |
version | 打印框架名与版本 |
help | 命令列表;没有命令时打印到 stderr 并以 64 退出 |
何时使用
- 生成容器与 Kubernetes 产物:
xihan pack,写法见部署与打包。 - 在仓库根或清单目录里查看应用的能力图谱、管道与操作:
xihan graph等转发命令,省去手写dotnet run --project … --。 - 让 Claude Code、Cursor、VS Code、Codex 等编码助手查证包名、能力 ID、配置键与缺省值:把
xihan mcp配成它们的 MCP 服务,见 MCP Server。 - 不需要工具也能做同样的事:转发命令等价于
dotnet run --project <项目> -- <命令>,应用要装配Hosting.CommandLine。
安装与启用
dotnet tool install --global XiHan.Framework.Cli --prerelease
xihan version当前是预览版,安装要带 --prerelease;从源码或本地包源引用见快速上手。不安装也可以从源码运行(在仓库根执行):
dotnet run --project framework/src/XiHan.Framework.Cli -- pack --manifest framework/samples/SimpleApp/xihan.app.json --output ./artifacts/simple-app-deploy命令
pack
xihan pack [--manifest <path>] [--output <dir>] [--only dockerfile,kustomize,compose,aspire]| 选项 | 缺省 | 说明 |
|---|---|---|
--manifest | ./xihan.app.json | 应用清单路径 |
--output | 清单所在目录下的 deploy/ | 输出目录,产物整份覆盖写入(UTF-8 无 BOM、LF 换行) |
--only | 全部 | 逗号分隔的产物种类,不区分大小写;不认识的种类为 CLI_VALIDATION_001,退出码 64 |
产物与清单字段的映射见部署与打包。写出的文件包括 Dockerfile 与 Dockerfile.dockerignore、kustomize/(Deployment、Service、ConfigMap、HPA、PDB、Lease 的 RBAC、Secret 示例与 kustomization)、compose.yaml、aspire/XiHanAppHost.g.cs,逐行输出写出的文件;Kafka、Nacos 这类依赖服务在 Kustomize 里只出 Secret 示例,不在集群里起服务。
graph、pipeline、operations、invoke
xihan graph --project src/Orders
xihan operations
xihan invoke orders.create --json '{"name":"widget","amount":3}'
xihan orders create --name widget --amount 3转发规则:执行 dotnet run --project <项目> --configuration <配置> -- <命令> <参数> <其余选项>。项目取 --project,否则取当前目录 xihan.app.json 的 project,都没有时交给 dotnet run 自己找;--configuration 缺省 Release;--project 与 --configuration 之外的选项(含 --locale)原样转发。不是已知命令、但「命令.第一个参数」是合法操作 ID 时按 invoke 简写处理:xihan orders create … 等价于 xihan invoke orders.create …。退出码是子进程的退出码;dotnet 无法启动为 CLI_UNAVAILABLE_001,退出码 6。
migrate
xihan migrate <来源版本> [--path <目录|.csproj|.slnx>] [--fixers <规则编号,…>] [--dry-run] [--report <文件>]工具当前没有登记任何规则集,所以任何来源版本都以 CLI_VALIDATION_002 失败,退出码 64。机制本身保留给之后的大版本升级(RFC-0020,spec/migration/README.md):语法级 Roslyn 重写,不加载 MSBuild 工作区;先扫描收集跨文件事实,再按规则顺序改写回写,之后写生成文件、删除与改名;改不了的位置留 // xihan-migrate(<规则编号>): <说明> 标记;对已迁移的代码再跑一遍零改动;跳过 bin/、obj/、.git/、.vs/、node_modules/、*.g.cs、*.Designer.cs。--dry-run 只出报告不写文件,--report 把 JSON 报告写到文件。
mcp
xihan mcp [--path <项目目录>] [--locale <区域>]
dnx XiHan.Framework.Cli@<版本> --yes -- mcp # 不安装、按版本运行(编码助手配置里的写法)以 stdio 提供 MCP 服务(协议版本 2025-06-18),stdout 每行一条 JSON-RPC 消息,stdin 关闭即退出。工具内嵌一个最小的 XiHan 应用(内存本地化 + Protocols.Mcp + 三个只读、只暴露给 MCP 的操作),协议、tools/list 与 tools/call 都由 Protocols.Mcp 处理;tool 的标题与描述按 --locale(或当前 UI 区域)取自工具的消息目录。服务名 xihan-framework。
| tool | 输入 | 输出 |
|---|---|---|
xihan_framework_info | name:包 ID、短名(Caching.Redis)、文档页名(caching-redis)、清单 ID、特性类型名或能力 ID(可带 @版本);不给时列出全部包 | 包:安装命令、环层、框架包 / 第三方包 / 共享框架依赖、每个特性的清单(种类与角色、提供与依赖的能力、绑定、配置节、管道中间件、操作、权限码、健康项)、读取的配置节、相关文档页;能力:提供者(含 default 角色)与依赖方 |
xihan_framework_config | query:配置节(含其下子节)、完整键路径(按名字展开的段任意匹配)、包、Options 类名,或键名与说明里的文字;不给时列出全部配置节 | 每个键的完整路径、类型、缺省值、是否必填、上下限或枚举取值、说明,以及按缺省值与必填示例写出的 appsettings 片段 |
xihan_framework_search | query(空格分隔的词须同时出现)与 limit(1-50,缺省 10),或 page(仓库内路径、guide/caching、RFC 编号或包 ID) | 按相关度排序的文档页与摘录,或一页全文 |
结果是结构化 JSON(structuredContent 与文本内容相同)。查不到时 isError,文本 CLI_NOTFOUND_003: … 带最接近的候选;检索既没给 query 也没给 page、或 limit 越界为 CLI_VALIDATION_004。
数据随工具一起构建,与工具版本一致:包与特性清单、各 Options 读取的配置键(有测试逐条核对与代码一致),以及文档站、RFC 与约定、各包 README 的全文。包与特性清单(Knowledge/catalog.json)由 XiHan.Framework.Cli.Tests 从项目文件、framework/README.md 包表与各特性的 Manifest 生成,与代码不一致时 KnowledgeCatalogTests 失败,运行 pwsh framework/scripts/Update-CliKnowledge.ps1 重新生成;配置键索引(Knowledge/configuration.json)人工整理,改了 Options 后 KnowledgeConfigurationTests 失败,按失败信息改索引;文档与 README 在构建时嵌入程序集。--path(缺省当前目录)所在项目引用的 XiHan.Framework.* 版本与工具不同时,stderr 与服务端说明里提示改用 dnx XiHan.Framework.Cli@<项目版本> --yes -- mcp。
setup
xihan setup --client <claude|cursor|vscode|codex> [--mode mcp|skill|both] [--pin <版本>] [--path <目录>] [--dry-run] [--check]
dnx XiHan.Framework.Cli@<版本> --yes -- setup --client claude # 不安装、按版本运行把 mcp 服务(服务名 xihan-framework,命令 dnx XiHan.Framework.Cli@<版本> --yes -- mcp)写进编码助手的项目配置,并按 --mode 写入使用技能:
--client | MCP 配置 | 技能 |
|---|---|---|
claude | .mcp.json 的 mcpServers;Windows 上命令写成 cmd /c dnx … | .claude/skills/xihan-framework/SKILL.md |
cursor | .cursor/mcp.json 的 mcpServers | .agents/skills/xihan-framework/SKILL.md |
vscode | .vscode/mcp.json 的 servers,每项带 "type": "stdio" | 同上 |
codex | 不写文件,打印 ~/.codex/config.toml 的 [mcp_servers.xihan-framework] 片段 | 同上 |
| 选项 | 缺省 | 说明 |
|---|---|---|
--client | — | 必填 |
--mode | both | mcp 只写服务配置,skill 只写技能 |
--pin | 项目引用的 XiHan.Framework.* 版本,没有时为工具版本 | 服务钉住的工具版本 |
--path | 当前目录 | 从这里向上找项目根:git 根,否则第一个含解决方案或项目文件的目录 |
--dry-run | — | 只打印要写的内容 |
--check | — | 核对配置与技能是否已就绪 |
- 幂等:JSON 配置只替换本服务那一项,别的服务与顶层键原样保留,重复执行得到相同的文件;技能文件整份覆盖。
- 要合并的配置文件读不了(带注释的 JSONC、顶层不是对象)时一个文件都不写,按
--dry-run打印的片段手工合并。 - 版本:数据随工具版本走,
--pin与项目引用的版本一致时,编码助手查到的就是项目在用的那一版。
行为与限制
退出码:
| 情形 | 错误码 | 退出码 |
|---|---|---|
| 成功 | — | 0 |
| 应用清单不存在 | CLI_NOTFOUND_001 | 3 |
应用清单不合法(detail 列出全部问题) | CLI_VALIDATION_001 | 2 |
--only 有不认识的产物种类 | CLI_VALIDATION_001 | 64 |
| 没有命令、命令不认识 | — | 64 |
dotnet 无法启动 | CLI_UNAVAILABLE_001 | 6 |
| 转发命令 | — | 子进程的退出码 |
migrate 的 --path 不存在 | CLI_NOTFOUND_002 | 3 |
migrate 的来源版本没有规则集 | CLI_VALIDATION_002 | 64 |
migrate --fixers 有不认识的规则编号 | CLI_VALIDATION_003 | 64 |
setup 的 --client 或 --mode 不认识 | CLI_VALIDATION_005 | 64 |
setup 找不到项目根 | CLI_NOTFOUND_004 | 3 |
setup 要合并的配置文件读不了(不改动任何文件) | CLI_VALIDATION_006 | 2 |
setup --check 未就绪(detail 列出各项) | CLI_CONFLICT_001 | 5 |
mcp 在 stdin 关闭后 | — | 0 |
| 被 Ctrl+C 取消 | — | 8 |
- Ctrl+C 先取消当前命令,让它按取消语义收尾,而不是直接终止进程。
pack只读清单与它引用的文件(项目、构建上下文、config.files),不构建项目、不调用 Docker 或 kubectl。- 生成的 Compose 应用服务 healthcheck 用 Dockerfile 随镜像构建的就绪探针
/xihan/healthprobe请求/health/ready(chiseled 镜像里没有curl与wget;AOT 镜像里是原生可执行文件,否则以dotnet运行框架依赖的探针),interval/timeout/start_period取probes的三个秒数。 - 绑定在 Compose 与 Aspire 里以
XiHan__Bindings__<名>__type/__value注入;blob的依赖服务是 S3 兼容的 RustFS(rustfs/rustfs:1.0.4,MinIO 社区版已停发镜像,ADR-0086),以固定的本地联调凭据启动,同一对值另作绑定属性accessKey/secretKey注入,覆盖 S3 配置节里的同名键。Kustomize 的bindings.example.yaml以注释列出各类型可单独给出的凭据键(RFC-0016「资源绑定与配置节」)。 CliMessages.Catalog是工具的消息目录(目录名cli),10 种区域各一个文件。
相关
- 部署与打包、命令行宿主
- Hosting.CommandLine
- 规范:RFC-0016《应用清单与打包》、RFC-0020《版本迁移》
