| name | add-query |
| description | Scaffold a new CQRS query with handler and GET endpoint following project conventions. Use whenever the user wants to add a read endpoint, GET route, list/detail view, or search/filter capability to a microservice. |
| allowed-tools | Read, Write, Edit, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__query-docs |
| user-invocable | true |
Add CQRS Query
When the user asks to add a new query, scaffold the following files in the correct microservice. Ask which service if ambiguous.
Arguments
{Name} — Query name in PascalCase (e.g., GetDeviceById, ListBundles)
{Service} — Target microservice (e.g., DeviceManager, BundleOrchestrator). Ask if ambiguous.
Prerequisites
- The target microservice must exist under
src/
- The entity and its query repository interface should exist (if not, run
/add-entity first)
- An Endpoints file should exist at
Host/Endpoints/ (if not, create one)
1. Query Record (Application/Queries/{QueryName}.cs)
namespace SignalBeam.{Service}.Application.Queries;
public record {Name}Query({parameters});
For list queries, include pagination:
public record List{Entity}Query(Guid TenantId, int PageNumber = 1, int PageSize = 20, string? Search = null);
2. Response Record (Application/Contracts/)
For single entity:
public record {Name}Response({fields});
For lists, return paged response:
public record {Name}ListResponse(IReadOnlyCollection<{Name}Response> Items, int TotalCount, int PageNumber, int PageSize);
3. Handler (Application/Queries/{Name}Handler.cs)
namespace SignalBeam.{Service}.Application.Queries;
public class {Name}Handler
{
private readonly I{Entity}QueryRepository _queryRepository;
public {Name}Handler(I{Entity}QueryRepository queryRepository)
{
_queryRepository = queryRepository;
}
public async Task<Result<{Name}Response>> Handle({Name}Query query, CancellationToken cancellationToken)
{
}
}
4. Query Repository Method
Add to the query repository interface in Domain:
Task<{Entity}?> GetByIdAsync({Entity}Id id, CancellationToken cancellationToken = default);
Implement in Infrastructure using EF Core or Dapper for read-optimized queries.
5. Endpoint (add to existing Host/Endpoints/{Domain}Endpoints.cs)
group.MapGet("/{route}", {Name})
.WithName("{Name}")
.WithSummary("...")
.Produces<{Name}Response>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status404NotFound);
private static async Task<IResult> {Name}(
[FromRoute] Guid id,
[FromServices] {Name}Handler handler,
CancellationToken cancellationToken)
{
var query = new {Name}Query(id);
var result = await handler.Handle(query, cancellationToken);
return result.ToHttpResult();
}
For list endpoints, use [FromQuery] for pagination:
[FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20, [FromQuery] string? search = null
Checklist
Output
After scaffolding, report:
## Scaffolded: {Name}Query
Files created/modified:
- `src/{Service}/{Service}.Application/Queries/{Name}Query.cs`
- `src/{Service}/{Service}.Application/Queries/{Name}Handler.cs`
- `src/{Service}/{Service}.Application/Contracts/{Name}Response.cs`
- `src/{Service}/{Service}.Host/Endpoints/{Domain}Endpoints.cs` (modified)
Next: Run `/run-tests` to verify, or `/add-feature` to create the frontend calling this query.
Error Handling
- Endpoints file doesn't exist: Create a new
{Domain}Endpoints.cs with the route group boilerplate.
- Query repository interface missing: Create it in the Domain layer alongside the command repository.
- Entity doesn't exist: Suggest running
/add-entity first before proceeding.
Related Skills
/add-command if you also need a write endpoint for the same resource
/add-entity if the entity doesn't exist yet
/add-feature to create the frontend feature that calls this query