# Add Query

> 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.

- Skill: `makigjuro/add-query` (Agent Skill)
- Install (CLI): `npx skillmds@latest add makigjuro/add-query`
- Raw SKILL.md: https://api.skillmd.com/api/skills/makigjuro/add-query/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: makigjuro (https://skillmd.com/u/makigjuro)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/makigjuro/add-query

---


# 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., `GetCustomerById`, `ListOrders`)
- `{Service}` -- Target microservice. Ask if ambiguous.

## Configuration

Read `cloudstack.json` from the project root at the start of execution. Extract:
- `NAMESPACE` = `project.namespace` (default: detect from `*.sln` name or first `*.csproj` root namespace)
- `SERVICES` = `backend.services[]` (default: discover from `src/*/` directories containing `.Application/` subfolders)
- `SOLUTION` = `backend.solutionPath` (default: find `*.sln` in `src/`)

If `cloudstack.json` does not exist, auto-detect by scanning the project structure.

## 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`)

```csharp
namespace {Namespace}.{Service}.Application.Queries;

public record {Name}Query({parameters});
```

For list queries, include pagination:
```csharp
public record List{Entity}Query(Guid TenantId, int PageNumber = 1, int PageSize = 20, string? Search = null);
```

## 2. Response Record (`Application/Contracts/`)

For single entity:
```csharp
public record {Name}Response({fields});
```

For lists, return paged response:
```csharp
public record {Name}ListResponse(IReadOnlyCollection<{Name}Response> Items, int TotalCount, int PageNumber, int PageSize);
```

## 3. Handler (`Application/Queries/{Name}Handler.cs`)

```csharp
namespace {Namespace}.{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)
    {
        // Use query repository (read-optimized, potentially Dapper)
        // Return Result.Success or Result.Failure("NOT_FOUND", ...)
    }
}
```

## 4. Query Repository Method

Add to the query repository interface in Domain:
```csharp
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`)

```csharp
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:
```csharp
[FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 20, [FromQuery] string? search = null
```

## Checklist
- [ ] Query record is immutable
- [ ] Uses query repository (read side), not command repository
- [ ] Handler returns `Result<T>`
- [ ] Endpoint has OpenAPI metadata
- [ ] Pagination supported for list queries
- [ ] CancellationToken propagated

## 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

