CLI tool
fabien0102/openapi-codegen avatar
fabien0102/openapi-codegen

openapi-codegen: type-safe fetchers and React Query hooks from a spec

A tool for generating code base on an OpenAPI schema.

635 stars82 forksTypeScriptLicense varies

At a glance

What is it?
openapi-codegen is a TypeScript code generator that turns an OpenAPI document into typed schemas, a typed fetcher and React Query components, with a plugin architecture so you can choose which generators run. The project publishes separate versioned packages for the CLI and the TypeScript plugin.
Who is it for?
openapi-codegen fits a TypeScript or React team whose backend is described by an OpenAPI document and who want the client and the types to come from the same source, since the whole point is that the generated fetcher and the schema types cannot drift apart.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 179 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

Three things you can generate, and one of them is the point

The repository describes itself as tooling to give you full type-safety around OpenAPI specs, and the list of outputs is short. You can generate TypeScript types. You can generate type-safe generic fetchers. And you can generate type-safe React Query hooks, with a link to the TanStack Query repository. The framing in the README is what makes the third item matter. A generic fetcher is already a common pattern and easy to write by hand, but a hook that knows the response type of a specific endpoint, with the query parameters typed, is where the type safety starts paying for itself. The example uses the Giphy spec as the running case, and the generated hooks include `useRandomGif`, a wrapper around `useQuery` with injected types, and `useSuspenseRandomGif`, the same thing with `useSuspense`.

The init and gen commands, and the files they leave behind

The workflow has two commands. The first initialises the generator, and it is interactive:

bash
   npx @openapi-codegen/cli init

The selections you make there are written to a generated `openapi-codegen.config.ts` file, and the README notes that you can change any of them later in that file. The second command starts the generation, taking a namespace:

bash
   npx openapi-codegen gen {namespace}

Afterwards you have four files. `{namespace}Fetcher.ts` defines the function that makes requests to your API. `{namespace}Context.tsx` is the context that provides that fetcher to other components. `{namespace}Components.tsx` holds the generated React Query components, if you selected React Query during initialisation. And `{namespace}Schemas.ts` holds the generated TypeScript types from the OpenAPI schemas. The namespace is doing real work here, because it is what keeps several APIs from colliding in one output directory, and it appears in every generated filename.

Which files get overwritten, and which do not

The README carries a warning that changes how you should set up your repository, and it is the sort of detail that costs an afternoon if you miss it. If `{namespace}Fetcher.ts` or `{namespace}Context.tsx` already exist in the output folder, they will not be replaced. However, `{namespace}Components.tsx` and `{namespace}Schemas.ts` will be regenerated each time based on the OpenAPI spec file provided. So the generated fetcher and the context are yours once you have them, and you can edit them, and the generated components and schemas are not, and they are replaced on every run. That split is deliberate. The fetcher and context are the files you are expected to adapt, since the fetcher by default uses the built-in Fetch API and you are free to change it to your fetching library of choice, Axios or Got, and the base URL has to be set to the server from your spec if one is configured, or specified by you if it is not. The schemas and components are pure function of the spec, so regenerating them is safe, and any manual edit you make to them is lost. Committing the generated output is therefore the sensible arrangement, and reviewing the diff on the schemas and components is where you spot an upstream change that broke your client.

The configuration file is where the flexibility lives

The README says the only thing you need to manage is the configuration, that everything is typed and self-documented, and then gives an example. The structure is a `defineConfig` call with one entry per API, and each entry has a `from` describing where the spec comes from, an `outputDir`, and a `to` callback that decides what gets generated:

ts
// openapi-codegen.config.ts
import { defineConfig } from "@openapi-codegen/cli";
import {
  generateSchemaTypes,
  generateReactQueryComponents,
} from "@openapi-codegen/typescript";

export default defineConfig({
  example: {
    // can be overridden from cli
    from: {
      source: "github",
      owner: "fabien0102",
      repository: "openapi-codegen",
      ref: "main",
      specPath: "examples/spec.yaml",
    },

    // can be overridden from cli
    outputDir: "src/queries",

    to: async (context) => {
      // You can transform the `context.openAPIDocument` here, can be useful to remove internal routes or fixing some known issues in the specs ;)

      // Generate all the schemas types (components & responses)
      const { schemasFiles } = await generateSchemaTypes(context, {
        /* config */
      });

      // Generate all react-query components
      await generateReactQueryComponents(context, {
        /* config*/
        schemasFiles,
      });
    },
  },
});

Two things in that file are worth pausing on. The `from` block points at a GitHub repository, an owner, a repository, a ref and a spec path, so the spec can be pulled from a remote repository at a given ref rather than a local file, and the comment says it can be overridden from the command line. And the `to` callback receives the parsed document, which the comment says you can transform, which the comment says is useful to remove internal routes or to fix known issues in the specs. That transform hook is the escape hatch for a spec that is technically valid and practically wrong, and it runs before generation, so it applies to every plugin in the chain.

Plugins decide what gets produced

