Open-source project
swaggo/swag avatar
swaggo/swag

swaggo/swag: generating Swagger 2.0 docs from Go annotations

Automatically generate RESTful API documentation with Swagger 2.0 for Go.

13,039 stars1,547 forksGoMIT

At a glance

What is it?
swaggo/swag turns comment annotations in Go source into Swagger 2.0 documentation, and its plugins wire the result into frameworks like Gin. It is a code-generation step, not a runtime library, and that distinction decides most of its trade-offs.
Who is it for?
Adopt swaggo/swag if your Go API already has a Gin or similar router and you want documentation generated from annotations in the same files as the handlers, accepting Swagger 2.0 as the output. Do not adopt it if you need OpenAPI 3.0 output, or if you cannot commit to keeping annotations in sync, because nothing in the tool detects a stale docs folder.
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 received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem swaggo/swag solves for Go API teams

A Go HTTP handler is ordinary code. The route, the request body type and the response type are visible to the compiler but invisible to anything that reads documentation. Without a generator, someone has to write the API description by hand and then keep it aligned with the structs as they change.

swaggo/swag takes a different route. The README states that it "converts Go annotations to Swagger Documentation 2.0." You write structured comments above your handler functions and above your main entry point, run a CLI, and get a docs folder containing docs.go, swagger.json and swagger.yaml. The audience is Go teams that already have a working service and want an API reference generated from the same repository rather than maintained beside it.

The tool is a build-time program, not a middleware. It never runs inside your server, so it adds no request-path cost and no runtime dependency to your binary beyond the generated docs package. That is the central design choice, and it explains both what works well and what does not.

How the parser turns comments into a Swagger 2.0 spec

The repository layout shows the pipeline. The cmd directory holds the CLI, gen holds the code generation, format holds the comment formatter, and the top level holds parser.go, field_parser.go, operation.go, schema.go and packages.go. Those files are the parsing engine: the tool walks Go source, reads the annotation comments, resolves the Go types referenced in them, and builds an in-memory representation that is finally serialized into the three output files.

The resolution step is where the real work happens. A response annotation can name a Go struct, and the parser then has to find that struct's definition, walk its fields, honour tags like swaggertype and swaggerignore, and decide how each field maps into a JSON schema. The CLI exposes flags that control how far this search goes, including --parseDependency and --parseDependencyLevel, which govern whether Go files inside dependency folders are parsed, and --parseInternal for internal packages. The default for dependency parsing is disabled, so a model defined in a separate module will not appear in the output unless you ask for it.

Two more flags shape the result. --propertyStrategy defaults to camelcase and controls how Go field names are rendered in the schema. --requiredByDefault makes every field required unless marked otherwise, which is a meaningful default change for teams whose existing spec treats fields as optional. The --overridesFile flag, defaulting to .swaggo, reads global type overrides, which is how the project handles custom types that the parser cannot infer on its own.

Installing swag and generating your first docs folder

The README gives three installation routes: go install, a Docker image, or a pre-compiled binary from the release page. Building from source needs Go 1.19 or newer according to the README, while the module file declares go 1.24.0, so the practical floor is the module's requirement if you build from a checkout.

The go install route is the shortest:

bash
go install github.com/swaggo/swag/cmd/swag@latest

If you prefer not to install a binary, the README offers a container invocation that mounts the current directory at /code, which matches the Dockerfile's WORKDIR:

bash
docker run --rm -v $(pwd):/code ghcr.io/swaggo/swag:latest

Once the binary is on your PATH, run it from the folder containing your main.go. The README's step is simply:

bash
swag init

This parses your comments and writes the docs folder plus docs/docs.go. The generated package has to be imported for its init function to run, and the README shows a blank import for that:

go
import _ "example-module-name/docs"

If your general API annotations do not live in main.go, point the tool at the right file with the -g flag, for example swag init -g http/api.go. The optional formatter, swag fmt, rewrites the annotation comments themselves, and the README asks that you upgrade to the latest version before using it.

Swagger 2.0 only, and other limits worth knowing before you adopt

The most consequential limitation is in the project description itself: swaggo/swag generates Swagger 2.0. It does not emit OpenAPI 3.0. If your consumers, gateway or client generator expect an OpenAPI 3 document, this tool produces the wrong artifact, and there is no flag in the documented CLI that changes the output version. Teams searching for an OpenAPI 3 path will not find one here.

The second limitation is the annotation model. Documentation lives in comments, so the compiler cannot check it. Rename a struct field and the annotation naming it may still parse, but a renamed handler or a deleted route leaves a stale entry that swag init will not flag as an error. The generated docs folder is a build artifact that can silently drift from the code until the next regeneration, and the README does not describe any staleness check or verification mode.

