chowbea-axios

Installation

Install chowbea-axios globally or use it directly with npx.

You need the CLI before you can stop hand-writing API types. This page gets you there — global install, npx, or "I already have Axios and I'm not starting over."

Prerequisites

  • Node.js 20 or higher (tested in CI on 20, 22, 24 across Linux, macOS, and Windows)
  • A project with package.json
  • An OpenAPI specification (v3.x) — endpoint URL or local file

chowbea-axios is ESM only. package.json declares "type": "module", so require("chowbea-axios") from a CommonJS file fails with ERR_REQUIRE_ESM. Use dynamic import() or migrate the importing file to ESM. The CLI binary works regardless of your project's module format.

Installation Options

Install globally to run chowbea-axios from anywhere:

npm install -g chowbea-axios
yarn global add chowbea-axios
pnpm add -g chowbea-axios
bun add -g chowbea-axios

Verify it works:

chowbea-axios --version

Using npx (No Installation)

Run commands directly:

npx chowbea-axios init
npx chowbea-axios fetch
npx chowbea-axios watch

npx downloads the package on first use. Subsequent runs are faster — unlike your manual type definitions, which get slower every sprint.

Dependencies

chowbea-axios installs axios in your project during init. No manual step.

Type generation is built in — no separate codegen packages. The CLI ships its own OpenAPI-to-TypeScript generator and writes files atomically.

Optional: Interactive Dashboard

Running chowbea-axios with no command launches an interactive TUI dashboard for fetch, generate, diff, validate, watch, plugins, and endpoint inspection. Requires Bun. Under Node, the CLI re-launches under Bun automatically; if Bun isn't installed, it falls back to headless mode with a hint. Headless commands (fetch, generate, watch, etc.) work under Node alone — use those in CI. See the dashboard guide.

Adding to an Existing Project

Already have Axios wired up with interceptors and battle scars? Fine. chowbea-axios generates an isolated client alongside your existing code. Migrate at your pace.

Initialize chowbea-axios

Run init in your project root:

npx chowbea-axios init

Enter your OpenAPI endpoint URL and choose an output folder (e.g., src/services/api). Init also adds api:* scripts to package.json.

Generate the typed client

Fetch your spec and generate:

npx chowbea-axios fetch

Or, after init:

npm run api:fetch

This creates a typed client in your chosen folder. Your existing Axios code is untouched.

Use both clients side by side

Old calls keep working. Use the generated client for new features or when you're already editing a file:

// Your existing code (still works)
import axios from 'axios';
const user = await axios.get('/api/users/123');

// New typed client (use for new work)
import { api } from '@/services/api';
import type { UserDto } from '@/services/api/_generated/api.contracts';

const { data, error } = await api.op.getUserById({ id: '123' });
// data is UserDto once you've handled error

For app structure beyond raw calls, see The Query Layer.

Migrate at your own pace

No big-bang rewrite required. Replace old Axios calls when you touch that code. Over time, the codebase becomes fully typed without a "API migration" epic on the roadmap.

Using Your Existing Axios Instance

Already have an instance with auth interceptors and custom config? Point the generated client at it.

Open api.instance.ts and swap the export:

// Before: generated instance
import axios from "axios";

export const axiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 30000,
});

// After: your existing instance
import { myAxiosInstance } from '@/lib/axios';

export const axiosInstance = myAxiosInstance;

The typed client uses your instance — interceptors, headers, and config intact.

api.instance.ts is never overwritten after initial creation. Your changes persist across regenerations.

Scripts You'll Use Daily

After init, your package.json includes:

{
  "scripts": {
    "api:fetch": "chowbea-axios fetch",
    "api:generate": "chowbea-axios generate",
    "api:watch": "chowbea-axios watch",
    "api:status": "chowbea-axios status",
    "api:validate": "chowbea-axios validate",
    "api:diff": "chowbea-axios diff"
  }
}

Run watch mode alongside your dev server so types stay in sync:

{
  "scripts": {
    "dev:all": "concurrently \"npm run api:watch\" \"npm run dev\""
  }
}

dev:all keeps the spec warm while you iterate. Highly recommended.

Verify Installation

Check that everything is wired up:

chowbea-axios status

Before your first fetch:

╭────────────────────────────────────────
│ Status
├────────────────────────────────────────

│ Config: api.config.toml (created)
│   endpoint: http://localhost:3000/docs/swagger/json
│   output: app/services/api

│ Spec:
│   cached: no - run 'chowbea-axios fetch' first
╰────────────────────────────────────────

If you see that, you're one api:fetch away from never writing interface User by hand again.

Next Steps

On this page