Reorganised the folders.
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
---
|
||||
name: aspire-orchestration
|
||||
description: >-
|
||||
**WORKFLOW SKILL** — Manage Aspire AppHost lifecycle and recover from file locks,
|
||||
port conflicts, and orphaned processes. WHEN: "start my Aspire app", "aspire start",
|
||||
"aspire stop", "aspire wait", "restart the API service", "file lock error",
|
||||
"MSB3491", "CS2012", "port already in use", "upgrade Aspire CLI", "aspire update --self",
|
||||
"proxies missing in aspire ps", "--include-hidden", "aspire integration list",
|
||||
"aspire integration search", "default watch", "hot reload". INVOKES: aspire CLI
|
||||
(start, stop, wait, ps, resource, integration, add, init, doctor, update, restore).
|
||||
FOR SINGLE OPERATIONS: Run the aspire CLI command directly.
|
||||
license: MIT
|
||||
metadata:
|
||||
author: Microsoft
|
||||
version: "0.0.1"
|
||||
---
|
||||
|
||||
# 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](https://github.com/microsoft/aspire/issues/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](references/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](references/safety-guardrails.md) for detailed rules and recovery patterns.
|
||||
|
||||
## Default Workflow
|
||||
|
||||
1. Confirm workspace is Aspire — identify the AppHost
|
||||
2. `aspire start` (or `aspire start --isolated` in worktrees)
|
||||
3. `aspire wait <resource>` before interacting with any resource
|
||||
4. `aspire describe` to inspect state, then work
|
||||
5. If AppHost code changed, rerun `aspire start`; if only one resource changed, prefer the resource's commands/watch/HMR/debug workflow
|
||||
6. `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](https://github.com/microsoft/aspire/issues/15843)) | Strip non-JSON lines before parsing |
|
||||
| `aspire wait` rejects name | Use `displayName` not `name` ([#15842](https://github.com/microsoft/aspire/issues/15842)) | Use `displayName` from `aspire ps --format Json` |
|
||||
| `aspire ps` hangs | AppHost on breakpoint ([#15576](https://github.com/microsoft/aspire/issues/15576)) | Use timeout, check AppHost process |
|
||||
| `aspire agent init` fails | Non-interactive terminal ([#16264](https://github.com/microsoft/aspire/issues/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:
|
||||
|
||||
```bash
|
||||
# ✅ 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`](../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`](../aspireify/SKILL.md).
|
||||
For first-run flows that only need the skeleton drop, see the in-plugin **aspire-init** skill:
|
||||
[`../aspire-init/SKILL.md`](../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](references/safety-guardrails.md) — Detailed rules and recovery patterns
|
||||
- [detection.md](references/detection.md) — Project fingerprinting
|
||||
- [app-commands.md](references/app-commands.md) — App lifecycle and bootstrap commands
|
||||
- [resource-management.md](references/resource-management.md) — Resource wait, restart, and operations
|
||||
- [agent-workflows.md](references/agent-workflows.md) — Common agent investigation, integration, TypeScript, and handoff workflows
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
# Aspire Agent Workflows
|
||||
|
||||
Use these patterns when a task needs investigation or orchestration rather than a one-off command lookup.
|
||||
|
||||
## Scenario: I Am In A Worktree And Need A Safe Background Run
|
||||
|
||||
Start the AppHost with `aspire start` so the CLI manages background execution. In git worktrees, use `--isolated` to avoid port conflicts and shared local state:
|
||||
|
||||
```bash
|
||||
aspire start --isolated
|
||||
```
|
||||
|
||||
If the next step depends on one resource, wait for it explicitly:
|
||||
|
||||
```bash
|
||||
aspire start --isolated
|
||||
aspire wait myapi
|
||||
```
|
||||
|
||||
Keep these points in mind:
|
||||
|
||||
- In a git worktree, rerun `aspire start --isolated` whenever AppHost changes need to be picked up.
|
||||
- Outside worktrees, rerun `aspire start`.
|
||||
- Avoid `aspire run` in normal agent workflows because it blocks the terminal.
|
||||
|
||||
## Scenario: I Changed Code While The AppHost Is Running
|
||||
|
||||
Classify the change before restarting anything:
|
||||
|
||||
1. If the AppHost model, AppHost code, integrations, resource definitions, or AppHost-level configuration changed, rerun the same AppHost start command. In a git worktree, use `aspire start --isolated`.
|
||||
2. If one resource's implementation changed, keep the AppHost running and use a resource-specific workflow.
|
||||
3. If an IDE is managing debugging or hot reload, defer to the IDE and avoid overlapping Aspire CLI restart, rebuild, or watch behavior.
|
||||
|
||||
Use resource commands when the running AppHost already knows about the resource and only that resource needs to be operated on. Choose the resource command path that matches the resource.
|
||||
|
||||
For a C# project resource that exposes rebuild:
|
||||
|
||||
```bash
|
||||
aspire resource api rebuild
|
||||
aspire wait api
|
||||
```
|
||||
|
||||
For a resource that needs a process restart and does not have a better resource-specific command:
|
||||
|
||||
```bash
|
||||
aspire resource api stop
|
||||
aspire resource api start
|
||||
aspire wait api
|
||||
```
|
||||
|
||||
Keep these points in mind:
|
||||
|
||||
- Use `aspire resource <resource-name> <command>` as the command shape.
|
||||
- Use `aspire resource <resource-name> rebuild` when a C# project resource exposes rebuild and you need the resource to pick up compiled changes.
|
||||
- Use runtime or framework-native hot reload/watch for resource implementation loops when that workflow is available.
|
||||
- For frontend resources, remember that frameworks such as Vite, Next.js, and similar client-side JavaScript stacks often enable hot module replacement (HMR) by default. If HMR is already applying the change through the resource's dev server, do not force a resource or AppHost restart.
|
||||
- Do not restart the whole AppHost just because one resource changed or one resource needs to be rebuilt.
|
||||
- Aspire default watch is controlled by `features.defaultWatchEnabled`; use it for AppHost-centered CLI watch behavior, not as a replacement for resource-specific or IDE hot reload workflows.
|
||||
|
||||
## Scenario: Something Is Wrong, But Do Not Edit Code Yet
|
||||
|
||||
Inspect the live app before editing code:
|
||||
|
||||
1. `aspire describe` to check resource state.
|
||||
2. `aspire otel logs <resource>` to inspect structured logs. Add `--search "<term>"` to filter by keyword.
|
||||
3. `aspire logs <resource>` to inspect console output. Add `--search "<term>"` to filter by keyword.
|
||||
4. `aspire otel traces <resource>` to follow cross-service activity. Add `--search "<term>"` to narrow results.
|
||||
5. `aspire export` when you need a zipped telemetry snapshot for deeper analysis or handoff.
|
||||
|
||||
## Scenario: I Need To Add An Integration, Understand An API, Or Add A Custom Command Safely
|
||||
|
||||
Use integration search to find the package when needed, then use the docs commands for the workflow and the API reference commands if you need the concrete API entry:
|
||||
|
||||
```bash
|
||||
aspire integration search postgres
|
||||
aspire docs search postgres
|
||||
aspire docs get <slug>
|
||||
aspire docs api search postgres --language csharp
|
||||
aspire docs api get <id>
|
||||
aspire add <package>
|
||||
```
|
||||
|
||||
For dashboard or custom resource commands, use docs for the pattern and API docs for the specific entry:
|
||||
|
||||
```bash
|
||||
aspire docs search "custom resource commands"
|
||||
aspire docs get custom-resource-commands
|
||||
aspire docs api search WithCommand --language csharp
|
||||
```
|
||||
|
||||
Keep these points in mind:
|
||||
|
||||
- Read the docs before editing the AppHost so the implementation follows a documented Aspire pattern instead of guessing the workflow.
|
||||
- Use `aspire integration list` when the user asks to discover available integrations before changing the AppHost, or `aspire integration search <query>` when the package ID is unknown.
|
||||
- Use `aspire docs api` when you need the C# or TypeScript reference entry for the exact API you are about to call.
|
||||
- If the AppHost is C# and you need to understand local overloads or builder chains, use the `dotnet-inspect` skill if it is available after checking the Aspire API reference.
|
||||
- After adding an integration, restart with `aspire start` so the updated AppHost takes effect.
|
||||
|
||||
## Scenario: The AppHost Is TypeScript And Generated APIs Matter
|
||||
|
||||
If the AppHost is `apphost.ts`, the `.aspire/modules/` directory contains generated TypeScript modules that expose Aspire APIs.
|
||||
|
||||
- Do not edit `.aspire/modules/` directly.
|
||||
- Use `aspire add <package>` to regenerate the available APIs when adding integrations.
|
||||
- Use `aspire restore` if `.aspire/modules/` disappeared after a pull, clean, or branch switch.
|
||||
- Inspect `.aspire/modules/aspire.ts` after regeneration or restore to see the newly available APIs.
|
||||
|
||||
## Scenario: I Need Secrets, Deployment, Or A Playwright Handoff
|
||||
|
||||
Use `aspire secret` for AppHost user secrets, especially connection strings and passwords:
|
||||
|
||||
```bash
|
||||
aspire secret set Parameters:postgres-password MySecretValue
|
||||
aspire secret list
|
||||
```
|
||||
|
||||
Use `aspire publish` and `aspire deploy` for full deployment work, or `aspire do <step>` when the user only wants one named pipeline step such as seeding data or pushing containers.
|
||||
|
||||
If Playwright CLI is configured in the environment, use Aspire to discover the endpoint first and let Playwright use that discovered URL afterward. When multiple frontends exist or the URL needs to be passed to another tool, prefer `aspire describe --format Json` before the Playwright handoff.
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
# App Commands
|
||||
|
||||
Use this when the task is about app-level lifecycle, bootstrap, or AppHost-wide maintenance.
|
||||
|
||||
## Start The App Safely In The Background
|
||||
|
||||
```bash
|
||||
aspire start
|
||||
aspire start --isolated
|
||||
aspire stop
|
||||
```
|
||||
|
||||
- Use `aspire start` for normal background AppHost execution.
|
||||
- In git worktrees or when another local instance may already be running, use `aspire start --isolated`.
|
||||
- To restart after AppHost changes, rerun the same start command.
|
||||
- Use `aspire stop` when cleanup is explicitly requested, ports/locks need to be released, or you are finished with a started instance that the user did not ask to keep running.
|
||||
- Avoid `aspire run` in agent workflows — it blocks the terminal.
|
||||
|
||||
### `aspire run` vs `aspire start`
|
||||
|
||||
| Command | Mode | Use Case |
|
||||
|---------|------|----------|
|
||||
| `aspire run` | Foreground (interactive) | Human developer at terminal |
|
||||
| `aspire start` | Background (detached) | **AI agents — always prefer** |
|
||||
| `aspire run --detach` | Background | Alternative to `aspire start` |
|
||||
|
||||
## Create A New Aspire App Or Add Aspire To An Existing App
|
||||
|
||||
```bash
|
||||
aspire new
|
||||
aspire init
|
||||
aspire init --language typescript
|
||||
```
|
||||
|
||||
- Use `aspire new` when creating a brand-new Aspire app from scratch.
|
||||
- Use `aspire init` when adding Aspire to an existing application.
|
||||
|
||||
## After `aspire init` — Hand Off to `aspireify`
|
||||
|
||||
`aspire init` drops a minimal AppHost skeleton + AppHost configuration into the
|
||||
repo and installs the **`aspireify`** agent skill alongside it. `aspire init` itself does not
|
||||
wire resources, projects, or integrations. Hand off the wiring step to:
|
||||
|
||||
1. The in-plugin sibling skill: [`../../aspireify/SKILL.md`](../../aspireify/SKILL.md), or
|
||||
2. The project-local `.agents/skills/aspireify/SKILL.md` if `aspire init` installed it
|
||||
(project-local wins — defer to it and warn the user).
|
||||
|
||||
The aspireify workflow:
|
||||
|
||||
1. **Scan** the repository — discover .NET projects, Node.js apps, Python/Go services, docker-compose files
|
||||
2. **Present findings** — confirm with user which services to include
|
||||
3. **Wire the AppHost** — add resources using 3-tier API preference:
|
||||
- Tier 1: First-party `Aspire.Hosting.*` (e.g., `AddPostgres`, `AddRedis`, `AddViteApp`, `AddNextJsApp`)
|
||||
- Tier 2: Community Toolkit `CommunityToolkit.Aspire.Hosting.*` (e.g., `AddGolangApp`)
|
||||
- Tier 3: Raw fallbacks (`AddExecutable`, `AddDockerfile`, `AddContainer`)
|
||||
4. **Configure dependencies** — ServiceDefaults for .NET, OTel for non-.NET
|
||||
5. **Validate** — `aspire start` until all resources are healthy
|
||||
|
||||
### Key Init Rules
|
||||
|
||||
- **Never install the obsolete Aspire workload** (`dotnet workload install aspire`)
|
||||
- **Never change the repo's .NET SDK version** (don't modify root `global.json`)
|
||||
- **Never change existing project target frameworks** (older TFMs work with newer AppHost)
|
||||
- **Always use `aspire docs search` before writing AppHost code** — don't guess APIs
|
||||
- **Never hardcode URLs** — use endpoint references (`WithReference`, `WithEnvironment` with expressions)
|
||||
- **Never overwrite existing files** — augment and merge
|
||||
- **Adapt the AppHost to the app**, not the other way around
|
||||
|
||||
### Init Config: `aspire.config.json`
|
||||
|
||||
Read `aspire.config.json` at repo root for init context:
|
||||
|
||||
| Field | Values | Meaning |
|
||||
|-------|--------|---------|
|
||||
| `appHost.language` | `"typescript/nodejs"` or `"csharp"` | AppHost syntax to use |
|
||||
| `appHost.path` | Path to AppHost file/dir | Where to edit |
|
||||
|
||||
C# has two sub-modes:
|
||||
- **Single-file**: `appHost.path` → `apphost.cs` (uses `#:sdk` directive)
|
||||
- **Full project**: `appHost.path` → directory with `.csproj` + `Program.cs`
|
||||
|
||||
## Find The Right AppHost Or Refresh AppHost-Wide Support
|
||||
|
||||
```bash
|
||||
aspire ps
|
||||
aspire integration list --format Json
|
||||
aspire integration search <query> --format Json
|
||||
aspire add <package>
|
||||
aspire update --self # upgrades the Aspire CLI itself (NativeAOT global tool or curl install)
|
||||
aspire update # updates project package references / aspire.config.json
|
||||
aspire restore
|
||||
```
|
||||
|
||||
- Use `aspire ps` first to discover which AppHost is already running.
|
||||
- Use `aspire integration list --format Json` and `aspire integration search <query> --format Json` for read-only integration discovery.
|
||||
- Use `aspire add <package>` to add integrations and regenerate AppHost APIs when you are ready to mutate the AppHost.
|
||||
- Use **`aspire update --self`** to upgrade the Aspire CLI itself — the safe, no-side-effect upgrade path agents can run unattended.
|
||||
- Use **`aspire update` (no `--self`)** to refresh AppHost package references and bump pinned versions in `aspire.config.json`. This **modifies project files** — get user approval before running unattended (CI / agent flows).
|
||||
- Use `aspire restore` after pulls, cleans, or missing generated files.
|
||||
- Use `--apphost <path>` when the workspace has multiple AppHosts. The CLI's global config validates configured AppHost paths to catch typos early.
|
||||
|
||||
## Key Rules
|
||||
|
||||
- **Never install the obsolete Aspire workload** (`dotnet workload install aspire`). Use `aspire add`, `aspire init`, or `aspire new` instead.
|
||||
- **Never edit `.aspire/modules/` directly** in TypeScript AppHosts. Use `aspire add <package>` to regenerate APIs, `aspire restore` if files are missing.
|
||||
- For unfamiliar C# AppHost APIs, use `aspire docs search` as primary reference. If the `dotnet-inspect` skill is available, use it to inspect local symbols and overloads — but keep docs as the source of truth.
|
||||
- For custom dashboard or resource commands (`WithCommand`), always run `aspire docs search "custom resource commands"` before implementing.
|
||||
|
||||
## Look Up API Reference Before Editing AppHost Code
|
||||
|
||||
```bash
|
||||
aspire docs search <query>
|
||||
aspire docs get <slug>
|
||||
aspire docs api search <query> --language csharp
|
||||
aspire docs api search <query> --language typescript
|
||||
aspire docs api list <scope>
|
||||
aspire docs api get <id>
|
||||
```
|
||||
|
||||
- Use `aspire docs search` and `aspire docs get` for workflow guidance and documented patterns.
|
||||
- Use `aspire docs api search` when you need the C# or TypeScript API reference entry for a resource builder, extension method, or member.
|
||||
- Use `aspire docs api list <scope>` to browse children under a language, package, module, type, or symbol.
|
||||
- Always specify `--language csharp` or `--language typescript` to get the correct API surface.
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
# Detection — Recognizing Aspire Projects
|
||||
|
||||
> **Purpose**: How to identify that a project uses Aspire, and which project is the AppHost.
|
||||
|
||||
## Detection Signals
|
||||
|
||||
### 1. C# AppHost (Definitive — Strongest Signal)
|
||||
|
||||
Look for `.csproj` files containing the Aspire AppHost SDK reference:
|
||||
|
||||
```xml
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="10.0.0" />
|
||||
<!-- ... -->
|
||||
</Project>
|
||||
```
|
||||
|
||||
**Detection method**: Search for `Aspire.AppHost.Sdk` in `.csproj` files:
|
||||
|
||||
```bash
|
||||
grep -rl "Aspire.AppHost.Sdk" --include="*.csproj" .
|
||||
```
|
||||
|
||||
This is the **definitive signal** — if a `.csproj` contains this SDK reference, it is an Aspire AppHost project. All Aspire CLI commands should target this project's directory.
|
||||
|
||||
### 1b. File-Based C# AppHost (Definitive)
|
||||
|
||||
Single-file C# AppHosts use `apphost.cs` (or similar `.cs` files) with SDK directives instead of a `.csproj`:
|
||||
|
||||
```cs
|
||||
#:sdk Aspire.AppHost.Sdk
|
||||
#:property IsAspireHost=true
|
||||
|
||||
var builder = DistributedApplication.CreateBuilder(args);
|
||||
// ...
|
||||
```
|
||||
|
||||
**Detection method**: Search for `apphost.cs` or `.cs` files containing `#:sdk Aspire.AppHost.Sdk`:
|
||||
|
||||
```bash
|
||||
find . -name "apphost.cs" -not -path "*/node_modules/*"
|
||||
grep -rl "#:sdk Aspire.AppHost.Sdk" --include="*.cs" .
|
||||
```
|
||||
|
||||
File-based AppHosts are run the same way: `aspire start` (never `dotnet apphost.cs` directly).
|
||||
|
||||
### 2. TypeScript AppHost (Definitive)
|
||||
|
||||
Look for an `apphost.ts` file in the project:
|
||||
|
||||
```bash
|
||||
find . -name "apphost.ts" -not -path "*/node_modules/*"
|
||||
```
|
||||
|
||||
A TypeScript AppHost uses the `@aspire/apphost` package and defines resources programmatically in TypeScript instead of C#.
|
||||
|
||||
### 3. `.aspire/modules/` Directory (High Confidence)
|
||||
|
||||
Aspire generates a `.aspire/modules/` directory for TypeScript AppHost support files. Its presence strongly indicates an Aspire project:
|
||||
|
||||
```bash
|
||||
[ -d ".aspire/modules" ] && echo "Aspire project detected"
|
||||
```
|
||||
|
||||
### 4. `aspire.config.json` Configuration (High Confidence)
|
||||
|
||||
Aspire 13.2+ uses a rooted `aspire.config.json` file (replaces legacy `aspire.json`):
|
||||
|
||||
```bash
|
||||
[ -f "aspire.config.json" ] && echo "Aspire configuration found"
|
||||
# Legacy fallback:
|
||||
[ -f "aspire.json" ] && echo "Legacy Aspire config found (pre-13.2)"
|
||||
```
|
||||
|
||||
### 5. `.aspire/` Directory (High Confidence)
|
||||
|
||||
The `.aspire/` directory stores Aspire settings and secrets:
|
||||
|
||||
```bash
|
||||
[ -d ".aspire" ] && echo "Aspire settings directory found"
|
||||
```
|
||||
|
||||
### 6. Service Defaults References (Medium Confidence)
|
||||
|
||||
Projects that reference `Aspire.ServiceDefaults` are Aspire service projects (not the AppHost, but part of an Aspire solution):
|
||||
|
||||
```bash
|
||||
grep -rl "Aspire.ServiceDefaults" --include="*.csproj" .
|
||||
```
|
||||
|
||||
This indicates the project is **part of** an Aspire solution, but these are the service projects, not the AppHost. Look for the AppHost SDK reference separately.
|
||||
|
||||
---
|
||||
|
||||
## Detection Priority
|
||||
|
||||
When scanning a repository, check signals in this order:
|
||||
|
||||
| Priority | Signal | What It Means |
|
||||
|----------|--------|---------------|
|
||||
| 1 | `Aspire.AppHost.Sdk` in `.csproj` | This IS the AppHost — target for `aspire start` |
|
||||
| 1b | `apphost.cs` or `#:sdk Aspire.AppHost.Sdk` in `.cs` | File-based C# AppHost — target for `aspire start` |
|
||||
| 2 | `apphost.ts` file | TypeScript AppHost — target for `aspire start` |
|
||||
| 3 | `.aspire/modules/` directory | Aspire project — look for the AppHost |
|
||||
| 4 | `aspire.config.json` or `.aspire/` | Aspire project — look for the AppHost |
|
||||
| 5 | `Aspire.ServiceDefaults` references | Part of Aspire solution — AppHost is elsewhere |
|
||||
|
||||
## Finding the AppHost Directory
|
||||
|
||||
The Aspire CLI commands must be run from the correct context. After detecting an Aspire project:
|
||||
|
||||
```bash
|
||||
# Find the AppHost project directory
|
||||
APPHOST_DIR=$(dirname $(grep -rl "Aspire.AppHost.Sdk" --include="*.csproj" .))
|
||||
|
||||
# Or for file-based C# AppHost
|
||||
APPHOST_FILE=$(find . -name "apphost.cs" -not -path "*/node_modules/*" | head -1)
|
||||
|
||||
# Or for TypeScript
|
||||
APPHOST_DIR=$(dirname $(find . -name "apphost.ts" -not -path "*/node_modules/*" | head -1))
|
||||
```
|
||||
|
||||
## Common Project Structures
|
||||
|
||||
### Typical C# Aspire Solution
|
||||
|
||||
```
|
||||
MyApp/
|
||||
├── MyApp.AppHost/ ← AppHost (has Aspire.AppHost.Sdk)
|
||||
│ ├── MyApp.AppHost.csproj
|
||||
│ └── Program.cs
|
||||
├── MyApp.ApiService/ ← Service project
|
||||
│ └── MyApp.ApiService.csproj
|
||||
├── MyApp.Web/ ← Frontend project
|
||||
│ └── MyApp.Web.csproj
|
||||
├── MyApp.ServiceDefaults/ ← Shared defaults
|
||||
│ └── MyApp.ServiceDefaults.csproj
|
||||
├── .aspire/
|
||||
│ └── modules/ ← Aspire-generated
|
||||
├── aspire.config.json
|
||||
└── MyApp.sln
|
||||
```
|
||||
|
||||
### Typical TypeScript Aspire Project
|
||||
|
||||
```
|
||||
MyApp/
|
||||
├── apphost.ts ← TypeScript AppHost
|
||||
├── package.json
|
||||
├── src/
|
||||
│ ├── api/ ← Service project
|
||||
│ └── web/ ← Frontend project
|
||||
├── .aspire/
|
||||
│ └── modules/
|
||||
└── aspire.config.json
|
||||
```
|
||||
|
||||
## Non-Aspire Projects
|
||||
|
||||
If none of the detection signals are found, this is **not** an Aspire project. Do not apply Aspire-specific rules. Standard .NET commands (`dotnet run`, `dotnet build`) are appropriate for non-Aspire projects.
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
# Resource Management
|
||||
|
||||
Use this when the task is scoped to one resource or depends on a specific resource becoming healthy.
|
||||
|
||||
## Wait For One Resource Before Touching It
|
||||
|
||||
```bash
|
||||
aspire wait <resource>
|
||||
aspire wait <resource> --status up --timeout 60
|
||||
```
|
||||
|
||||
- Use `aspire wait` before a dependent action when readiness is the blocker.
|
||||
- Add `--status` and `--timeout` for explicit readiness conditions.
|
||||
- Treat readiness as resource-scoped — a missing ready signal is not a reason to restart the whole AppHost.
|
||||
- Use `displayName` from `aspire ps --format Json`, not `name` ([#15842](https://github.com/microsoft/aspire/issues/15842)).
|
||||
|
||||
## Fix Or Operate On One Resource Without Bouncing The Whole App
|
||||
|
||||
```bash
|
||||
aspire resource <resource> start
|
||||
aspire resource <resource> stop
|
||||
aspire resource <resource> <command>
|
||||
```
|
||||
|
||||
- Prefer resource-scoped commands when the task doesn't require an AppHost-wide restart.
|
||||
- If one resource is wedged, use resource-scoped commands such as `stop`, `start`, or `rebuild` when the resource exposes them before escalating to a full AppHost restart.
|
||||
- Use `aspire resource <resource> <command>` when the AppHost exposes resource-specific dashboard or operational commands.
|
||||
- If the resource's own framework watch/HMR/debug workflow is already handling the change, do not force an Aspire resource command.
|
||||
|
||||
## What Changed Determines the Action
|
||||
|
||||
| What Changed | Action | Command |
|
||||
|--------------|--------|---------|
|
||||
| AppHost project (Program.cs, .csproj) | Full restart | `aspire stop` → edit → `aspire start` |
|
||||
| .NET service project (.cs files) | Rebuild/refresh resource if exposed | `aspire resource <name> rebuild` or the resource's IDE/watch workflow |
|
||||
| JavaScript/Python/Go files | Usually no Aspire action | File watchers/HMR handle it automatically |
|
||||
| Configuration (appsettings.json) | Check first | `aspire describe` then decide |
|
||||
| TypeScript AppHost deps | Restore | `aspire restore` |
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
# Safety Guardrails — Aspire Agent Rules
|
||||
|
||||
> **Purpose**: Detailed explanation of why each guardrail exists, what goes wrong when violated, and how to recover.
|
||||
|
||||
## Why These Rules Exist
|
||||
|
||||
Issue [#15801](https://github.com/microsoft/aspire/issues/15801) documented 5 specific failures when AI agents work in Aspire projects without guidance. Every rule below directly prevents one or more of these failures.
|
||||
|
||||
---
|
||||
|
||||
## Rule 1: ALWAYS `aspire start` — NEVER `dotnet run`
|
||||
|
||||
### Why `dotnet run` Is Dangerous for AppHosts
|
||||
|
||||
The AppHost project is an **orchestrator**, not a regular .NET app. Running it with `dotnet run`:
|
||||
|
||||
- **Bypasses the Aspire CLI orchestration layer** — resources don't get managed lifecycle
|
||||
- **No dashboard** — the Aspire developer dashboard won't launch
|
||||
- **No backchannel** — `aspire wait`, `aspire logs`, `aspire describe` won't work
|
||||
- **No resource management** — can't operate on individual resources
|
||||
- **Port conflicts** — resources start without coordinated port allocation
|
||||
- **No cleanup** — orphaned processes when the host exits
|
||||
|
||||
### Correct Pattern
|
||||
|
||||
```bash
|
||||
# ✅ Start the Aspire app
|
||||
aspire start
|
||||
|
||||
# ✅ Verify it's running
|
||||
aspire ps
|
||||
```
|
||||
|
||||
### `aspire run` vs `aspire start`
|
||||
|
||||
| Command | Mode | Dashboard | Use Case |
|
||||
|---------|------|-----------|----------|
|
||||
| `aspire run` | Foreground (interactive) | Yes, in terminal | Human developer at terminal |
|
||||
| `aspire start` | Background (detached) | No terminal output | **AI agents — always prefer this** |
|
||||
| `aspire run --detach` | Background (same as start) | Yes, separate window | Alternative to `aspire start` |
|
||||
|
||||
For AI agents, **always use `aspire start`** — it runs in the background and returns control to the agent.
|
||||
|
||||
### Recovery If `dotnet run` Was Used
|
||||
|
||||
```bash
|
||||
# Kill the dotnet process manually (find PID first)
|
||||
# Then start correctly:
|
||||
aspire start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rule 2: ALWAYS `aspire wait` — NEVER `curl` Polling
|
||||
|
||||
### Why `curl` Polling Is Wrong
|
||||
|
||||
Aspire tracks resource readiness internally through health checks, dependency graphs, and startup ordering. Manual HTTP polling:
|
||||
|
||||
- **Doesn't know the correct port** — Aspire assigns ports dynamically
|
||||
- **Doesn't respect dependency ordering** — a resource may respond to HTTP before its dependencies are ready
|
||||
- **Creates false negatives** — health endpoint may not exist or may return 503 during startup
|
||||
- **Wastes time** — retry loops with arbitrary delays vs. event-driven readiness
|
||||
|
||||
### Correct Pattern
|
||||
|
||||
```bash
|
||||
# ✅ Wait for a specific resource
|
||||
aspire wait apiservice
|
||||
|
||||
# ✅ Wait with extended timeout for slow resources
|
||||
aspire wait postgres --timeout 120
|
||||
|
||||
# ✅ Wait then interact
|
||||
aspire wait apiservice && curl $(aspire describe apiservice --format Json | jq -r '.endpoints[0].url')
|
||||
```
|
||||
|
||||
### Machine-Readable Output
|
||||
|
||||
Always use `--format Json` when parsing output programmatically:
|
||||
|
||||
```bash
|
||||
# ✅ Get resource endpoints as JSON
|
||||
aspire describe --format Json
|
||||
|
||||
# ❌ Never scrape text output
|
||||
aspire describe | grep "http" # fragile, format may change
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rule 3: Prefer Resource Commands / Watch — NEVER `dotnet build` With Aspire Running
|
||||
|
||||
### Why `dotnet build` Causes File-Lock Errors
|
||||
|
||||
When Aspire is running, it holds file locks on:
|
||||
|
||||
- Output assemblies (`.dll`, `.pdb`) of managed resources
|
||||
- Build intermediates in `obj/` directories
|
||||
- NuGet package caches being read by running processes
|
||||
|
||||
Running `dotnet build` while Aspire holds these locks produces:
|
||||
|
||||
```
|
||||
error MSB3491: Could not write to output file 'bin/Debug/net10.0/MyService.dll'
|
||||
error CS2012: Cannot open 'obj/Debug/net10.0/MyService.dll' for writing
|
||||
```
|
||||
|
||||
The agent then concludes the project is "un-buildable" — a false conclusion.
|
||||
|
||||
### Recovery If `dotnet build` Was Used and Locks Hit
|
||||
|
||||
When you see `MSB3491` / `CS2012` / "file in use" / "another process is using":
|
||||
|
||||
```bash
|
||||
# ✅ Single correct recovery
|
||||
aspire stop # release all Aspire-held locks
|
||||
|
||||
# Then EITHER use a resource-scoped command if Aspire is still up + one resource changed:
|
||||
aspire resource <name> rebuild
|
||||
# OR:
|
||||
aspire start # if AppHost code changed or Aspire was fully stopped
|
||||
```
|
||||
|
||||
> 🔒 **`aspire stop` is the ONLY first step.** Do not `pkill dotnet`, do not delete
|
||||
> `bin/`/`obj/`, do not "reboot to release the lock", and do not tell the user the
|
||||
> project has a permanent build failure. The cause is always the same — Aspire is
|
||||
> holding the output files — and the fix is always `aspire stop`.
|
||||
|
||||
| ❌ NEVER (file-lock recovery) | ✅ ALWAYS |
|
||||
|------------------------------|----------|
|
||||
| Say the project has a permanent build failure when you see `MSB3491`/`CS2012` | Recognize Aspire is holding locks and run `aspire stop` |
|
||||
| `pkill dotnet` / `kill <PID>` | `aspire stop` (clean shutdown via the CLI) |
|
||||
| `rm -rf bin obj` to "force" the build | `aspire stop`, then rebuild |
|
||||
| Suggest a reboot | `aspire stop` (single command) |
|
||||
| Re-run `dotnet build` with Aspire still up | `aspire stop` first; prefer resource commands/watch/HMR/debug workflow |
|
||||
|
||||
### What Changed Determines the Action
|
||||
|
||||
| What Changed | Action | Command |
|
||||
|--------------|--------|---------|
|
||||
| AppHost project (Program.cs, .csproj) | Full restart | `aspire stop` → edit → `aspire start` |
|
||||
| .NET service project (.cs files) | Rebuild/refresh resource if exposed | `aspire resource <name> rebuild` or the resource's IDE/watch workflow |
|
||||
| JavaScript/Python/Go files | Usually no Aspire action | File watchers/HMR handle it automatically |
|
||||
| Configuration (appsettings.json) | Check first | `aspire describe` then decide |
|
||||
|
||||
---
|
||||
|
||||
## Rule 4: Use `aspire stop` For Cleanup — NEVER Leave Unwanted Processes Running
|
||||
|
||||
### Why Cleanup Matters
|
||||
|
||||
Aspire orchestrates multiple processes (your services, databases, message brokers, etc.). Leaving them running causes:
|
||||
|
||||
- **Port conflicts** — next `aspire start` fails because ports are occupied
|
||||
- **File locks** — can't build or modify service code
|
||||
- **Resource consumption** — databases, Redis, etc. consuming memory
|
||||
- **Stale state** — old code running while you've made changes
|
||||
- **Orphaned containers** — Docker containers left running
|
||||
|
||||
### Correct Pattern
|
||||
|
||||
```bash
|
||||
# ✅ Stop when cleanup is requested or the user did not ask to keep it running
|
||||
aspire stop
|
||||
|
||||
# ✅ Verify everything stopped
|
||||
aspire ps # should show no running resources
|
||||
```
|
||||
|
||||
### Recovery from Orphaned Processes
|
||||
|
||||
```bash
|
||||
# Check if anything is still running
|
||||
aspire ps
|
||||
|
||||
# If aspire ps shows nothing but ports are blocked:
|
||||
# The previous instance may have crashed. Start fresh:
|
||||
aspire start # will clean up orphaned state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rule 5: ALWAYS `--format Json` for Machine-Readable Output
|
||||
|
||||
### Why JSON Output Matters for Agents
|
||||
|
||||
Text output is formatted for humans and may change between versions. JSON output is:
|
||||
|
||||
- **Stable** — structured contract unlikely to break
|
||||
- **Parseable** — `jq`, Python, or any JSON parser works
|
||||
- **Complete** — includes fields not shown in text output
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# ✅ Machine-readable resource list
|
||||
aspire ps --format Json
|
||||
|
||||
# ✅ Get specific resource details
|
||||
aspire describe apiservice --format Json
|
||||
|
||||
# ✅ Parse with jq
|
||||
aspire describe --format Json | jq '.resources[] | select(.state == "Running")'
|
||||
```
|
||||
|
||||
### ⚠️ Known JSON Output Issues
|
||||
|
||||
| Issue | Workaround |
|
||||
|-------|-----------|
|
||||
| `aspire start --format json` may emit human-readable text before JSON ([#15843](https://github.com/microsoft/aspire/issues/15843)) | Strip non-JSON lines before parsing |
|
||||
| `aspire stop` does NOT support `--format json` yet | Use exit code for success/failure |
|
||||
| `aspire ps --format Json` returns `name` and `displayName` fields | Use `displayName` for `aspire wait` — the `name` field may be rejected ([#15842](https://github.com/microsoft/aspire/issues/15842)) |
|
||||
|
||||
### Hidden Resources and `--include-hidden`
|
||||
|
||||
`aspire ps`, `aspire describe`, and other CLI commands **filter out resources marked as
|
||||
hidden in the AppHost** (proxies, helper containers, migration jobs, etc.).
|
||||
This filtering is correct for normal workflows — agents and humans see only the resources they
|
||||
care about, not the implementation scaffolding.
|
||||
|
||||
Use `--include-hidden` when:
|
||||
|
||||
| Situation | Why |
|
||||
|-----------|-----|
|
||||
| Debugging a proxy or sidecar | Proxies are hidden by default; you need their state to diagnose connectivity |
|
||||
| Investigating helper containers | Helper containers (e.g. wait-for-it shims, init containers) are hidden |
|
||||
| Tracking down migration jobs | Migration / seed jobs are typically hidden once they finish |
|
||||
| Expected resources are missing from `aspire ps` | The resource may exist but be marked hidden — confirm with `--include-hidden` before assuming the AppHost is wrong |
|
||||
| Parsing for completeness in agent automation | A full-graph view requires explicit opt-in |
|
||||
|
||||
```bash
|
||||
# ✅ Normal flow — filtered (correct for most tasks)
|
||||
aspire ps --format Json
|
||||
|
||||
# ✅ Debugging / completeness — include hidden resources
|
||||
aspire ps --include-hidden --format Json
|
||||
aspire describe --include-hidden --format Json
|
||||
```
|
||||
|
||||
If a user reports "I can't see my proxy / migration / helper container," reach for
|
||||
`--include-hidden` before assuming the AppHost is misconfigured.
|
||||
|
||||
---
|
||||
|
||||
## Rule 6: ALWAYS `--non-interactive` for Agent Commands
|
||||
|
||||
### Why It Matters
|
||||
|
||||
AI agents run in non-interactive terminals. Some Aspire CLI commands may prompt for confirmation or input. Always pass `--non-interactive` to prevent hangs:
|
||||
|
||||
```bash
|
||||
# ✅ Agent-safe commands
|
||||
aspire start --non-interactive
|
||||
aspire deploy --non-interactive
|
||||
aspire agent init --non-interactive
|
||||
```
|
||||
|
||||
> ⚠️ **Known issue**: `aspire agent init --non-interactive` is broken in some versions ([#16264](https://github.com/microsoft/aspire/issues/16264), [#15071](https://github.com/microsoft/aspire/issues/15071)). If it fails, instruct the user to run it from a standard terminal.
|
||||
|
||||
---
|
||||
|
||||
## Recovery Patterns Summary
|
||||
|
||||
| Mistake Made | Recovery Steps |
|
||||
|-------------|---------------|
|
||||
| Used `dotnet run` on AppHost | Kill the process, run `aspire start` |
|
||||
| Used `dotnet build` and got file locks | `aspire stop`, wait 2s, then `dotnet build` or `aspire start` |
|
||||
| Used `curl` polling and got false results | `aspire wait <resource>`, then use endpoints from `aspire describe` |
|
||||
| Left Aspire running, now ports conflict | `aspire stop`, then `aspire start` |
|
||||
| Resource won't start after code change | Fix code, then use resource commands/watch/HMR/debug workflow or restart the AppHost if the AppHost model changed |
|
||||
| Nothing works, environment broken | `aspire doctor` to diagnose, then follow recommendations |
|
||||
Reference in New Issue
Block a user