swag: the Go tool that turns comment annotations into a Swagger 2.0 tree
Automatically generate RESTful API documentation with Swagger 2.0 for Go.
At a glance
- What is it?
- Swag parses Go comments at build time and writes a docs package into your source tree, but that package only does something if you import it by hand, the install paths disagree about the required Go version, and the 2.0 line is still release candidates.
- Who is it for?
- Swag is a reasonable fit for teams that already write Go web services and want the specification generated from the source rather than maintained by hand, and the annotation vocabulary covers most of what a public API needs. Adopt it knowing three things: the generated docs package fails silently until something imports it, host and base path are compiled into the spec unless you override SwaggerInfo at runtime, and v2.0.0 exists only as release candidates.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 46 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- swaggo/swag13,053 ★ · +21
| Repository | 2026-09-22 | 2026-11-14 |
|---|---|---|
| swaggo/swag | 13k | 13.1k |
21 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
swag init writes docs.go that registers only if you import it
Swag does not read your handlers at runtime. It parses Go comments at build time and writes a docs directory plus docs/docs.go into your tree, and the instruction is to run swag init in the folder that holds main.go. That generated package has no effect until the program imports it, so an empty import has to be added by hand:
import _ "example-module-name/docs"Skip that line and the binary starts, the routes answer, and no specification is registered anywhere. When the general API annotations sit somewhere other than main.go, the -g flag points the parser at that file:
swag init -g http/api.goBecause the docs folder is generated output that lives inside your source tree, it shows up in review diffs and in merges like any other code you did not type.
Four ways to get the binary, each with a different catch
The shortest route is go install through the module proxy, which leaves no checkout behind:
go install github.com/swaggo/swag/cmd/swag@latestBuilding from source asks for Go 1.19 or newer. The container image is built from golang:1.24-alpine, compiles with CGO_ENABLED=0 and GOOS=linux, and ships as a binary copied into a scratch stage whose entrypoint is /bin/swag, so it carries no shell and no package manager. The published run command mounts your current directory:
docker run --rm -v $(pwd):/code ghcr.io/swaggo/swag:latestThe Dockerfile declares TARGETOS and TARGETARCH, exports them as GOOS and GOARCH, then the build line overrides GOOS with linux, so a cross-target build gets a Linux binary whatever you asked for. A pre-compiled binary from the release page is the fourth option and asks nothing of your toolchain. Building a checkout instead goes through the Makefile, where build compiles ./cmd/swag into a binary named swag, install shells out to go install, and the test target loops over four packages: swag, cmd/swag, gen and format.
Go 1.19 in the prose against go 1.24.0 in go.mod
The stated build requirement and the module file disagree. The project text says building from source needs Go 1.19 or newer, while go.mod opens with go 1.24.0 and the container build stage uses golang:1.24-alpine. Trust the 1.19 figure and the toolchain decides for you, because a Go install older than the module's go directive refuses to build it. The dependency list is worth reading before you pin anything: direct requirements include go-openapi/spec v0.22.1, urfave/cli/v2 v2.3.0, KyleBanks/depth v1.2.1, stretchr/testify v1.11.1, sigs.k8s.io/yaml v1.3.0 and golang.org/x/tools v0.26.0, while the indirect block drags in three yaml packages, blackfriday and seven go-openapi/swag subpackages.
v1.16.0 and v1.9.0 are retracted as accidental publishes
Two published versions are marked as mistakes inside go.mod itself. The retract block names v1.16.0 and v1.9.0, each carrying the comment published accidentally. A retract entry marks those versions as withdrawn, so a build script that pinned one of them should move to another version. It also means the tag list you read in the release page and the version list a resolver will actually accept are not the same list. The tags themselves run v1.16.6 from 2025-07-29, then v2.0.0-rc5 from 2026-01-09 and v2.0.0-rc6 from 2026-09-13, so the 2.0 line exists only as candidates.
-d sets the parse roots and pins general info to the first one
Three options decide what gets parsed and what gets skipped. The -d flag takes the directories you want to parse, comma separated, and carries a constraint that is easy to skim past: the general-info file must be in the first one. Point -d at a layout where main.go lives in a subdirectory and the parser has nowhere to read the title, version, host and base path from. --exclude takes directories and files to skip in the same comma-separated form, which is how vendored trees stay out of the output. -q makes the logger quiet and defaults to false, useful in CI where a parse warning otherwise disappears into the build log.
SwaggerInfo is the only runtime lever on host and base path
Everything about the specification's identity comes from comment tags, and by default those live in main.go. A general block sets @title, @version, @description and @termsOfService, carries @contact.name, @contact.url and @contact.email, adds @license.name and @license.url, and declares @host and @BasePath, with @securityDefinitions and @externalDocs entries available alongside. @host and @BasePath are the two that break between environments, because localhost:8080 with a /api/v1 prefix is not what any deployed instance looks like. The generated docs package exports a SwaggerInfo variable for exactly that reason, letting a program set title, description, version, host and base path at runtime. Both values are otherwise compiled into the spec at generation time.
Ten framework plugins live in other repositories entirely
Support for a web framework means adopting somebody else's repository, not importing a package from this one. The list covers gin, echo, buffalo, net/http, gorilla/mux and go-chi/chi under the swaggo organisation, plus flamingo from i-love-flamingo, fiber from gofiber, atreugo from Nerzal and hertz from hertz-contrib. None of them appear in go.mod, so swag generates the specification and each plugin serves it. The Gin walkthrough shows the two imports that bridge the gap:
import "github.com/swaggo/gin-swagger" // gin-swagger middleware
import "github.com/swaggo/files" // swagger embed filesThe first is the middleware, the second embeds the Swagger UI assets. Runnable examples sit in the repository under basic, celler, go-module-support, markdown, object-map-example and override. The parsing logic is split across parser.go, field_parser.go, operation.go, schema.go, spec.go and generics.go at the repository root, with the comment formatter in formatter.go and format/ and the output writer in gen/, so an annotation you need to extend has a file to extend it in.
Two 2.0.0 candidates, no stable tag, push dated 2026-09-30
Version 2.0 has never landed as a stable tag in the release list. What appears instead is v2.0.0-rc6 dated 2026-09-13 and v2.0.0-rc5 dated 2026-01-09, eight months apart, sitting above a stable v1.16.6 from 2025-07-29. The project is not archived and master took its last push on 2026-09-30, so the churn is current rather than abandoned. For a tool that writes files into your repository, that distinction decides whether you track master or hold at the last stable tag, because the init output lands in version control and a candidate release can change the shape of the generated files between two runs against unchanged source.
Editorial conclusion
Swag is a reasonable fit for teams that already write Go web services and want the specification generated from the source rather than maintained by hand, and the annotation vocabulary covers most of what a public API needs. Adopt it knowing three things: the generated docs package fails silently until something imports it, host and base path are compiled into the spec unless you override SwaggerInfo at runtime, and v2.0.0 exists only as release candidates. Check your Go version against go.mod, not the stated 1.19 floor, and pin a candidate deliberately.
Frequently asked questions
How can I use Swagger in Gin?
Run swag init first, then import github.com/swaggo/gin-swagger as the middleware and github.com/swaggo/files to embed the UI assets, and put your General API annotations in main.go. A complete example lives in the example/celler directory.
What Go version does swag need to build from source?
The project text says 1.19 or newer, while go.mod declares go 1.24.0 and the container build stage uses golang:1.24-alpine, so the module file is the stricter of the two.
What does swag init generate, and what do I have to do afterwards?
It writes a docs folder and docs/docs.go in the folder containing main.go. You then have to import the generated docs package yourself so that its init runs and the specification is registered.
Why was a pinned swag version withdrawn?
go.mod retracts v1.16.0 and v1.9.0, both annotated published accidentally, so both are marked as withdrawn versions of the module.
Which web frameworks can serve the output swag generates?
gin, echo, buffalo, net/http, gorilla/mux and go-chi/chi have plugins under the swaggo organisation, with flamingo, fiber, atreugo and hertz covered by partner projects in their own repositories.
Is swag at a stable 2.0 release yet?
No stable 2.0 tag shows in the release list. The 2.0 entries are v2.0.0-rc5 from 2026-01-09 and v2.0.0-rc6 from 2026-09-13, above the stable v1.16.6 from 2025-07-29.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/swaggo-swag)Star history chart for your README
[](https://hysenlabs.com/projects/swaggo-swag)Was this useful?