The CLI supports generator plugins, and the README documents three of them. `generateSchemaTypes` generates all schema types for your specification, for both frontend and backend, and outputs `{namespace}Schemas.ts`. `generateFetchers` generates all fetchers with types, for the frontend, and outputs `{namespace}Fetchers.ts`. And `generateReactQueryComponents` generates React Query components for useQuery and useMutation, for the frontend, and outputs `{namespace}Components.ts`. The plugin set also generates a query function usable with most React Query functions, and the README gives the data loader case as `queryClient.fetchQuery(getYourQueryNameQuery({}))`. The last line of that section says you can import any generator into the `to` section, and that those can be the ones provided. So the plugin set is not closed, and the architecture is a set of composable generators over a shared document rather than a fixed pipeline.

Typing the awkward cases, skipToken and the query function

The generated hooks have to cope with the situations that make typed clients awkward, and the README shows how. The first is the parameter that is not yet known. There is support for `reactQuery.skipToken` to stay type-safe while you are waiting for params, so the hook can be called with a skip token instead of an empty parameter object, which is the pattern the library uses to avoid firing a request with missing inputs. The second is the case where you do not want a hook at all. You can use the query function directly for more advanced use cases, and the README shows creating a QueryClient and calling `queryClient.fetchQuery(randomGifQuery({}))`, importing the query from the generated components module. Both of these are places where most hand written clients leak `any` into the interface, and the fact that the generator emits them is the argument for using it rather than writing your own wrapper.

The workspace behind the two published packages

The repository is a monorepo with a `cli/` directory, a `plugins/` directory, an `examples/` directory with a frontend example, and the root files you would expect, with a lerna.json, a pnpm-workspace.yaml, a pnpm-lock.yaml, a release-please-config.json and a .release-please-manifest.json, an eslint config, a tsconfig and a husky directory. The root package.json is marked private with version 0.0.1, engines requiring Node 20 or greater, and the package manager pinned to pnpm 9.15.4. The scripts show the shape of the build, with separate build steps for the TypeScript plugin and the CLI, and a check script that runs the type, lint and prettier checks together. The dev dependencies are the usual modern TypeScript toolchain, with typescript 5.7.3, vitest for tests, eslint 9 and prettier 3, plus got and all-contributors. The published packages are versioned separately, and the release tags carry a language prefix, typescript-v11.3.0 for 2026-04-27 and typescript-v11.2.0 for 2026-02-14, which is how you tell the TypeScript plugin line from the CLI line at a glance.

Where this is the wrong choice

The limits are worth naming. First, this is a front end tool. The plugins are marked frontend or backend, and the fetcher is designed around the browser Fetch API and React Query, so a server side SDK in another language is out of scope and you would use a general purpose generator instead. Second, it is coupled to React Query. The value of the generated hooks depends on TanStack Query being in your stack, and if your data fetching is SWR, RTK Query or hand written, the fetcher output is the only part you want. Third, the generated files are the contract, and they churn. Every spec change regenerates the schemas and the components, so a busy upstream spec produces noisy diffs, and a team that dislikes large generated diffs will find that annoying. Fourth, the plugin set is small compared with a general purpose generator, so unusual spec features may not have a plugin, and the transform hook becomes the place where you patch around them. Fifth, the release model is unusual, with separately versioned packages under a monorepo and language-prefixed tags, so you need to be deliberate about which version of the CLI and which version of the plugin you install together.

Editorial conclusion

openapi-codegen fits a TypeScript or React team whose backend is described by an OpenAPI document and who want the client and the types to come from the same source, since the whole point is that the generated fetcher and the schema types cannot drift apart. It is the wrong choice if you need a server SDK in another language, if your spec is a large document that changes faster than you can regenerate, or if you want a general purpose OpenAPI generator with many language targets, since this one is aimed at the front end. Before you adopt it, commit the generated output to version control, read the warning about which files are overwritten on each run, and pin the CLI and the plugin to matching versions. The last push was on 2026-04-27 with typescript-v11.3.0 released the same day.

Frequently asked questions

What does openapi-codegen generate from an OpenAPI spec?

TypeScript types, a type-safe generic fetcher, and type-safe React Query hooks. The generated files are `{namespace}Schemas.ts` with the types, `{namespace}Fetcher.ts` with the request function, `{namespace}Context.tsx` providing the fetcher to components, and `{namespace}Components.tsx` with the React Query components.

How do I start using openapi-codegen?

Run `npx @openapi-codegen/cli init` to initialise the generator and answer the interactive questions, then run `npx openapi-codegen gen {namespace}` to generate. Your selections from the init step are written to `openapi-codegen.config.ts` and can be changed later.

Which generated files does openapi-codegen overwrite?

`{namespace}Components.tsx` and `{namespace}Schemas.ts` are regenerated each time from the spec, while `{namespace}Fetcher.ts` and `{namespace}Context.tsx` are not replaced if they already exist in the output folder, so you are free to edit those two.

Can I change the OpenAPI document before generation?

Yes. The `to` callback in the config receives the context and you can transform `context.openAPIDocument` there, which the README says is useful to remove internal routes or to fix known issues in the specs, and the transform runs before the generators produce the schemas and components.

Official sources

  1. fabien0102/openapi-codegen on GitHub
  2. Issues
  3. README
  4. 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/fabien0102-openapi-codegen.svg)](https://hysenlabs.com/projects/fabien0102-openapi-codegen)

Was this useful?