CLI tool
google/gnostic avatar
google/gnostic

gnostic: compiling OpenAPI descriptions into Protocol Buffers

A compiler for APIs described by the OpenAPI Specification with plugins for code generation and other API support tasks.

2,306 stars279 forksGoApache-2.0

At a glance

What is it?
gnostic reads a JSON or YAML OpenAPI document into generated protobuf models, resolves its internal references and reports errors. It is the compiler layer under several Google API tooling projects.
Who is it for?
gnostic is a good fit when your API description is a build artifact that other tools consume, rather than a file only humans read. The protobuf models give you typed access to an OpenAPI document, error reporting and reference resolution in one binary, and the plugin interface means linters and generators bolt on without patching the compiler.
Can I use it commercially?
Yes. Apache-2.0 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 57 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 September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Building the binary from a clone with make

The installation path is a source build, not a package download. The README's first step is a clone:

bash
git clone https://github.com/google/gnostic
cd gnostic

Step two is a precondition rather than an action: you need `protoc`, the Protocol Buffer compiler, already installed. The README links to the protobuf project for that. Without it the build fails during code generation, which is the single most common stumbling block for anyone trying gnostic for the first time.

Step three runs `make`, and this is the part worth understanding rather than just typing. The top of the Makefile shows what the default target does:

makefile
all:
	go generate ./...
	go get ./...
	go install ./...
	cd extensions/sample; make

`go generate` triggers the generation step, and per the README that invokes `COMPILE-PROTOS.sh`, which downloads the Go `protoc` plugin automatically. `go install` then places the command and every plugin in the repository on your `GOPATH/bin`. The Makefile also builds `extensions/sample`, so a first build produces more than the one binary you may have wanted.

To confirm the build, step four is `make test`. The Makefile clears the test cache first, with a comment explaining that some tests call separately built binaries, so a passing run really does exercise the compiled tools rather than reusing cached results.

Turning a petstore document into a binary description

The README's fifth step is the whole point of the tool in one line. Running gnostic against the bundled petstore example produces `petstore.pb` in the current directory, a binary Protocol Buffer encoding of the API description:

bash
gnostic --pb-out=. examples/v2.0/json/petstore.json

Note that the input is a local path into `examples/`, and the flag takes a directory rather than a filename. Step six shows that a URL works just as well, and that a second output format is available for inspection:

bash
gnostic --text-out=petstore.text https://raw.githubusercontent.com/google/gnostic/master/examples/v2.0/json/petstore.json

The text form is the readable one, and the README is clear that it is mainly for testing and debugging. The two-step workflow of the next example, binary out then a reader over the binary, is how you consume the result. `apps/report` is that sample application, and the README notes it is installed by the top-level Makefile:

bash
go install ./apps/report ## automatically installed by the top-level Makefile
report petstore.pb

Because the encoding is protobuf, that reader does not have to be written in Go. Any language with protobuf support can open `petstore.pb`, which is the whole reason for doing this rather than parsing the JSON yourself.

What the compiler does between reading and writing

The README describes four jobs, and they are the ones to judge the tool on. It reads OpenAPI descriptions into generated data structures. It reports errors. It resolves internal dependencies, meaning the `$ref` pointers inside a document get followed and the output is self-contained. And it writes the result in a binary form usable from any language protobuf supports, with a JSON or YAML reexport available when necessary.

The generated structures are the interesting design decision. Rather than parsing OpenAPI as a tree of maps, gnostic compiles to Go types with explicit fields for each element of the specification. The README frames the payoff as working with OpenAPI descriptions in type-safe ways, and singles out Go and Dart as the languages where that pays off most. In practice this is the difference between indexing a spec by nested string keys, where a typo becomes a runtime failure, and reading a field the compiler already checked.

Almost none of that Go code is written by hand. The README says the compilation code and the OpenAPI protobuf models are automatically generated from the OpenAPI JSON Schema, with the generator's source in `generate-gnostic/`. The generated files are checked in under `openapiv2/`, `openapiv3/` and `discovery/`, so you get them without running the generator. That regeneration step is optional and takes three commands:

bash
go install ./generate-gnostic
generate-gnostic --v2
generate-gnostic --v3
generate-gnostic --discovery

The `linters/` and `surface/` directories in the tree suggest a second dimension: checking a description against style rules rather than merely converting it.

The plugin interface and the vocabulary plugin

gnostic is less a single tool than a host for tools. Its plugin interface is explicitly modeled on protoc's own `plugin.proto`, which means a gnostic plugin is structurally the same shape of program as a protoc plugin: it reads a CodeGeneratorRequest from stdin and writes a CodeGeneratorResponse to stdout. That choice lowers the learning curve for anyone already writing protoc plugins, and it is why plugins can be written in any language.

Several plugins live in the repository's own `plugins/` directory, and the README points at two in separate repositories: `gnostic-grpc`, which generates an annotated protobuf description such that transcoding it yields an API conforming to a given OpenAPI document, and `gnostic-go-generator`, which is flagged as experimental and generates a Go client for an API. The reverse direction, protobuf back to OpenAPI, is handled by `protoc-gen-openapi` under `cmd/`.

A third bundled plugin, `gnostic-vocabulary`, is worth trying first because it needs no flags to understand:

bash
gnostic examples/v2.0/json/petstore.json --vocabulary_out=.

