Reorganised the folders.

This commit is contained in:
2026-06-28 16:45:38 +02:00
parent 3434e9fb91
commit 1b5bf4f8d4
111 changed files with 81 additions and 0 deletions
@@ -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.
@@ -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.
@@ -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.
@@ -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` |
@@ -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 |