Third, dependency resolution is off by default. A model that lives in another module, or in a vendor folder, is skipped unless you pass --parseVendor, --parseDependency or --parseDependencyLevel. That default is defensible for speed, but it produces incomplete schemas that look complete, which is a worse failure than an outright error.

Finally, the release channel deserves attention. The most recent tags are v2.0.0-rc6 from 2026-09-13 and v2.0.0-rc5 from 2026-01-09, with v1.16.6 from 2025-07-29 as the last non-prerelease. The maintainers have been publishing release candidates for the v2 line for over a year. That is not abandonment, but anyone pinning a version should decide deliberately between the stable v1 line and a release candidate.

How swaggo/swag differs from go-swagger

The natural comparison is go-swagger, and the difference is where the specification comes from. swaggo/swag starts with Go source and annotations and derives the spec from them: your handlers are the source of truth, and the documentation follows. go-swagger, by contrast, is built around generating server code from a specification, so the spec is the input and the Go code is the output.

That inverts the workflow. With a spec-first generator, the API contract is reviewed and versioned before implementation, and the generated stubs constrain what the handlers can do. With swaggo/swag, the implementation comes first and the spec is extracted afterward, which suits teams that already have running services and want documentation without restructuring them. The cost is that the contract has no independent existence; it is always a projection of the current code.

Neither approach is universally better. If multiple teams need to agree on a contract before anyone writes a handler, spec-first fits. If you have an existing Go service and want a docs folder by the end of the afternoon, annotation-first fits, and that is the case swaggo/swag is built for.

Maintenance cost, releases and the MIT licence

The last push to the repository was on 2026-09-13, and the same day carries the v2.0.0-rc6 tag. The project is not archived. The release cadence on the v2 line has been roughly one release candidate per eight months across the two most recent tags, so upgrades arrive slowly and each one is a deliberate event rather than a routine pull.

The go.mod file carries retract directives for v1.16.0 and v1.9.0, both marked as published accidentally. That is a concrete reason to check which version your module graph resolves before you upgrade, because a version can exist in the proxy and still be retracted by the maintainers.

On the operational side, the upgrade cost is mostly regeneration. Because the output is a build artifact, a version bump means re-running swag init and reviewing the diff in swagger.json, which is a reviewable change if you commit the generated files. The Makefile shows the project's own expectations: a build target, a test target that runs coverage across the swag, cmd/swag, gen and format packages, and a fmt-check target that fails if gofmt would change anything. That is a conventional Go setup rather than an unusual one.

The licence is MIT, which is permissive and imposes no copyleft obligation on your own code. The generated docs folder is output of the tool rather than a copy of it, but how that interacts with your distribution model is a question for your own legal review, not something the repository settles.

Editorial conclusion

Adopt swaggo/swag if your Go API already has a Gin or similar router and you want documentation generated from annotations in the same files as the handlers, accepting Swagger 2.0 as the output. Do not adopt it if you need OpenAPI 3.0 output, or if you cannot commit to keeping annotations in sync, because nothing in the tool detects a stale docs folder. Before committing, verify three things: that swag init runs cleanly against your module layout, that the generated docs.go is imported exactly once, and that you are pinning a release rather than tracking master, since the newest published tag is v2.0.0-rc6.

Frequently asked questions

How can I use swaggo/swag with Gin?

The README has a dedicated section titled "How to use it with Gin" and states that swaggo/swag ships plugins for popular Go web frameworks so you can integrate it with an existing project using Swagger UI. The generation step itself is framework-independent: you annotate the handlers and run swag init.

How do I install swaggo/swag?

The README gives three options: go install github.com/swaggo/swag/cmd/swag@latest, the Docker image ghcr.io/swaggo/swag:latest, or a pre-compiled binary from the release page. Building from source requires Go, and the README states version 1.19 or newer.

Does swaggo/swag generate OpenAPI 3.0?

No. The project description and README both state that it converts Go annotations to Swagger Documentation 2.0, and the documented CLI options do not include an output-version switch.

What does the swag init command produce?

According to the README, running swag init in the project root parses your comments and generates the docs folder and docs/docs.go. The --outputTypes flag controls which of docs.go, swagger.json and swagger.yaml are written, defaulting to all three.

Why is my model missing from the generated documentation?

Dependency parsing is disabled by default. The CLI provides --parseDependency and --parseDependencyLevel to parse Go files inside dependency folders, and --parseVendor to include the vendor folder, so a model defined outside your parsed directories will not appear until one of those is set.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. swaggo/swag on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/swaggo-swag.svg)](https://hysenlabs.com/projects/swaggo-swag)