It produces `vocabulary.pb` and `vocabulary.json` in `examples/v2.0/json`, summarizing word usage in an API's interface. The format of the binary one is defined in `metrics/vocabulary.proto`. Word frequency is not a linter rule, but it is a cheap way to find undocumented or inconsistent terminology across a large description before anyone writes a real rule about it.

For low-dependency integration, the README points at `google/gnostic-models`, a lightweight distribution of just the generated protobuf models. Go projects that only want the types can import from there instead of pulling in the compiler.

Version history, the go.mod requirements, and the 1.0 question

The releases are informative and slightly awkward. `v0.6.6`, published 2022-01-22, was titled Module cleanup and fixed a series of problems with a multi-module configuration and its reversion. It also restored the `cmd` components to the main module so they could be installed independently, with `protoc-gen-openapi`, `report`, `report-messages`, `vocabulary-operations`, `disco` and several others installable at `@latest`. If you hit an install failure with an old tag, that release note is the explanation.

`v0.6.8` in April 2022 added the ability to use proto annotations to add fragments to generated OpenAPI documents, and fixed string maps that were not properly exported from the `ToRawInfo()` methods in the v2 and v3 packages. The most recent release is `v0.7.0` on 2023-10-01, which lists no notes at all.

Meanwhile `go.mod` requires Go 1.24.6 and pulls in `gnostic-models v0.7.0`, `go-cmp v0.6.0`, `protobuf v1.36.7`, `go-jsonschema` and `docopt-go`, which tells you the current tree is built against a much newer toolchain than the 2022 releases. Copyright runs 2017-2020 and the license is Apache 2.0.

The disclaimer is the sentence that should shape your plan. Until there is a 1.0 release, the project asks that you treat it as prerelease software and work in progress, and asks dependent projects to refer to tagged releases for stable builds. The last push was on 2026-08-10, so the code is moving even though the release cadence is slow and the version stays below 1.0. That combination is normal for infrastructure tools and means your upgrade cost is a small deliberate exercise rather than something automatic.

Where gnostic sits against plain protobuf and standalone linters

The honest comparison is with two things a team might otherwise do. The first is writing a protobuf definition by hand, which is what most teams still do for internal APIs. That gives you full control and zero dependencies, and it works well until the service gains enough endpoints that hand-maintaining the descriptor becomes the bottleneck. gnostic inverts the direction: you write the OpenAPI document, since that is what people and gateways consume anyway, and the descriptor is derived from it.

The second comparison is with a dedicated OpenAPI linter. A linter reads your document and reports style violations; gnostic reads it, validates it against the schema, resolves references and then hands a typed representation to plugins. If all you need is to catch a missing `description` on an operation, a linter is a smaller dependency and gives better rules. gnostic earns its extra weight when you need to do something with the resolved model, which includes generating a server, transcoding to gRPC, or producing documentation from the same source of truth.

Against the other OpenAPI tooling ecosystem, the distinguishing detail is that gnostic's models are protobuf. That means the output loads with the protobuf runtime you already have, and that a plugin interface modeled on protoc's is a familiar contract. Against competing OpenAPI parsers that emit plain Go structs or a JSON model, the trade is a binary intermediate format and a heavier build in exchange for portability and a shared plugin protocol.

The catch is the one the disclaimer names. Because there is no 1.0, you are depending on a project that asks for caution, and because the compiler code is generated, an upgrade can change generated model shapes underneath code you wrote against them. Pin a tag and read the diff in `openapiv2/` and `openapiv3/` when you move.

Editorial conclusion

gnostic is a good fit when your API description is a build artifact that other tools consume, rather than a file only humans read. The protobuf models give you typed access to an OpenAPI document, error reporting and reference resolution in one binary, and the plugin interface means linters and generators bolt on without patching the compiler. Two things argue against it. The project asks consumers to treat it as prerelease work and to pin tagged releases, and there is still no 1.0. Build from a tag, start with the `apps/report` sample against `examples/v2.0/json/petstore.json`, and read the plugin interface in `plugins/plugin.proto` before deciding whether a separate OpenAPI linter already covers your rules.

Frequently asked questions

What is gnostic and what does it convert?

gnostic is a Go command line tool that converts JSON and YAML OpenAPI descriptions to and from Protocol Buffer representations. It reads a description into generated data structures, reports errors, resolves internal dependencies and writes a binary form usable from any language protobuf supports.

How do I build gnostic from source?

Clone the repository, make sure `protoc` is installed, then run `make`. The default target runs `go generate`, which triggers `COMPILE-PROTOS.sh` to download the Go protoc plugin and generate support code, then installs the command and its plugins. Run `make test` afterwards to verify the build.

How do I write a plugin for gnostic?

gnostic's plugin interface is modeled on protoc's `plugin.proto` and described in `plugins/plugin.proto`, so a plugin reads a CodeGeneratorRequest and writes a CodeGeneratorResponse. Several are in the `plugins` directory, and `gnostic-vocabulary` is the simplest one to try, run with `--vocabulary_out=.`.

Is gnostic stable enough to depend on?

The README asks that you treat it as prerelease software until there is a 1.0 release, and asks dependent projects to refer to tagged releases for stable builds. The most recent release is v0.7.0 from 2023-10-01, so pinning a tag rather than tracking the default branch is the approach the project itself requests.

Official sources

  1. google/gnostic on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
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/google-gnostic.svg)](https://hysenlabs.com/projects/google-gnostic)