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
Global Installation (Recommended)
Install globally to run chowbea-axios from anywhere:
npm install -g chowbea-axiosyarn global add chowbea-axiospnpm add -g chowbea-axiosbun add -g chowbea-axiosVerify it works:
chowbea-axios --versionUsing npx (No Installation)
Run commands directly:
npx chowbea-axios init
npx chowbea-axios fetch
npx chowbea-axios watchnpx 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 initEnter 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 fetchOr, after init:
npm run api:fetchThis 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 errorFor 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 statusBefore 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.