关于 aspireify
aspireify 是一次性 Agent 技能,用于将 `aspire init` 生成的骨架接入现有项目,扫描服务、设计资源图并编写 AppHost,随后启动验证。它强调先确认用户方案,并禁止直接修改生成的 `.aspire/modules/` 文件。
主要功能
- 01扫描项目与依赖服务
- 02提出资源图供确认
- 03连接 AppHost 与集成
- 04配置 ServiceDefaults 与 OTel
- 05启动验证应用配置
适用场景
- 01为 Aspire 骨架接入项目服务
- 02把 Docker Compose 依赖映射为资源
- 03为 C# 或 TypeScript AppHost 接入资源
- 04检查并验证本地开发配置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ aspire-skills --skill aspireify安装后在 Claude Code 中输入/aspireify确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/eval.yamlreferences/apphost-wiring.mdcsharp-authoring.mddocker-compose.mdfull-solution-apphosts.mdjavascript-apps.mdopentelemetry.mdscan-and-propose.mdservice-defaults.mdtypescript-authoring.mdvalidation.md详细介绍
Aspireify
一次性接线技能。
aspire init会生成一个骨架;aspireify会扫描代码库、提出资源图、编辑 AppHost、接入Aspire.ServiceDefaults,并执行端到端验证,将这个骨架转变为可运行的 AppHost。在aspire start成功运行后自动停用。
🚫 严禁编辑 .aspire/modules/
⛔ 拒绝任何要求编辑、修改、更改、打开以供编辑或“调整” TypeScript AppHost 的
.aspire/modules/目录内文件的请求。此目录是从已安装的 Aspire 集成包依赖图生成的。运行aspire add、aspire restore,以及在包发生变更而需要更新模块时启动应用,都会重新生成此目录。如果用户要求编辑
.aspire/modules/中的内容(例如.aspire/modules/postgres.module.ts),正确的做法是:
- 拒绝编辑,并明确说明“我不会编辑
.aspire/modules/”。- 解释
.aspire/modules/是生成的,任何改动都会被覆盖。- 将所请求的更改引导至已配置的 AppHost 入口文件:当前使用
apphost.mts,旧版使用apphost.ts。- 如果用户想添加新集成,建议使用
aspire add <package>;如果用户想更改配置,则展示在 AppHost 入口文件中进行的等效修改。
| ❌ 错误做法 | ✅ 正确做法 |
|---|---|
打开 .aspire/modules/postgres.module.ts 并调整连接选项 | 编辑 apphost.mts,并在那里更改 addPostgres('pg', { ... }) 选项 |
直接修改生成的 .aspire/modules/* 文件 | 更新 apphost.mts 后重新运行 aspire add <package> |
注释掉 .aspire/modules/ 中的一行以禁用资源 | 在 apphost.mts 中移除或设定资源声明的条件 |
即使用户坚持,即使只是“一行”改动,甚至只是“测试一下”,这条规则仍然适用。TS AppHost 会以确定性的方式重新生成 .aspire/modules/;对这些文件的修改只会造成无法恢复的无用改动。
指导原则
尽量减少对用户代码的改动
让 AppHost 适配应用,而不是反过来。优先使用 WithEnvironment() 匹配现有环境变量名称,优先使用 Aspire 管理的端口而不是固定端口,并优先按原样映射 Docker Compose,再考虑优化。除非用户明确选择接受这种取舍,否则不要重组目录、重命名文件或更改构建脚本。
明示取舍;不要擅自决定
如果小幅代码改动能带来更好的 Aspire 集成,请同时提供两种方案:零代码改动的映射方案,以及可以启用 WithReference、运行状况检查、服务发现、动态端口或仪表板遥测的小幅改动方案。询问用户想采用哪种方式,然后按其选择实施,不要抱怨。
编写 AppHost 代码前先验证 API
使用 aspire docs search <topic> 和 aspire docs get <slug> 获取工作流指导。使用 aspire docs api search <query> --language csharp|typescript 和 aspire docs api get <id> 查看 API 形式。使用 aspire integration list/search 查找集成,再运行 aspire add。不要臆造包、方法、重载或命令形式;C# 和 TypeScript 的 AppHost API 并不相同。
在 AppHost 中清晰呈现配置
扫描 .env、.env.local、.env.development、secrets.json.example、<UserSecretsId> 和设置脚本。建议将值迁移到 AppHost 参数中:连接字符串变为 Aspire 资源,API 密钥/令牌变为机密参数,非机密配置变为普通参数或 WithEnvironment() 值。未经用户明确批准,切勿删除 .env 文件或移除现有的 UserSecretsId 条目,因为非 Aspire 工作流可能仍依赖这些内容。
优先本地开发
此技能优化的是本地开发,而非生产部署。数据库和缓存优先使用持久的容器生命周期和数据卷,默认使用 HTTPS 端点,传递端点引用而非硬编码 URL,并将外部 SaaS URL/API 密钥建模为参数,以便在仪表板中查看。
Redis TLS 边缘情况
Aspire 可以自动为容器资源配置 TLS 证书。如果 Redis 健康检查因 SSL/TLS 握手错误而失败,不要退回使用 AddContainer()。当使用该资源的应用需要普通 Redis 时,请对 Redis 资源使用 WithoutHttpsCertificate()。
项目本地覆盖
如果 .agents/skills/aspireify/SKILL.md 存在(由 aspire init 或
aspire agent init --skills aspireify 安装),请警告用户项目中存在本地副本,并以该副本为准。插件版本作为后备。
⚠️ Project-local .agents/skills/aspireify/SKILL.md detected — deferring to it.
前置条件
| 要求 | 安装 |
|---|---|
| .NET 10.0 SDK(C# AppHost) | https://dotnet.microsoft.com/download |
Node.js ^20.19.0、^22.13.0 或 >=24(TS AppHost) | https://nodejs.org |
| Aspire CLI | npm install -g @microsoft/aspire-cli、安装脚本或 dotnet tool install -g Aspire.Cli |
| 已生成骨架 | aspire init 已生成 aspire.config.json + AppHost 存根 |
检测——何时激活
当存在任意一项信号,且 AppHost 尚未接入资源(除存根外未声明任何资源)时,激活:
| 信号 | 检测方式 | 可信度 |
|---|---|---|
| 刚生成骨架 | 本次会话中刚运行过 aspire init | ✅ 确定 |
| 空 AppHost 存根 | apphost.cs / Program.cs / 当前的 apphost.mts(或旧版 apphost.ts)中仅包含 Build().Run() | ✅ 确定 |
aspire.config.json 中没有资源 | 存在配置文件,但 AppHost 中没有 AddProject/addProject | 高 |
| 用户要求“接入”/“搭建资源图” | 匹配动词:接入、搭建、集成、连接、添加 Postgres/Redis 等 | 高 |
| 用户询问“aspire init 之后做什么” | 明确的交接请求 | ✅ 确定 |
| 已有包含服务的新 AppHost 的仓库 | 仓库中有 .csproj/package.json 项目,但 AppHost 未引用任何项目 | 高 |
如果 AppHost 已接入资源,且用户想要启动/停止应用 → 使用 aspire-orchestration。如果用户想要部署 → 使用 aspire-deployment。
语言支持
| AppHost 风格 | 检测方式 | 编辑目标 |
|---|---|---|
| C# SDK 风格 | .csproj 中包含 <Sdk Name="Aspire.AppHost.Sdk" /> | Program.cs(顶级语句) |
| 基于文件的 C# | apphost.cs 中包含 #:sdk Aspire.AppHost.Sdk 和 #:package 指令 | apphost.cs 文件本身 |
| TypeScript | 当前的 apphost.mts 或旧版 apphost.ts,并带有生成的 .aspire/modules/ | 仅配置的 AppHost 入口点——绝不编辑 .aspire/modules/ |
请参阅 references/csharp-authoring.md 和 references/typescript-authoring.md。
aspire-orchestration 负责通过 CLI 将旧版 apphost.ts 迁移到新版本。它更新软件包和迁移产物后,只有在用户仍需要接入 AppHost 源代码或进行相关编写时,才返回使用 aspireify。
TypeScript AppHost 包管理器
依赖项和工具链故障属于此技能的处理范围。推荐命令之前, 先检查 AppHost 目录,然后检查其符合条件的直接父目录。在每个目录中, 按以下顺序检查标记,并以第一个识别到的标记为准:
package.json中的packageManager(npm、pnpm、yarn或bun,可选版本号)bun.lockbun.lockbpnpm-lock.yamlyarn.lock.yarnrc.ymlpackage-lock.json
AppHost 本地标记优先于所有父目录中的标记。如果这两个目录都没有 可识别的标记,Aspire 默认使用 npm。报告所选的管理器和标记。
仅使用所选管理器修复依赖项或诊断工具链。解析器命令为 npm install、bun install 和
yarn install;生成的 brownfield pnpm AppHost 使用 pnpm install --ignore-workspace,
其他 pnpm 依赖项安装使用 pnpm install。不支持 Yarn Classic(yarn@1... 或 v1 锁文件):
请停止操作,并要求用户升级到 Yarn 4+,或明确迁移到 npm、pnpm 或 Bun。
不要更改 packageManager,也不要仅为影响检测或切换管理器而创建、替换或重新生成
锁文件。除非用户明确选择升级或迁移,否则应保留现有文件。使用 aspire start --non-interactive
启动 AppHost,而不是使用原始包管理器启动器。完整命令矩阵和解析器详情请参阅
references/typescript-authoring.md。
工作流阶段
1. SCAN → discover projects, services, dependencies, integration candidates
2. PROPOSE → resource graph + integration list, confirm with user
3. EDIT → wire AppHost, add ServiceDefaults + OTel + health checks
4. VALIDATE → aspire start --non-interactive → aspire wait <each resource>
5. DEACTIVATE → confirm clean start, hand off to aspire-orchestration
如需采用与上游完全一致的详细工作流,请在编辑前加载以下参考文档:
- apphost-wiring.md — 完整的 AppHost 接线工作流、API 查询、端点/参数模式、验证、解决方案更新和清理。
- docker-compose.md — docker-compose 迁移、配置文件、映像映射、端口、卷和
depends_on。 - full-solution-apphosts.md — 大型解决方案的分类处理、混合 SDK 边界、解决方案成员资格、ServiceDefaults 放置位置和旧版主机迁移。
- javascript-apps.md — JavaScript 资源选择、工作区/单体仓库包管理器处理、端口、脚本和 TS AppHost 包配置。
- opentelemetry.md — 为非 .NET 服务配置可选的 Node.js、Python 和 Go OpenTelemetry。
1. 扫描
遍历仓库并建立清单:
| 内容 | 方法 |
|---|---|
| .NET 项目 | find . -name '*.csproj' -not -path '*/bin/*' -not -path '*/obj/*' |
| Node 服务 | find . -name 'package.json' -not -path '*/node_modules/*' |
| Python 服务 | find . -name 'pyproject.toml' -o -name 'requirements.txt' |
| compose 中的容器依赖项 | docker-compose.yml、compose.yaml(Postgres?Redis?Rabbit?) |
| 连接字符串 | 在 appsettings*.json、.env*、config/* 中 grep Postgres、Redis、Mongo、RabbitMQ、Cosmos、ServiceBus |
| 集成包 | 每个项目运行 dotnet list package;检查 package.json 中的 dependencies |
| 现有端点 | launchSettings.json、next.config.js、vite.config.ts 中硬编码的端口 |
完整的启发式规则请参阅 references/scan-and-propose.md。
2. 提议
在编辑之前展示资源图。提出澄清问题:
- “我在
docker-compose.yml中看到了 Postgres——应该将其建模为AddPostgres('db'),还是使用 Azure Database for PostgreSQL?” - “你的 React 应用硬编码了
http://localhost:5000——要替换为 Aspire 服务发现(endpoint.url)吗?” - “你的 API 有一个
/admin端点——要将其从WithReference()中排除,以免使用方看到它吗?”
3. 编辑
应用提议的资源图。根据 AppHost 语言采用合适的编写方式。
4. 验证
aspire start --non-interactive --format Json
aspire wait <resource> # repeat for each declared resource
aspire describe --format Json # sanity check graph
完整的验证流程和恢复方法请参阅 references/validation.md。
5. 自动停用
在 aspire start 成功运行后,宣布:
✅ AppHost wired and validated. Handing off to aspire-orchestration for
day-to-day start/stop/wait. Aspireify is done.
集成发现目录
将检测到的服务映射到 Aspire 集成。完整目录请参阅 references/scan-and-propose.md。
| 检测到的服务 | C# | TS |
|---|---|---|
compose 中的 Postgres / Npgsql 包 | AddPostgres("pg").AddDatabase("db") | addPostgres('pg').addDatabase('db') |
compose 中的 Redis / StackExchange.Redis | AddRedis("cache") | addRedis('cache') |
| RabbitMQ | AddRabbitMQ("mq")(v7 客户端,支持发布-订阅追踪) | addRabbitMQ('mq') |
| MongoDB | AddMongoDB("mongo") | addMongoDB('mongo') |
| Cosmos DB | AddAzureCosmosDB("cosmos") | addAzureCosmosDB('cosmos') |
| Azure Service Bus | AddAzureServiceBus("sb") | addAzureServiceBus('sb') |
| Azure Cache for Redis(Entra) | AddAzureRedis("cache")(现已正式发布) | addAzureRedis('cache') |
| Next.js 前端 | AddNextJsApp("web", "./web") | addNextJsApp('web', '../web') |
| Vite SPA | AddViteApp("web", "./web") | addViteApp('web', '../web') |
| 普通 Node 应用 | AddNodeApp("api", "server.js") | addNodeApp('api', 'server.js') |
当前编写规则
| 规则 | 原因 |
|---|---|
在 TS 中使用统一的 withEnvironment(name, value) — 不要使用已弃用的按类型区分的帮助方法(withEnvironmentEndpoint、withEnvironmentParameter 等) | 一个 API 可处理所有类型的值;按类型区分的帮助方法已弃用 |
JS 前端优先使用 AddNextJsApp / AddViteApp,而非手动编写 Dockerfile | 提供一流的生命周期支持,并集成 PublishAs* |
JS 发布使用 PublishAsStaticWebsite / PublishAsNodeServer / PublishAsPackageScript | 取代手动编写的 Dockerfile;SPA → 静态网站,SSR Node → NodeServer,package-script SSR → PackageScript |
为前端资源添加 WithBrowserLogs(),以便在仪表板中查看浏览器控制台和屏幕截图 | Aspire.Hosting.Browsers 会在仪表板中呈现浏览器遥测数据 |
存在多个环境时,使用 WithComputeEnvironment(env) 将每个资源绑定到计算环境 | 多环境部署需要显式绑定 |
绝不要编辑 TS AppHost 中的 .aspire/modules/ | 该目录由生成器生成,手动修改会被覆盖。只编辑已配置的 apphost.mts(或旧版 apphost.ts) |
使用 WithEndpoint("name", e => ...) 更新端点 | 端点回调会更新现有端点,而不会因重复项而抛出异常 |
将管理端点标记为 ExcludeReferenceEndpoint = true | 防止消费者通过 WithReference() 获取管理 URL |
查询不熟悉的 API:aspire docs api search <query> --language csharp|typescript | 不要猜测重载或构建器链 |
使用上下文的 .Services / await ctx.services().getInteractionService() | .ServiceProvider 已过时,而单独调用 ctx.services() 只会返回服务访问器 |
对外部连接字符串使用 AddConnectionString | PublishAsConnectionString 已过时 |
提示用户前检查 IInteractionService.IsAvailable | 通过 CLI 调用的命令可能无法交互;对于仪表板和 CLI 输入,优先使用命令参数 |
将 WithTerminal() 视为实验性功能 | 抑制 ASPIRETERMINAL001;不要生成已移除的 TerminalOptions.Shell 或 TypeScript 维度选项 |
所有 Aspire SDK 和 Aspire.Hosting.* 包都使用同一发布系列 | 混用不同发布系列可能导致启动失败 |
| 将 GitHub Models 集成迁移到 Azure AI Foundry | Aspire.Hosting.GitHub.Models 已弃用,且不会出现在集成发现中 |
Redis 8 模块使用 WithModule(RedisModules.*) | 优先使用类型化的 JSON、Search、Bloom Filter 和 TimeSeries 常量,而非原始模块路径 |
托管的可执行文件/容器 Agent 使用 Foundry AsHostedAgent(...) | 当前 Azure AI Foundry 路径取代了已弃用的 GitHub Models |
C# 与 TS 快速参考
| 概念 | C# | TypeScript |
|---|---|---|
| 构建器 | var builder = DistributedApplication.CreateBuilder(args); | const builder = await createBuilder(); |
| 添加项目 | builder.AddProject<Projects.Api>("api")(SDK)或 AddProject("api", "../Api/Api.csproj") | await builder.addProject('api', '../Api/Api.csproj') |
| 设置环境变量(任意值类型) | .WithEnvironment("KEY", value) | .withEnvironment('KEY', value) ← 统一 API |
| 等待依赖项 | .WaitFor(db) | .waitFor(db) |
| 传递连接 | .WithReference(db) | .withReference(db) |
| 外部 HTTP | .WithExternalHttpEndpoints() | .withExternalHttpEndpoints() |
| 终结点表达式 | api.GetEndpoint("http") | api.getEndpoint('http').url / .host / .port |
| 构建并运行 | builder.Build().Run(); | await builder.build().run(); |
ServiceDefaults 配置
每个项目都应调用 builder.AddServiceDefaults();,以启用 OpenTelemetry、
运行状况检查和服务发现。添加对 Aspire.ServiceDefaults 项目的引用
(对于非单体仓库,使用 NuGet)。请参阅
references/service-defaults.md。
终结点和引用约定
// Public-facing API. Mark "admin" endpoint as not-for-consumers.
var api = builder.AddProject<Projects.Api>("api")
.WithExternalHttpEndpoints()
.WithEndpoint("admin", e => e.ExcludeReferenceEndpoint = true);
// Frontend wires the API via service discovery.
builder.AddNextJsApp("web", "./web")
.WithReference(api) // injects services__api__http and __https
.WaitFor(api)
.WithBrowserLogs(); // browser console + screenshots
验证与恢复
| 症状 | 操作 |
|---|---|
aspire start 因构建错误失败 | 修复代码,然后重新运行 aspire start |
| 编辑时出现文件锁错误 | 移交给 aspire-orchestration → aspire stop → 重试 |
aspire describe 未显示资源 | 重新运行 aspire describe --include-hidden;aspire ps 仅适用于 AppHost 级别 |
| TS AppHost 更改未生效 | 确认编辑的是已配置的 apphost.mts(或旧版 apphost.ts),而不是 .aspire/modules/ |
aspire start 输出混有其他内容的 JSON | 解析前去除非 JSON 行(#15843) |
完整流程见 references/validation.md。
移交规则
| 场景 | 移交至 |
|---|---|
| 尚未创建 AppHost 框架 | → aspire-init skill |
| 日常启动/停止/等待/重启 | → aspire-orchestration skill |
| 发布、部署、销毁、流水线步骤 | → aspire-deployment skill |
| 日志、追踪、指标、仪表板、浏览器日志检查 | → aspire-monitoring skill |
| 已部署应用(Azure/AKS)诊断 | → azure-diagnostics skill(azure-skills) |
关键规则
- 绝不覆盖现有文件——始终采用增补或合并的方式。
- 修改服务代码前先征求同意,尤其是 OpenTelemetry 和 ServiceDefaults 注入。
- 尊重现有项目结构——不要重组代码库。
- 如果遇到困难,使用
aspire doctor诊断环境问题。 - 绝不要在
WithEnvironment/withEnvironment中硬编码 URL——应传递终结点引用,例如api.GetEndpoint("http")或api.getEndpoint('http'),而不是字符串字面量。 - 绝不要使用
WithUrlForEndpoint/withUrlForEndpoint设置dev.localhostURL——该 API 仅用于仪表板显示标签;dev.localhost应配置在 AppHost 启动/配置文件中。
参考资料
- apphost-wiring.md — 详细的 AppHost 接线工作流和 API 查询模式
- docker-compose.md — Docker Compose 迁移模式
- full-solution-apphosts.md — 大型/完整解决方案的 AppHost 指南
- javascript-apps.md — JavaScript/TypeScript 应用和工作区处理
- opentelemetry.md — 非 .NET OpenTelemetry 设置
- scan-and-propose.md — 仓库扫描启发式规则和集成目录
- csharp-authoring.md — C# AppHost 模式
- typescript-authoring.md — TS AppHost 模式和等效 API
- service-defaults.md — 配置 OTel、运行状况检查和服务发现
- validation.md — 端到端验证和恢复
- aspire-13-5-breaking-changes.md — 13.5 引入的重大变更,以及受影响版本的修复方法