Categories
Agent Tooling (71)
- .agents/skills/agent-browser/references/authentication.md
- .agents/skills/agent-browser/references/commands.md
- .agents/skills/agent-browser/references/profiling.md
- .agents/skills/agent-browser/references/proxy-support.md
- .agents/skills/agent-browser/references/session-management.md
- .agents/skills/agent-browser/references/snapshot-refs.md
- .agents/skills/agent-browser/references/video-recording.md
- .agents/skills/agent-browser/SKILL.md
- .agents/skills/aspire-deployment/references/aws.md
- .agents/skills/aspire-deployment/references/azure.md
- .agents/skills/aspire-deployment/references/cicd.md
- .agents/skills/aspire-deployment/references/docker-compose.md
- .agents/skills/aspire-deployment/references/javascript.md
- .agents/skills/aspire-deployment/references/kubernetes.md
- .agents/skills/aspire-deployment/references/preflight.md
- .agents/skills/aspire-deployment/SKILL.md
- .agents/skills/aspire-monitoring/references/diagnostics-bridge.md
- .agents/skills/aspire-monitoring/references/monitoring.md
- .agents/skills/aspire-monitoring/references/playwright-handoff.md
- .agents/skills/aspire-monitoring/SKILL.md
- .agents/skills/aspire-orchestration/references/agent-workflows.md
- .agents/skills/aspire-orchestration/references/app-commands.md
- .agents/skills/aspire-orchestration/references/detection.md
- .agents/skills/aspire-orchestration/references/resource-management.md
- .agents/skills/aspire-orchestration/references/safety-guardrails.md
- .agents/skills/aspire-orchestration/SKILL.md
- .agents/skills/aspire/references/aspire-13-3-breaking-changes.md
- .agents/skills/aspire/SKILL.md
- .agents/skills/aspireify/references/apphost-wiring.md
- .agents/skills/aspireify/references/csharp-authoring.md
- .agents/skills/aspireify/references/docker-compose.md
- .agents/skills/aspireify/references/full-solution-apphosts.md
- .agents/skills/aspireify/references/javascript-apps.md
- .agents/skills/aspireify/references/opentelemetry.md
- .agents/skills/aspireify/references/scan-and-propose.md
- .agents/skills/aspireify/references/service-defaults.md
- .agents/skills/aspireify/references/typescript-authoring.md
- .agents/skills/aspireify/references/validation.md
- .agents/skills/aspireify/SKILL.md
- .agents/skills/caveman-compress/README.md
- .agents/skills/caveman-compress/SECURITY.md
- .agents/skills/caveman-compress/SKILL.md
- .agents/skills/caveman-help/README.md
- .agents/skills/caveman-help/SKILL.md
- .agents/skills/caveman-stats/README.md
- .agents/skills/caveman-stats/SKILL.md
- .agents/skills/caveman/README.md
- .agents/skills/caveman/SKILL.md
- .agents/skills/csharp-developer/SKILL.md
- .agents/skills/dotnet-inspect/SKILL.md
- .agents/skills/efcore-data-layer/SKILL.md
- .agents/skills/git/SKILL.md
- .agents/skills/microsoft-code-reference/SKILL.md
- .agents/skills/microsoft-docs/SKILL.md
- .agents/skills/microsoft-skill-creator/references/skill-templates.md
- .agents/skills/microsoft-skill-creator/SKILL.md
- .agents/skills/skill-creator/references/output-patterns.md
- .agents/skills/skill-creator/references/workflows.md
- .agents/skills/skill-creator/SKILL.md
- .agents/skills/tunit-testing/references/aspire-integration.md
- .agents/skills/tunit-testing/references/aspnetcore-integration.md
- .agents/skills/tunit-testing/references/assertions.md
- .agents/skills/tunit-testing/references/data-driven.md
- .agents/skills/tunit-testing/references/infrastructure-and-troubleshooting.md
- .agents/skills/tunit-testing/references/lifecycle-hooks.md
- .agents/skills/tunit-testing/SKILL.md
- AGENTS.md
- backend/AGENTS.md
- backend/tests/AGENTS.md
- Front/AGENT.md
- opencode.jsonc
Full-solution C# AppHosts
Use this reference when aspire init created a full project mode AppHost because a .sln or .slnx was discovered.
This is the high-friction path: solution-backed repos often have older bootstrap patterns, SDK pins, existing ServiceDefaults-like code, build constraints, and significantly more projects than single-file repos. Some of these solutions have dozens or hundreds of projects — the skill must triage smartly, not try to wire everything.
What this reference is for
Load this reference when any of the following are true:
appHost.pathpoints to a directory containingapphost.csand a.csproj- a
.slnor.slnxexists near the AppHost - the repo has a root
global.json - selected .NET services still use
Program.cs+Startup.cs,Host.CreateDefaultBuilder,ConfigureWebHostDefaults,UseStartup, or otherIHostBuilderpatterns
Core rule: solution-backed AppHosts are not single-file AppHosts
Treat these repos as solution-aware C# init, not as generic AppHost setup.
- The AppHost may need project references
- The AppHost may need its own SDK boundary
- The solution may or may not be able to own the AppHost safely
- ServiceDefaults changes may require bootstrap modernization
Do not apply single-file assumptions here.
Large solution triage
When a solution contains more than a handful of projects, don't try to model everything at once. Classify projects first, then present a focused list.
Step 1: Classify all projects
For every .csproj in the solution, determine its role:
| Classification | How to detect | Action |
|---|---|---|
| Runnable service | OutputType = Exe or WinExe, not a test project, not the AppHost | Candidate for AppHost modeling |
| Class library | OutputType = Library | Skip — these are dependencies, not services |
| Test project | References xUnit/NUnit/MSTest, or name ends in .Test/.Tests/.IntegrationTest | Skip |
| Migration runner | Name contains Migrat, or references DbUp/FluentMigrator/EF migrations tooling | Special handling — see below |
| Utility/tool | Located in util/, tools/, or scripts/ directories; not a long-running service | Skip unless user requests |
| AppHost | IsAspireHost = true | Skip — this is the host itself |
Run dotnet msbuild <project> -getProperty:OutputType to classify. For large solutions, batch these calls.
Step 2: Check for multiple source roots
Some repos keep code in more than one top-level directory. Common patterns:
src/+bitwarden_license/src/(open-source vs commercial)src/+util/(services vs utilities)apps/+packages/(monorepo with shared packages)
Scan all directories in the solution, not just src/. If you find projects outside src/, note them and ask the user if they should be included.
Step 3: Present the focused list
Group runnable services by category and present them concisely. For a repo with 60+ projects, show something like:
"I found 8 runnable web services (Api, Admin, Identity, Billing, Events, EventsProcessor, Icons, Notifications), 5 class libraries (Core, SharedWeb, Infrastructure.Dapper, Infrastructure.EntityFramework, Sql), 3 migration runners (Migrator, MsSqlMigratorUtility, PostgresMigrations), and 40+ test projects.
I recommend starting with the core services. Which of the 8 web services should I include in the AppHost?"
Do not dump a flat list of 60+ projects. Classify, summarize, and let the user choose.
Incremental "core loop" wiring
For solutions with 5 or more runnable services, recommend starting with a core loop — the minimum set of services needed for a useful local dev session — and expanding from there.
The core loop is typically:
- The primary API service
- Its database dependency
- Any authentication/identity service
- The essential cache (Redis, etc.)
Present this explicitly:
"You have 8 services. I recommend wiring the core loop first — Api, Identity, and the database — so we can validate aspire start works. Then we'll add the remaining services. Sound good?"
After the core loop succeeds with aspire start:
- Stop the AppHost
- Add the next batch of services (2-3 at a time) to the AppHost
- Run
aspire startagain to validate - If it fails, diagnose and fix before adding more
- Repeat until all selected services are wired
Present progress to the user as you go:
"Core loop is working (Api + Identity + Postgres + Redis). Adding the next batch: Admin, Billing, and Events..."
Do not consider the skill complete until all services the user selected in Step 3 are wired and aspire start runs with all of them healthy. The core loop is a risk-reduction strategy, not an excuse to stop early.
Migration runners and setup utilities
Migration runners (database migrations, schema updates, data seeders) deserve special handling. They aren't long-running services — they run once and exit.
Present the user with options:
- Model as a project resource with
WaitForCompletion()— the migration runs at startup and dependent services wait for it to finish before starting:
var db = builder.AddSqlServer("mssql").AddDatabase("vault");
var migrator = builder.AddProject<Projects.Migrator>("migrator")
.WithReference(db)
.WaitFor(db);
var api = builder.AddProject<Projects.Api>("api")
.WithReference(db)
.WaitForCompletion(migrator); // api waits for migrations to finish- Leave as manual — the developer runs migrations separately before
aspire start. Note this in an AppHost comment:
// Run migrations manually: dotnet run --project ../util/Migrator
var db = builder.AddSqlServer("mssql").AddDatabase("vault");Recommend option 1 for repos that currently run migrations as part of their docker-compose or startup scripts. Recommend option 2 for repos where migrations are a deliberate, explicit step.
Custom MSBuild SDKs
Check global.json for msbuild-sdks entries beyond the standard Microsoft ones. Common SDKs like Microsoft.Build.Traversal are well-known, but custom SDKs (e.g., Bitwarden.Server.Sdk) are opaque.
When you find a custom MSBuild SDK:
- Don't assume project properties are reliable — the custom SDK may override
OutputType, inject implicit references, or modify build behavior in ways you can't see - Note it to the user — "This repo uses a custom MSBuild SDK (Bitwarden.Server.Sdk). I'll classify projects based on their directory structure and names as well as MSBuild properties, since the custom SDK may affect property evaluation."
- Cross-reference with directory structure — if
OutputTypesaysLibrarybut the project is insrc/Api/and has aProgram.csandStartup.cs, it's likely a runnable service whose OutputType is set by the custom SDK
Conditional compilation
Some repos use #if / #endif to maintain multiple build variants from the same source:
#if OSS
services.AddOosServices();
#else
services.AddCommercialCoreServices();
#endifWhen you detect conditional compilation in Program.cs or Startup.cs:
- Surface it early — "Your services use
#if OSSconditional compilation, which means the app behaves differently depending on the build configuration. Which variant should the AppHost target — OSS or commercial?" - Don't try to model both — pick the variant the user selects and wire accordingly
- Note the other variant — leave a comment in the AppHost:
// This AppHost targets the OSS build. For commercial, adjust service registrations.
This is not a priority to solve perfectly — just make sure the agent doesn't silently pick the wrong variant.
Mixed SDK repos
Some repos pin the root global.json to an older SDK such as .NET 8. A .csproj-based Aspire AppHost should still stay on the current Aspire-supported SDK (for example, .NET 10), while existing service projects can remain on net8.0.
Do not downgrade the AppHost project to match the repo's root SDK pin. Do not change the root global.json. Do not change any existing project's <TargetFramework>.
Create a nested global.json for the AppHost
If the repo's root global.json pins an older SDK and the AppHost is in full project mode, you must create a nested global.json inside the AppHost directory so it builds with the correct SDK. Check whether one already exists before creating it.
Steps:
- Keep the repo root
global.jsonunchanged. - Check if a
global.jsonalready exists in the AppHost directory — if so, skip this. - Create a
global.jsonnext to the AppHost.csprojthat pins the Aspire-supported SDK:
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestFeature"
}
}- Leave existing services targeting their current TFM unless the user explicitly asks to migrate them.
Important solution caveat
If the repo's normal root build runs under SDK 8, do not assume it can safely own a net10.0 AppHost project.
When that's likely to break the repo's normal build:
- tell the user explicitly
- prefer keeping the AppHost isolated in its own folder
- only add it to the root solution if the user wants that tradeoff
Solution membership
A discovered solution means the AppHost was created in project mode, but that does not always mean every new project should be added to the root solution automatically.
Use this decision order:
- If the root solution already includes the services being modeled and is the normal local entry point, prefer adding the AppHost and ServiceDefaults there.
- If the root solution is tightly coupled to an older SDK/toolchain and adding a
net10.0AppHost is likely to break routine builds, keep the AppHost outside the solution or in a safer sibling solution boundary. - If you're unsure, ask instead of guessing.
ServiceDefaults in solution-backed repos
Before creating or wiring ServiceDefaults:
- Look for an existing ServiceDefaults project or equivalent shared bootstrap code.
- Check whether selected services already have tracing, health checks, or service discovery setup.
- Check whether the service bootstrap is modern enough for
AddServiceDefaults()andMapDefaultEndpoints().
If a ServiceDefaults project already exists, reuse it instead of creating another one.
Legacy bootstrap detection: IHostBuilder vs IHostApplicationBuilder
This is the easy-to-forget gotcha.
The generated ServiceDefaults extensions typically target IHostApplicationBuilder and WebApplication patterns:
builder.AddServiceDefaults();
app.MapDefaultEndpoints();That drops cleanly into modern code such as:
var builder = WebApplication.CreateBuilder(args);var builder = Host.CreateApplicationBuilder(args);
It does not automatically map onto older patterns such as:
Host.CreateDefaultBuilder(args)ConfigureWebHostDefaults(...)UseStartup<Startup>()IHostBuilder-only worker/bootstrap code
What to do when you find legacy hosting
Do not silently jam ServiceDefaults into the old shape. Do not create adapter extension methods on IHostBuilder — ServiceDefaults is designed for IHostApplicationBuilder and should only be used with the modern bootstrap pattern.
There are exactly two options. Present them clearly:
- Skip ServiceDefaults for now (recommended for initial setup)
- Model the service in the AppHost with
AddProject<T>()orAddCSharpApp() - The service appears in the dashboard, gets environment wiring, and shows logs
- No code changes to the service project needed
- Health checks, service discovery, and OTel from ServiceDefaults are deferred
- Modernize the service's bootstrap (larger change, per-service)
- Convert
Program.csfromHost.CreateDefaultBuilder()toWebApplication.CreateBuilder() - Inline the
Startup.ConfigureServices()intobuilder.Services.*calls - Inline the
Startup.Configure()into theapp.*middleware pipeline - Then add
builder.AddServiceDefaults()andapp.MapDefaultEndpoints() - Existing
IHostBuilderextensions (like custom logging, SDK setup) can be called viabuilder.Host.*
When multiple services share the same legacy pattern, batch the decision. If 8 services all use Host.CreateDefaultBuilder + UseStartup<T>, don't ask 8 times. Ask once:
"All 8 of your web services use the legacy IHostBuilder + Startup pattern. I can either (a) model them all in the AppHost without ServiceDefaults for now — they'll appear in the dashboard and get environment wiring but won't have health checks or service discovery — or (b) modernize each service's bootstrap to the WebApplicationBuilder pattern so ServiceDefaults works fully. Which approach do you prefer? You can also mix — modernize a few key services and leave the rest."
If the repo is conservative or large, default to asking, not migrating automatically.
Modernization guidance
ASP.NET Core app using IHostBuilder / Startup
If the user wants full ServiceDefaults support, migrate toward a WebApplicationBuilder shape.
Target pattern:
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.MapDefaultEndpoints();
app.Run();Preserve existing service registrations and middleware ordering carefully. Move only what is required to land on a WebApplicationBuilder/WebApplication pipeline.
When the Startup class has custom extension methods (e.g., UseBitwardenSdk(), AddGlobalSettingsServices()), those typically need to be called on the new builder or app in the appropriate phase. Don't silently drop them — trace each call to its registration phase (services vs middleware) and preserve it.
Worker/background service using IHostBuilder
If the service is a worker and the user wants ServiceDefaults, migrate toward Host.CreateApplicationBuilder(args):
var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults();
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
await host.RunAsync();For non-web workers, MapDefaultEndpoints() usually does not apply unless the app exposes HTTP endpoints.
AppHost project references
For full project mode, prefer explicit project references from the AppHost to selected .NET services:
dotnet add <AppHost.csproj> reference <Api.csproj>This keeps solution-backed AppHosts easier to navigate and build.
Validation checklist for full-solution mode
Before declaring success:
- The AppHost project builds under its intended SDK boundary.
- The root solution still behaves the way the user expects, or the user has explicitly accepted any tradeoff.
- Any ServiceDefaults changes compile in the selected services.
aspire startworks from the AppHost context, and long-lived app resources are healthy rather than merelyFinished.- Legacy
IHostBuilderservices were either modernized intentionally or explicitly left unchanged. - Migration runners, if modeled, complete successfully before dependent services start.
When to ask the user instead of deciding
Ask when:
- adding the AppHost to the root solution might break the repo's normal SDK/build
- a service uses
Startup.cs/IHostBuilderand would need real bootstrap surgery - there are multiple plausible ServiceDefaults/shared-bootstrap projects to reuse
- the repo has mixed solution boundaries and it's unclear which one is the real developer entry point
- the repo has a custom MSBuild SDK and project classification is ambiguous
- the repo uses conditional compilation and the target variant is unclear
- there are more than 5 runnable services and you need to decide which to wire first