Install
$ agentstack add skill-muratmirgun-gophers-go-swagger ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
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
- Docs are a contract. A field documented as required is the API's promise; a mismatch with the implementation is a bug.
- Annotations live next to handlers. Not in a separate
docs/folder — comments rot when separated from code. - Regenerate on every change.
swag initis part of the build (go generateor a Makefile target). Staledocs/is worse than no docs. - The
docspackage must be imported. A blank import (_ "yourmod/docs") registers the spec at process start. - Use named structs for request/response bodies. swag cannot derive a schema from
map[string]anyor a primitive type. - Security definitions match implementation. If the API enforces JWT, declare
@securityDefinitions.apikey Bearerand annotate every protected endpoint with@Security Bearer.
Install and Bootstrap
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:
// 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:
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):
// @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 "
For multi-environment deployments, set host/basepath at runtime instead of hard-coding:
import docs "github.com/acme/myapi/docs"
func main() {
docs.SwaggerInfo.Host = os.Getenv("API_HOST")
docs.SwaggerInfo.BasePath = "/api/v1"
// ...
}
Operation Annotations
// 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 "" [attributes] — ` 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: @ {} "" — {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:
// @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".
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
.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 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 initruns 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]orResponse{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
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: muratmirgun
- Source: muratmirgun/gophers
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.