Skip to content
Development
Skill

/openapi

Built-in OpenAPI support for .NET 10 applications. Covers document generation, transformers, TypedResults metadata, security schemes, XML comments, build-time generation, and multiple document support. No Swashbuckle needed. Load this skill when setting up API documentation,

BOOST
From plugin
dotnet-claude-kit
76147 skills10 agents2 hooks1 MCP
Install
$ npx -y skills add codewithmukesh/dotnet-claude-kit --skill openapi --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/openapi

Context preview

The summary Claude sees to decide when to auto-load this skill.

Built-in OpenAPI support for .NET 10 applications. Covers document generation, transformers, TypedResults metadata, security schemes, XML comments, build-time generation, and multiple document support. No Swashbuckle needed. Load this skill when setting up API documentation,

SKILL.md

openapi.SKILL.md
name: openapi
description: >
  Built-in OpenAPI support for .NET 10 applications. Covers document generation,
  transformers, TypedResults metadata, security schemes, XML comments, build-time
  generation, and multiple document support. No Swashbuckle needed.
  Load this skill when setting up API documentation, customizing OpenAPI output,
  adding security schemes to docs, or when the user mentions "OpenAPI",
  "AddOpenApi", "MapOpenApi", "document transformer", "operation transformer",
  "schema transformer", "OpenAPI 3.1", "API documentation", "Swashbuckle
  replacement", "Produces", "WithSummary", "WithDescription", "ProblemDetails",
  "Kiota", or "client generation".

OpenAPI

Core Principles

1. **Built-in, not Swashbuckle** — .NET 10 ships `Microsoft.AspNetCore.OpenApi` as the official, framework-maintained OpenAPI solution. Swashbuckle was removed from templates in .NET 9 and is no longer recommended. 2. **TypedResults drive the schema** — `TypedResults.Ok<T>()` automatically generates correct OpenAPI response schemas. `Results.Ok()` does not. Always use `TypedResults`. 3. **Transformers over workarounds** — Document, operation, and schema transformers compose cleanly. Use them for security schemes, global responses, and schema customization. 4. **Metadata on every endpoint** — Use `.WithName()`, `.WithSummary()`, `.WithTags()` on every endpoint. This metadata feeds directly into the OpenAPI spec and client generators.

Patterns

Basic Setup

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();  // Serves at /openapi/v1.json
}

Endpoint Metadata

group.MapPost("/", CreateOrder)
    .WithName("CreateOrder")
    .WithSummary("Create a new order")
    .WithDescription("Creates a new order for the specified customer.")
    .Produces<OrderResponse>(StatusCodes.Status201Created)
    .ProducesValidationProblem()
    .ProducesProblem(StatusCodes.Status500InternalServerError);

With `TypedResults`, response metadata is inferred automatically:

static async Task<Results<Created<OrderResponse>, ValidationProblem>> CreateOrder(
    CreateOrderRequest request, ISender sender, CancellationToken ct)
{
    var result = await sender.Send(new CreateOrder.Command(request), ct);
    return result.IsSuccess
        ? TypedResults.Created($"/api/orders/{result.Value.Id}", result.Value)
        : TypedResults.ValidationProblem(result.Errors);
}

Bearer Token Security Scheme

builder.Services.AddOpenApi(options =>
{
    options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});

internal sealed class BearerSecuritySchemeTransformer(
    IAuthenticationSchemeProvider authSchemeProvider) : IOpenApiDocumentTransformer
{
    public async Task TransformAsync(OpenApiDocument document,
        OpenApiDocumentTransformerContext context, CancellationToken ct)
    {
        var schemes = await authSchemeProvider.GetAllSchemesAsync();
        if (!schemes.Any(s => s.Name == "Bearer"))
            return;

        document.Components ??= new OpenApiComponents();
        document.Components.SecuritySchemes = new Dictionary<string, IOpenApiSecurityScheme>
        {
            ["Bearer"] = new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.Http,
                Scheme = "bearer",
                BearerFormat = "JWT",
                In = ParameterLocation.Header
            }
        };

        foreach (var operation in document.Paths.Values.SelectMany(p => p.Operations))
        {
            operation.Value.Security ??= [];
            operation.Value.Security.Add(new OpenApiSecurityRequirement
            {
                [new OpenApiSecuritySchemeReference("Bearer", document)] = []
            });
        }
    }
}

Document Info Transformer

builder.Services.AddOpenApi(options =>
{
    options.AddDocumentTransformer((document, context, ct) =>
    {
        document.Info = new()
        {
            Title = "Checkout API",
            Version = "v1",
            Description = "API for processing orders and payments."
        };
        return Task.CompletedTask;
    });
});

Multiple OpenAPI Documents

builder.Services.AddOpenApi("v1");
builder.Services.AddOpenApi("internal", options =>
{
    options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});

// Endpoints choose their document via WithGroupName
app.MapGet("/public", () => "Hello").WithGroupName("v1");
app.MapGet("/admin", () => "Secret").WithGroupName("internal");

Endpoints without `.WithGroupName()` appear in all documents.

XML Documentation Comments (.NET 10)

Enable in the project file — the source generator extracts `<summary>`, `<param>`, `<response>` tags automatically:

<PropertyGroup>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
/// <summary>Retrieves a project board by ID.</summary>
/// <param name="id">The project board ID.</param>
/// <response code="200">Returns the project board.</response>
/// <response code="404">Board not found.</response>
static async Task<Results<Ok<Board>, NotFound>> GetBoard(int id, AppDbContext db)
{
    var board = await db.Boards.FindAsync(id);
    return board is not null ? TypedResults.Ok(board) : TypedResults.NotFound();
}

XML comments on lambdas are not captured by the compiler. Use named methods.

Schema Transformer

options.AddSchemaTransformer((schema, context, ct) =>
{
    if (context.JsonTypeInfo.Type == typeof(decimal))
    {
        schema.Format = "decimal";
    }
    return Task.CompletedTask;
});

Per-Endpoint Operation Transformer (.NET 10)

app.MapGet("/old", () => "deprecated")
    .AddOpenApiOperationTransformer((operation, context, ct) =>
    {
        operation.Deprecated = true;
        return Task.Complet
Read more
Ships withdotnet-claude-kit

Make Claude Code a .NET 10 Expert

Get the whole plugin

Other skills on dotnet-claude-kit.