Skip to content
Back to skills

Go Swagger

ASecurity

Use when adding or maintaining OpenAPI/Swagger documentation for a Go HTTP API. Covers swaggo/swag annotation comments (@Summary, @Param, @Success, @Router, @Security), the swag CLI workflow, framework integration for Gin/Echo/Fiber/Chi/net-http, security definitions (Bearer/JWT, OAuth2, API key), and struct tags (example, enums, swaggertype, swaggerignore). Apply when a project imports github.com/swaggo/swag or any of the swaggo UI adapters, or when you need to expose /swagger/index.html.

  • 8 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 9, 2026
ai-agentsgobashgitapisecuritydocumentation

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned June 9, 2026

npx -y skills add muratmirgun/gophers --skill go-swagger --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Go Swagger?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Go Swagger
[![Security: A β€” Skills Directory](https://www.skillsdirectory.com/api/skills/muratmirgun-go-swagger/badge)](https://www.skillsdirectory.com/skills/muratmirgun-go-swagger)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: go-swagger
description: "Use when adding or maintaining OpenAPI/Swagger documentation for a Go HTTP API. Covers swaggo/swag annotation comments (@Summary, @Param, @Success, @Router, @Security), the swag CLI workflow, framework integration for Gin/Echo/Fiber/Chi/net-http, security definitions (Bearer/JWT, OAuth2, API key), and struct tags (example, enums, swaggertype, swaggerignore). Apply when a project imports github.com/swaggo/swag or any of the swaggo UI adapters, or when you need to expose /swagger/index.html."
user-invocable: false
license: MIT
compatibility: "Designed for Claude Code or similar AI coding agents. Requires Go 1.21+, swaggo/swag v1.16+ (CLI: `swag`)."
metadata:
  author: muratmirgun
  version: "0.1.0"
  openclaw:
    emoji: "πŸ“‹"
    homepage: https://github.com/muratmirgun/gophers
    requires:
      bins:
        - go
    install:
      - kind: go
        package: github.com/swaggo/swag/cmd/swag@latest
        bins: [swag]
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*)
---

# Go Swagger / OpenAPI with swaggo

`github.com/swaggo/swag` is the de-facto annotation-driven OpenAPI generator for Go. You annotate handlers with `// @...` comments, run the `swag` CLI, and get `docs/swagger.json`, `docs/swagger.yaml`, and `docs/docs.go` for the UI.

## Core Rules

1. **Docs are a contract.** A field documented as required is the API's promise; a mismatch with the implementation is a bug.
2. **Annotations live next to handlers.** Not in a separate `docs/` folder β€” comments rot when separated from code.
3. **Regenerate on every change.** `swag init` is part of the build (`go generate` or a Makefile target). Stale `docs/` is worse than no docs.
4. **The `docs` package must be imported.** A blank import (`_ "yourmod/docs"`) registers the spec at process start.
5. **Use named structs for request/response bodies.** swag cannot derive a schema from `map[string]any` or a primitive type.
6. **Security definitions match implementation.** If the API enforces JWT, declare `@securityDefinitions.apikey Bearer` and annotate every protected endpoint with `@Security Bearer`.

## Install and Bootstrap

```bash
go install github.com/swaggo/swag/cmd/swag@latest
swag init                              # general info from main.go
swag init -g cmd/api/main.go           # custom main path
swag fmt                               # format annotation comments like gofmt
```

Wire the UI for your framework β€” choose one:

```go
// Gin
import (
    swaggerFiles "github.com/swaggo/files"
    ginSwagger  "github.com/swaggo/gin-swagger"
)
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

// Echo
r.GET("/swagger/*", echoSwagger.WrapHandler)

// Fiber
app.Get("/swagger/*", fiberSwagger.WrapHandler(swaggerFiles.Handler))

// Chi / net/http
mux.Handle("/swagger/", httpSwagger.Handler(swaggerFiles.Handler))
```

Import the generated spec:

```go
import _ "github.com/acme/myapi/docs"          // blank: just register
import docs "github.com/acme/myapi/docs"       // named: override host at runtime
```

> Read [references/swag-cli.md](references/swag-cli.md) for the CLI flag inventory and Makefile patterns.

## General API Info

Place in the file passed via `-g` (usually `main.go`):

```go
// @title           Orders API
// @version         1.0
// @description     Orders, customers, shipments.
// @contact.name    API Support
// @contact.email   api@acme.example
// @license.name    Apache-2.0
// @host            api.acme.example
// @BasePath        /api/v1
// @schemes         https http

// @securityDefinitions.apikey Bearer
// @in   header
// @name Authorization
// @description Use "Bearer <token>"
```

For multi-environment deployments, set host/basepath at runtime instead of hard-coding:

```go
import docs "github.com/acme/myapi/docs"

func main() {
    docs.SwaggerInfo.Host     = os.Getenv("API_HOST")
    docs.SwaggerInfo.BasePath = "/api/v1"
    // ...
}
```

## Operation Annotations

```go
// GetOrder godoc
// @Summary      Get an order by ID
// @Tags         orders
// @Produce      json
// @Param        id   path  string  true  "Order ID (UUID)"
// @Success      200  {object}  api.OrderResponse
// @Failure      404  {object}  api.ErrorResponse
// @Router       /orders/{id} [get]
// @Security     Bearer
func GetOrder(c *gin.Context) { /* ... */ }
```

**`@Param`:** `@Param <name> <in> <type> <required> "<desc>" [attributes]` β€” `<in>` is one of `path`, `query`, `body`, `header`, `formData`. Useful attributes: `default(v)`, `minimum(n)`, `maximum(n)`, `Enums(a,b,c)`, `example(v)`, `collectionFormat(multi)`.

**`@Success` / `@Failure`:** `@<kw> <code> {<kind>} <type> "<desc>"` β€” `{object}` (struct), `{array}` (slice), or a primitive (`string`, `integer`). Generics (swag v2): `api.Response[model.Order]`. Composition: `api.Response{data=model.Order}`.

> Read [references/annotations.md](references/annotations.md) for the full annotation grammar, edge cases, and security definitions.

## Security

Declare schemes once globally (`@securityDefinitions.apikey Bearer`, `@securityDefinitions.oauth2.authorizationCode`, `@securityDefinitions.basic`) and apply per endpoint:

```go
// @Security Bearer
// @Security OAuth2[read, write]
// @Security BasicAuth && Bearer   // both required (AND)
```

Endpoints without `@Security` are documented as public β€” match the implementation.

## Struct Tags

Enrich models without changing their Go type. Common tags: `example`, `enums:"a,b,c"`, `minimum`/`maximum`, `minLength`/`maxLength`, `format`, `swaggertype` (override detected type, e.g. `time.Time` β†’ string), `swaggerignore:"true"`, and `extensions:"x-nullable,x-deprecated=true"`.

```go
type CreateOrderRequest struct {
    Status   string    `json:"status" enums:"pending,paid,shipped"`
    Total    int64     `json:"total" minimum:"0" example:"19999"`
    PlacedAt time.Time `json:"placed_at" swaggertype:"string" format:"date-time"`
    Internal string    `json:"-" swaggerignore:"true"`
}
```

> Read [references/struct-tags.md](references/struct-tags.md) for type overrides (`time.Time`, `uuid.UUID`, `decimal.Decimal`, custom scalars) and NULL handling.

## Make Target

```makefile
.PHONY: docs
docs:
	swag fmt
	swag init -g cmd/api/main.go --parseDependency --parseInternal

check-docs: docs
	@git diff --quiet docs || (echo "docs/ is stale; run make docs"; exit 1)
```

Run `make check-docs` in CI to catch annotation drift before merge.

## Anti-Patterns

| Anti-pattern | Why it hurts | Do this instead |
|---|---|---|
| Forgetting `_ "yourmod/docs"` | UI loads empty, no errors | Add the blank import in main |
| `@Param body string` | swag cannot derive a schema from a primitive | Use a named struct |
| Stale `docs/` after handler change | Docs lie to clients | Regenerate in CI; fail on drift |
| General info in wrong file | Spec has no title/host | Use `-g <file>` or move to main |
| `{object} map[string]any` | swag silently empty | Define a wrapper struct |
| No `@Security` on protected route | UI shows no lock icon | Add `@Security` everywhere auth is required |
| Multi-word `@Tags` unquoted | Tags split on whitespace | Quote: `@Tags "order management"` |
| Exposing `/swagger/*` in production unconditionally | Public API surface map | Gate behind env flag or auth |

## Verification Checklist

- [ ] `swag init` runs clean (no warnings)
- [ ] `docs/` is committed and up-to-date with handlers
- [ ] Every handler has `@Summary`, `@Router`, and at least one `@Success`
- [ ] Every protected handler has `@Security`
- [ ] Request bodies are named structs (no `map`, no primitives)
- [ ] Generic / nested response wrappers are spelled correctly (`Response[T]` or `Response{data=T}`)
- [ ] `/swagger/*` is gated in production (env flag or auth middleware)
- [ ] CI fails when `docs/` drifts from annotations

## References

- [references/swag-cli.md](references/swag-cli.md) β€” CLI flags, parsing options, Makefile patterns
- [references/annotations.md](references/annotations.md) β€” full annotation grammar with examples
- [references/struct-tags.md](references/struct-tags.md) β€” type overrides, time/UUID/decimal handling
- [references/anti-patterns.md](references/anti-patterns.md) β€” detailed walkthrough of each failure mode

Files in this skill

  • SKILL.md8.1 KB
  • references/annotations.md4.6 KB
  • references/anti-patterns.md4 KB
  • references/struct-tags.md4.6 KB
  • references/swag-cli.md3.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.