Aspire Orchestration
MANDATORY COMPLIANCE — This skill prevents agent self-harm in Aspire projects.
Violating these rules causes file locks, orphaned processes, and user frustration (#15801).
Prerequisites
| Requirement |
Install |
| .NET 10.0 SDK |
https://dotnet.microsoft.com/download |
| Aspire CLI (curl/PowerShell) |
curl -sSL https://aspire.dev/install.sh | bash |
| Aspire CLI (NativeAOT global tool, .NET 10) |
dotnet tool install -g Aspire.Cli |
Either install method works. The dotnet tool install path produces a NativeAOT binary
(instant startup, no JIT warmup) and is the recommended option when .NET 10 is already present.
Detection
Activate when ANY signal is present:
| Signal |
How to Detect |
Confidence |
| C# AppHost |
.csproj containing Aspire.AppHost.Sdk |
✅ Definitive |
| File-based C# AppHost |
apphost.cs or .cs file with #:sdk Aspire.AppHost.Sdk |
✅ Definitive |
| TypeScript AppHost |
apphost.ts file in project |
✅ Definitive |
| Aspire config |
aspire.config.json in project root |
High |
| Aspire settings |
.aspire/ directory present |
High |
| Generated TS modules |
.aspire/modules/ directory present |
High |
| Service defaults |
Aspire.ServiceDefaults in project references |
Medium |
See detection.md for detailed fingerprinting.
Safety Guardrails
| Situation |
✅ ALWAYS Do |
❌ NEVER Do |
| Start an Aspire app |
aspire start |
dotnet run on AppHost |
| Wait for resource ready |
aspire wait <resource> |
curl / HTTP polling loops |
| Code changed in a resource |
Prefer resource commands, runtime watch/HMR, dashboard actions, or IDE-managed debugging |
dotnet build against locked files |
| Task complete |
aspire stop |
Leave processes running |
| Check resource status |
aspire describe / aspire ps |
Manual process inspection |
| Working in git worktree |
aspire start --isolated |
aspire start without isolation |
| Running from AI agent |
Add --non-interactive to all commands |
Assuming interactive terminal |
| Editing unfamiliar API |
aspire docs search <topic> then aspire docs api search <query> for API reference |
Guessing API shape |
| C# AppHost API inspection |
Use dotnet-inspect skill (if available) for local symbols |
Guessing overloads or builder chains |
| Adding custom dashboard/resource commands |
aspire docs search "custom resource commands" first |
Inventing WithCommand patterns without docs |
| Installing Aspire support |
Use aspire add or aspire init |
dotnet workload install aspire (obsolete) |
See safety-guardrails.md for detailed rules and recovery patterns.
Default Workflow
- Confirm workspace is Aspire — identify the AppHost
aspire start (or aspire start --isolated in worktrees)
aspire wait <resource> before interacting with any resource
aspire describe to inspect state, then work
- If AppHost code changed, rerun
aspire start; if only one resource changed, prefer the resource's commands/watch/HMR/debug workflow
aspire stop when cleanup is explicitly requested or needed to release locks/ports
Quick Reference
| Task |
Command |
| Start app (agents) |
aspire start (background, preferred) |
| Start app (human) |
aspire run (foreground, dashboard) |
| Stop app |
aspire stop |
| Wait for resource |
aspire wait <resource> |
| Check status |
aspire ps or aspire describe |
| Show hidden resources (proxies, helpers, migrations) |
aspire ps --include-hidden / aspire describe --include-hidden |
| Resource operation |
aspire resource <resource-name> <command> such as stop, start, or rebuild when exposed |
| Create new project |
aspire new aspire-starter |
| Add Aspire to existing |
aspire init (then hand off to aspireify skill for wiring) |
| Add integration |
aspire add <package> |
| Discover integrations |
aspire integration list --format Json / aspire integration search <query> --format Json |
| Upgrade the CLI itself |
aspire update --self |
| Update project package refs |
aspire update (modifies project files — get user approval) |
| Restore generated files |
aspire restore |
| Environment maintenance |
aspire cache clear, aspire certs trust, aspire certs clean |
| Diagnose environment |
aspire doctor |
| Machine-readable output |
--format Json (supported: ps, describe, start) |
| Look up API reference |
aspire docs api search <query> --language csharp|typescript |
| Browse API entries |
aspire docs api list <scope> |
| Get API detail |
aspire docs api get <id> |
Error Handling
| Symptom |
Cause |
Action |
File lock errors during build (MSB3491, CS2012) |
Aspire is running and holds locks on bin/, obj/, and assemblies. |
Run aspire stop first, then rebuild or aspire start. Do NOT conclude the project has a permanent build failure. |
| "Port already in use" |
Previous instance running |
aspire stop, then aspire start |
| Resource not found |
App not started or name wrong |
aspire ps to check |
| Build errors in resource |
Code error, not Aspire issue |
Fix code, then use resource commands/watch/HMR/debug workflow or rerun aspire start if AppHost code changed |
| Environment issues |
Missing SDK or tools |
aspire doctor to diagnose |
JSON parse failure from aspire start |
Mixed human/JSON output (#15843) |
Strip non-JSON lines before parsing |
aspire wait rejects name |
Use displayName not name (#15842) |
Use displayName from aspire ps --format Json |
aspire ps hangs |
AppHost on breakpoint (#15576) |
Use timeout, check AppHost process |
aspire agent init fails |
Non-interactive terminal (#16264) |
Run from standard terminal |
| Docker daemon unavailable |
Container-backed resources fail to start |
Start Docker Desktop, then aspire start |
| Multiple AppHosts detected |
Wrong AppHost targeted |
Use --apphost <path> to specify explicitly |
🔒 File-Lock Recovery (MSB3491 / CS2012) — Always aspire stop First
When a build fails with error MSB3491: Could not write to output file ... or
error CS2012: Cannot open ... for writing, the project itself is healthy —
Aspire is running and holding file locks on the resource's output assemblies.
The recovery is always the same:
# ✅ Correct recovery sequence
aspire stop # release the locks
# ... then either rebuild / restart one resource if the resource exposes commands ...
aspire resource <name> rebuild # example: C# project resource with rebuild command
# ... or restart the whole AppHost ...
aspire start # if AppHost code changed or Aspire was already stopped
| ❌ NEVER do |
✅ ALWAYS do |
| Tell the user the project has a permanent build failure |
Recognize the lock as Aspire holding outputs and run aspire stop |
dotnet build again with locks held |
aspire stop first, then dotnet build (or prefer resource commands/watch/HMR/debug workflow) |
Delete bin/ / obj/ to "fix" the lock |
aspire stop — deletion may succeed but the next build relocks |
pkill dotnet or kill <PID> to free locks |
aspire stop — clean shutdown via the CLI, no orphans |
| Tell the user to "reboot" or "restart your machine" |
aspire stop — single command, instant fix |
The same rule applies to any "file in use", "cannot access the file", or
"another process is using" error during a build of an Aspire-managed resource.
Handoff Rules
| Scenario |
Route To |
AppHost wiring after aspire init (scan repo, add resources, ServiceDefaults/OTel) |
→ aspireify skill (../aspireify/SKILL.md) or project-local .agents/skills/aspireify/SKILL.md |
Browser logs (Aspire.Hosting.Browsers / WithBrowserLogs()) and dashboard authoring |
→ aspireify skill (code edits) and aspire-monitoring (discovery) |
Custom resource commands (WithCommand, ExecuteCommandResult, HttpCommandResultMode) |
→ aspireify skill |
Lifecycle hooks (SubscribeBeforeStart, SubscribeAfterResourcesCreated, BeforeStart pipeline phase) |
→ aspireify skill |
Endpoint authoring (WithEndpoint updates, ExcludeReferenceEndpoint flag) |
→ aspireify skill |
Deploy, publish, pipeline steps, aspire destroy |
→ aspire-deployment skill |
Logs, traces, metrics, dashboard, aspire dashboard run |
→ aspire-monitoring skill |
| Deployed app diagnostics |
→ azure-diagnostics skill (azure-skills) |
Runtime Settings And Environment
| Variable |
Default |
Purpose |
ASPIRE_ENABLE_CONTAINER_TUNNEL |
true |
Container tunnel provides uniform host connectivity across Docker Desktop, Docker Engine, and Podman. Set to false to opt out. |
ASPIRE_ENVIRONMENT |
unset |
Selects the environment-specific config profile — controls which appsettings.{environment}.json is loaded and which environment is reported in dashboard telemetry. |
ASPIRE_DCP_USE_DEVELOPER_CERTIFICATE |
true |
The Aspire trusted developer certificate is used by DCP on Windows. Set to false to opt out. |
features.defaultWatchEnabled |
false unless configured |
Enables Aspire default watch for supported C# and TypeScript AppHosts. Do not treat this as per-resource rebuild, restart, or hot reload for resource source changes. |
TypeScript AppHost Note
Detection covers TS AppHosts (apphost.ts), but all TS AppHost authoring is delegated to aspireify.
Current rules to apply when handing off:
| Rule |
Why |
Prefer unified withEnvironment(name, value) over deprecated per-kind helpers (withEnvironmentEndpoint, withEnvironmentParameter, withEnvironmentConnectionString, withEnvironmentExpression, withEnvironmentFromOutput, withEnvironmentFromKeyVaultSecret) |
Per-kind helpers are deprecated — single API now handles all value types |
Never edit .aspire/modules/ directly |
Generated; use aspire add <package> to regenerate and aspire restore to recover missing files |
Use aspire docs api search <query> --language typescript for API lookup |
TS surface differs from C# |
Skill Routing — In-Plugin Sibling Skills
After aspire init drops a skeleton AppHost + aspire.config.json, route AppHost wiring
(scan repo → propose resource graph → edit AppHost → wire Aspire.ServiceDefaults / OTel →
validate via aspire start) to the in-plugin aspireify skill: ../aspireify/SKILL.md.
For first-run flows that only need the skeleton drop, see the in-plugin aspire-init skill:
../aspire-init/SKILL.md. This orchestration skill stays focused
on lifecycle (start/stop/wait/restart) and never edits AppHost code itself.
Project-Local Skill Precedence
If .agents/skills/aspire/SKILL.md exists (from aspire agent init), defer to it for:
C# AppHost editing, TS AppHost editing, Playwright handoff, investigation workflows.
Safety guardrails from this plugin ALWAYS apply.
If .agents/skills/aspireify/SKILL.md exists project-locally (installed by aspire init in
current Aspire), warn the user that a project-local aspireify skill is present and defer to it
for AppHost wiring instead of the in-plugin sibling. Same precedence rule as the project-local
aspire skill above: project-local wins, plugin guardrails still apply.
References
- safety-guardrails.md — Detailed rules and recovery patterns
- detection.md — Project fingerprinting
- app-commands.md — App lifecycle and bootstrap commands
- resource-management.md — Resource wait, restart, and operations
- agent-workflows.md — Common agent investigation, integration, TypeScript, and handoff workflows
Source: MarcelMichau/fake-survey-generator — distributed by TomeVault.
1---2name: marcelmichau-fake-survey-generator-fake-survey-generator3description: Aspire Orchestration4---56# Aspire Orchestration78> **MANDATORY COMPLIANCE** — This skill prevents agent self-harm in Aspire projects.9> Violating these rules causes file locks, orphaned processes, and user frustration ([#15801](https://github.com/microsoft/aspire/issues/15801)).1011## Prerequisites1213| Requirement | Install |14|-------------|---------|15| .NET 10.0 SDK | https://dotnet.microsoft.com/download |16| Aspire CLI (curl/PowerShell) | `curl -sSL https://aspire.dev/install.sh \| bash` |17| Aspire CLI (NativeAOT global tool, .NET 10) | `dotnet tool install -g Aspire.Cli` |1819Either install method works. The `dotnet tool install` path produces a NativeAOT binary20(instant startup, no JIT warmup) and is the recommended option when .NET 10 is already present.2122## Detection2324Activate when ANY signal is present:2526| Signal | How to Detect | Confidence |27|--------|---------------|------------|28| C# AppHost | `.csproj` containing `Aspire.AppHost.Sdk` | ✅ Definitive |29| File-based C# AppHost | `apphost.cs` or `.cs` file with `#:sdk Aspire.AppHost.Sdk` | ✅ Definitive |30| TypeScript AppHost | `apphost.ts` file in project | ✅ Definitive |31| Aspire config | `aspire.config.json` in project root | High |32| Aspire settings | `.aspire/` directory present | High |33| Generated TS modules | `.aspire/modules/` directory present | High |34| Service defaults | `Aspire.ServiceDefaults` in project references | Medium |3536See [detection.md](references/detection.md) for detailed fingerprinting.3738## Safety Guardrails3940| Situation | ✅ ALWAYS Do | ❌ NEVER Do |41|-----------|-------------|------------|42| Start an Aspire app | `aspire start` | `dotnet run` on AppHost |43| Wait for resource ready | `aspire wait <resource>` | `curl` / HTTP polling loops |44| Code changed in a resource | Prefer resource commands, runtime watch/HMR, dashboard actions, or IDE-managed debugging | `dotnet build` against locked files |45| Task complete | `aspire stop` | Leave processes running |46| Check resource status | `aspire describe` / `aspire ps` | Manual process inspection |47| Working in git worktree | `aspire start --isolated` | `aspire start` without isolation |48| Running from AI agent | Add `--non-interactive` to all commands | Assuming interactive terminal |49| Editing unfamiliar API | `aspire docs search <topic>` then `aspire docs api search <query>` for API reference | Guessing API shape |50| C# AppHost API inspection | Use `dotnet-inspect` skill (if available) for local symbols | Guessing overloads or builder chains |51| Adding custom dashboard/resource commands | `aspire docs search "custom resource commands"` first | Inventing `WithCommand` patterns without docs |52| Installing Aspire support | Use `aspire add` or `aspire init` | ~~`dotnet workload install aspire`~~ (obsolete) |5354See [safety-guardrails.md](references/safety-guardrails.md) for detailed rules and recovery patterns.5556## Default Workflow57581. Confirm workspace is Aspire — identify the AppHost592. `aspire start` (or `aspire start --isolated` in worktrees)603. `aspire wait <resource>` before interacting with any resource614. `aspire describe` to inspect state, then work625. If AppHost code changed, rerun `aspire start`; if only one resource changed, prefer the resource's commands/watch/HMR/debug workflow636. `aspire stop` when cleanup is explicitly requested or needed to release locks/ports6465## Quick Reference6667| Task | Command |68|------|---------|69| Start app (agents) | `aspire start` (background, preferred) |70| Start app (human) | `aspire run` (foreground, dashboard) |71| Stop app | `aspire stop` |72| Wait for resource | `aspire wait <resource>` |73| Check status | `aspire ps` or `aspire describe` |74| Show hidden resources (proxies, helpers, migrations) | `aspire ps --include-hidden` / `aspire describe --include-hidden` |75| Resource operation | `aspire resource <resource-name> <command>` such as `stop`, `start`, or `rebuild` when exposed |76| Create new project | `aspire new aspire-starter` |77| Add Aspire to existing | `aspire init` (then hand off to `aspireify` skill for wiring) |78| Add integration | `aspire add <package>` |79| Discover integrations | `aspire integration list --format Json` / `aspire integration search <query> --format Json` |80| Upgrade the CLI itself | `aspire update --self` |81| Update project package refs | `aspire update` (modifies project files — get user approval) |82| Restore generated files | `aspire restore` |83| Environment maintenance | `aspire cache clear`, `aspire certs trust`, `aspire certs clean` |84| Diagnose environment | `aspire doctor` |85| Machine-readable output | `--format Json` (supported: `ps`, `describe`, `start`) |86| Look up API reference | `aspire docs api search <query> --language csharp\|typescript` |87| Browse API entries | `aspire docs api list <scope>` |88| Get API detail | `aspire docs api get <id>` |8990## Error Handling9192| Symptom | Cause | Action |93|---------|-------|--------|94| **File lock errors during build (`MSB3491`, `CS2012`)** | **Aspire is running and holds locks on `bin/`, `obj/`, and assemblies.** | **Run `aspire stop` first**, then rebuild or `aspire start`. Do NOT conclude the project has a permanent build failure. |95| "Port already in use" | Previous instance running | `aspire stop`, then `aspire start` |96| Resource not found | App not started or name wrong | `aspire ps` to check |97| Build errors in resource | Code error, not Aspire issue | Fix code, then use resource commands/watch/HMR/debug workflow or rerun `aspire start` if AppHost code changed |98| Environment issues | Missing SDK or tools | `aspire doctor` to diagnose |99| JSON parse failure from `aspire start` | Mixed human/JSON output ([#15843](https://github.com/microsoft/aspire/issues/15843)) | Strip non-JSON lines before parsing |100| `aspire wait` rejects name | Use `displayName` not `name` ([#15842](https://github.com/microsoft/aspire/issues/15842)) | Use `displayName` from `aspire ps --format Json` |101| `aspire ps` hangs | AppHost on breakpoint ([#15576](https://github.com/microsoft/aspire/issues/15576)) | Use timeout, check AppHost process |102| `aspire agent init` fails | Non-interactive terminal ([#16264](https://github.com/microsoft/aspire/issues/16264)) | Run from standard terminal |103| Docker daemon unavailable | Container-backed resources fail to start | Start Docker Desktop, then `aspire start` |104| Multiple AppHosts detected | Wrong AppHost targeted | Use `--apphost <path>` to specify explicitly |105106### 🔒 File-Lock Recovery (MSB3491 / CS2012) — Always `aspire stop` First107108When a build fails with `error MSB3491: Could not write to output file ...` or109`error CS2012: Cannot open ... for writing`, the project itself is healthy —110**Aspire is running and holding file locks** on the resource's output assemblies.111The recovery is always the same:112113```bash114# ✅ Correct recovery sequence115aspire stop # release the locks116# ... then either rebuild / restart one resource if the resource exposes commands ...117aspire resource <name> rebuild # example: C# project resource with rebuild command118# ... or restart the whole AppHost ...119aspire start # if AppHost code changed or Aspire was already stopped120```121122| ❌ NEVER do | ✅ ALWAYS do |123|------------|-------------|124| Tell the user the project has a permanent build failure | Recognize the lock as Aspire holding outputs and run `aspire stop` |125| `dotnet build` again with locks held | `aspire stop` first, then `dotnet build` (or prefer resource commands/watch/HMR/debug workflow) |126| Delete `bin/` / `obj/` to "fix" the lock | `aspire stop` — deletion may succeed but the next build relocks |127| `pkill dotnet` or `kill <PID>` to free locks | `aspire stop` — clean shutdown via the CLI, no orphans |128| Tell the user to "reboot" or "restart your machine" | `aspire stop` — single command, instant fix |129130The same rule applies to any "file in use", "cannot access the file", or131"another process is using" error during a build of an Aspire-managed resource.132133## Handoff Rules134135| Scenario | Route To |136|----------|----------|137| AppHost wiring after `aspire init` (scan repo, add resources, ServiceDefaults/OTel) | → `aspireify` skill ([`../aspireify/SKILL.md`](../aspireify/SKILL.md)) or project-local `.agents/skills/aspireify/SKILL.md` |138| Browser logs (`Aspire.Hosting.Browsers` / `WithBrowserLogs()`) and dashboard authoring | → `aspireify` skill (code edits) and `aspire-monitoring` (discovery) |139| Custom resource commands (`WithCommand`, `ExecuteCommandResult`, `HttpCommandResultMode`) | → `aspireify` skill |140| Lifecycle hooks (`SubscribeBeforeStart`, `SubscribeAfterResourcesCreated`, BeforeStart pipeline phase) | → `aspireify` skill |141| Endpoint authoring (`WithEndpoint` updates, `ExcludeReferenceEndpoint` flag) | → `aspireify` skill |142| Deploy, publish, pipeline steps, `aspire destroy` | → `aspire-deployment` skill |143| Logs, traces, metrics, dashboard, `aspire dashboard run` | → `aspire-monitoring` skill |144| Deployed app diagnostics | → `azure-diagnostics` skill (azure-skills) |145146## Runtime Settings And Environment147148| Variable | Default | Purpose |149|----------|---------|---------|150| `ASPIRE_ENABLE_CONTAINER_TUNNEL` | `true` | Container tunnel provides uniform host connectivity across Docker Desktop, Docker Engine, and Podman. Set to `false` to opt out. |151| `ASPIRE_ENVIRONMENT` | unset | Selects the environment-specific config profile — controls which `appsettings.{environment}.json` is loaded and which environment is reported in dashboard telemetry. |152| `ASPIRE_DCP_USE_DEVELOPER_CERTIFICATE` | `true` | The Aspire trusted developer certificate is used by DCP on Windows. Set to `false` to opt out. |153| `features.defaultWatchEnabled` | false unless configured | Enables Aspire default watch for supported C# and TypeScript AppHosts. Do not treat this as per-resource rebuild, restart, or hot reload for resource source changes. |154155## TypeScript AppHost Note156157Detection covers TS AppHosts (`apphost.ts`), but **all TS AppHost authoring is delegated to `aspireify`**.158Current rules to apply when handing off:159160| Rule | Why |161|------|-----|162| Prefer unified `withEnvironment(name, value)` over deprecated per-kind helpers (`withEnvironmentEndpoint`, `withEnvironmentParameter`, `withEnvironmentConnectionString`, `withEnvironmentExpression`, `withEnvironmentFromOutput`, `withEnvironmentFromKeyVaultSecret`) | Per-kind helpers are deprecated — single API now handles all value types |163| Never edit `.aspire/modules/` directly | Generated; use `aspire add <package>` to regenerate and `aspire restore` to recover missing files |164| Use `aspire docs api search <query> --language typescript` for API lookup | TS surface differs from C# |165166## Skill Routing — In-Plugin Sibling Skills167168After `aspire init` drops a skeleton AppHost + `aspire.config.json`, route AppHost wiring169(scan repo → propose resource graph → edit AppHost → wire `Aspire.ServiceDefaults` / OTel →170validate via `aspire start`) to the in-plugin **aspireify** skill: [`../aspireify/SKILL.md`](../aspireify/SKILL.md).171For first-run flows that only need the skeleton drop, see the in-plugin **aspire-init** skill:172[`../aspire-init/SKILL.md`](../aspire-init/SKILL.md). This orchestration skill stays focused173on lifecycle (start/stop/wait/restart) and never edits AppHost code itself.174175## Project-Local Skill Precedence176177If `.agents/skills/aspire/SKILL.md` exists (from `aspire agent init`), defer to it for:178C# AppHost editing, TS AppHost editing, Playwright handoff, investigation workflows.179Safety guardrails from this plugin ALWAYS apply.180181If `.agents/skills/aspireify/SKILL.md` exists project-locally (installed by `aspire init` in182current Aspire), **warn the user** that a project-local aspireify skill is present and **defer to it**183for AppHost wiring instead of the in-plugin sibling. Same precedence rule as the project-local184`aspire` skill above: project-local wins, plugin guardrails still apply.185186## References187188- [safety-guardrails.md](references/safety-guardrails.md) — Detailed rules and recovery patterns189- [detection.md](references/detection.md) — Project fingerprinting190- [app-commands.md](references/app-commands.md) — App lifecycle and bootstrap commands191- [resource-management.md](references/resource-management.md) — Resource wait, restart, and operations192- [agent-workflows.md](references/agent-workflows.md) — Common agent investigation, integration, TypeScript, and handoff workflows193194---195> Source: [MarcelMichau/fake-survey-generator](https://github.com/MarcelMichau/fake-survey-generator) — distributed by [TomeVault](https://tomevault.io).196<!-- tomevault:4.0:skill_md:2026-07-07 -->