/cli-generate — Auto-Generate Agent-Ready CLIs
Generate a complete, production-grade CLI from any web/SaaS codebase in 5 phases.
Quick start: Run /cli-generate inside any project directory. It auto-detects the project type and generates a CLI.
What it generates:
- TypeScript CLI with Commander.js
- Dual output: pretty tables for humans, JSON for AI agents
- Auth system with multi-account profiles
doctor command for diagnostics
whoami command for auth status
- Single
.cjs bundle via esbuild
- SKILL.md for AI agent discoverability
- README.md with install, commands, output modes
npx instant execution ready
Phase 1: Detect Project Type
Scan the codebase to determine what kind of project this is. Read references/detection-matrix.md for the full detection logic.
Two-tier detection:
Tier 1 (pattern-based): Check for known frameworks first — MCP SDK, OpenAPI specs, Next.js routes, Express/Fastify. These have mechanical extraction rules.
Tier 2 (LLM-native): If Tier 1 doesn't match, READ THE CODE. Claude can understand any language — Python Flask, Go Gin, Ruby Rails, Rust Actix, gRPC protos, GraphQL schemas. Scan entry points, find route handlers/endpoints/RPC definitions, and extract the API surface.
Launch parallel searches:
- Identify language from manifest files (package.json, go.mod, requirements.txt, Cargo.toml, etc.)
- Check for Tier 1 matches (MCP SDK, OpenAPI spec, Next.js routes, Express/Fastify)
- If no Tier 1 match: read entry points and routing files, extract endpoints by reading the actual code
- Identify auth pattern (API key, Bearer token, env var, session, none)
Output: Detection report with:
- Project type and language
- List of endpoints/tools found (name, method, params, description)
- Auth pattern detected
- Suggested CLI name
Present findings to user. Asking the user to describe the API is the LAST resort — only if Claude genuinely cannot find endpoints after reading the code.
Phase 2: Plan CLI Structure
Map each detected endpoint/tool to a CLI command. Read references/command-patterns.md for mapping rules.
Generate a plan:
CLI: {name}-cli
Commands:
{name}-cli login — Authenticate with API key
{name}-cli logout — Remove credentials
{name}-cli whoami — Show auth status
{name}-cli doctor — Run diagnostic checks
{name}-cli {command-1} — {description}
{name}-cli {command-2} — {description}
...
Global flags: --json, --quiet, --api-key, --profile, --verbose
Auth: {API_KEY_ENV_VAR} env var + ~/.config/{name}-cli/credentials.json
Naming rules:
- Command names: kebab-case, verb-noun or just noun (e.g.,
list-users, send-email, mrr)
- Skip internal/health/webhook endpoints
- Group related endpoints if >20 commands (e.g.,
users list, users get, users create)
Present plan to user. Wait for approval before generating code.
Phase 3: Scaffold Infrastructure
Generate the fixed boilerplate files. These are identical for every CLI — only names change. Read references/cli-architecture.md for the exact file contents.
Files to generate:
Config files (project root)
package.json — deps: commander, @commander-js/extra-typings, @clack/prompts, picocolors, esbuild (dev), tsx (dev), typescript (dev), @types/node (dev), plus any project-specific SDK
tsconfig.json — ES2022, bundler moduleResolution, strict
build.mjs — esbuild bundle to single dist/cli.cjs with shebang
.gitignore — node_modules, dist, .env, *.tgz, .DS_Store
LICENSE — MIT
Infrastructure files (src/lib/)
constants.ts — VERSION, CLI_NAME, CONFIG_DIR_NAME, USER_AGENT
config.ts — XDG config, profiles, auth chain (flag > env > file), GlobalOpts
output.ts — ExitCode enum, shouldOutputJson, outputResult, outputError, outputFormatted
table.ts — hand-rolled column-aligned table renderer
tty.ts — isInteractive() terminal detection
spinner.ts — braille spinner for async operations
format.ts — CSV and Markdown export formatters
banner.ts — ASCII art banner (generated via npx figlet-cli)
Customization points (change per project):
constants.ts: CLI_NAME, CONFIG_DIR_NAME
config.ts: env var names (e.g., {NAME}_API_KEY, {NAME}_PROFILE), GlobalOpts fields
banner.ts: ASCII art — always generate with npx figlet-cli -f "ANSI Shadow" "{cli-name}". Never hand-draw ASCII art.
package.json: name, description, keywords, repository, project-specific dependencies
After scaffolding, run npm install and npm run build to verify.
Phase 4: Generate Commands
For each endpoint in the plan, generate a command file in src/commands/. Read references/command-patterns.md for the exact patterns per project type.
Every command follows this pattern:
import { Command } from '@commander-js/extra-typings'
import type { GlobalOpts } from '../lib/config.js'
import { resolveApiKey } from '../lib/config.js'
import { shouldOutputJson, outputError, ExitCode } from '../lib/output.js'
import { withSpinner } from '../lib/spinner.js'
export function make{Name}Command(globalOpts: () => GlobalOpts): Command {
return new Command('{command-name}')
.description('{description}')
.action(async (cmdOpts) => {
const opts = globalOpts()
const apiKey = resolveApiKey(opts)
if (!apiKey) {
outputError({ code: 'AUTH', message: 'No API key. Run `{cli-name} login` or set {ENV_VAR}.' }, opts)
process.exit(ExitCode.AUTH_ERROR)
}
try {
const result = await withSpinner('Fetching...', () => callApi(apiKey, cmdOpts), opts)
if (shouldOutputJson(opts)) {
process.stdout.write(JSON.stringify(result, null, 2) + '\n')
return
}
// Human output (tables, formatted text, etc.)
} catch (err) {
outputError({ code: 'API', message: err instanceof Error ? err.message : 'Unknown error' }, opts)
process.exit(ExitCode.API_ERROR)
}
})
}
Also generate:
src/commands/login.ts — interactive auth with @clack/prompts
src/commands/logout.ts — remove credentials
src/commands/whoami.ts — show auth status
src/commands/doctor.ts — CLI version, Node.js version, API key check, connection test
src/index.ts — Commander program with all global options, register all commands
src/core/client.ts — API client (HTTP fetch wrapper or SDK instantiation)
src/core/types.ts — TypeScript interfaces for API responses
After generating, run npm run build and npx tsc --noEmit to verify.
Phase 5: Verify & Ship
Run the verification checklist:
npm run build — clean build, produces dist/cli.cjs
node dist/cli.cjs --version — prints version
node dist/cli.cjs --help — shows all commands
node dist/cli.cjs (no args) — shows banner + help
node dist/cli.cjs doctor --json — outputs valid JSON
- Bundle size check:
ls -lh dist/cli.cjs (target: <500 KB)
Generate SKILL.md for AI agent discoverability:
- List all commands with JSON output schemas
- Document auth setup
- Include common workflows
- Document exit codes
Generate README.md:
- Banner from
banner.ts (plain text, no ANSI)
- Command tables match Commander
.description() strings
- Quick start: 2-3 commands to first value
Fix any build/type errors. Present the final CLI to the user.
Gotchas
- MCP Zod schemas don't map 1:1 to Commander options.
z.array(z.string()) needs special handling — use --items item1,item2 with .split(','). z.object() needs --data '{json}' with JSON.parse().
- OpenAPI specs can have hundreds of endpoints. Only generate commands for paths with
operationId. Skip paths without it. If >30 commands, group by tag into subcommands.
- Auth validation differs per project. MCP servers often don't need auth. APIs need a health check endpoint. Don't assume
accounts.retrieve() exists — find the lightest endpoint to validate the key.
- Restricted API keys may lack permissions. Always wrap auth validation in try/catch with a fallback to a simpler endpoint.
picocolors uses ANSI codes that break padEnd(). Never call .padEnd() on colored strings. Pad first, then color.
- ESM imports need
.js extensions. Every import must end with .js even though source is .ts.
process.stdout.isTTY is undefined when piped. shouldOutputJson checks this — never skip it.
- Don't add chalk, ora, boxen, figlet, or ink. picocolors + hand-rolled output is the pattern.
- Never hand-draw ASCII art. Always run
npx figlet-cli -f "ANSI Shadow" "{name}" via Bash.
Rules
- Always present the plan (Phase 2) before generating code. Never skip to Phase 3.
- The lib/ files are identical every time. Don't reinvent them. Copy from the architecture reference.
- Every command gets
--json support. No exceptions.
- The build must pass before presenting to the user. Run
npm run build and fix errors.
- 5 production deps max (excluding project-specific SDK): commander, @commander-js/extra-typings, @clack/prompts, picocolors, and optionally simple-ascii-chart.
- Hand-roll visual output. No table libraries, no chart libraries, no box-drawing libraries.
Source: progrmoiz/skills — distributed by TomeVault.
1---2name: cli-generate3description: Auto-generate agent-ready CLIs from any codebase in any language. Reads your project's source code — MCP servers, OpenAPI specs, Next.js, Express, Flask, Go, Rails, gRPC, GraphQL, or any API — and generates a complete TypeScript CLI with --json output, dual TTY/JSON mode, auth profiles, doctor command, and esbuild bundling. Use when asked to 'generate a CLI', 'create a CLI for this project', 'make this agent-ready', or 'add a CLI'. Use when this capability is needed.4---56# /cli-generate — Auto-Generate Agent-Ready CLIs78Generate a complete, production-grade CLI from any web/SaaS codebase in 5 phases.910**Quick start:** Run `/cli-generate` inside any project directory. It auto-detects the project type and generates a CLI.1112**What it generates:**13- TypeScript CLI with Commander.js14- Dual output: pretty tables for humans, JSON for AI agents15- Auth system with multi-account profiles16- `doctor` command for diagnostics17- `whoami` command for auth status18- Single `.cjs` bundle via esbuild19- SKILL.md for AI agent discoverability20- README.md with install, commands, output modes21- `npx` instant execution ready2223---2425## Phase 1: Detect Project Type2627Scan the codebase to determine what kind of project this is. Read [references/detection-matrix.md](references/detection-matrix.md) for the full detection logic.2829**Two-tier detection:**3031**Tier 1 (pattern-based):** Check for known frameworks first — MCP SDK, OpenAPI specs, Next.js routes, Express/Fastify. These have mechanical extraction rules.3233**Tier 2 (LLM-native):** If Tier 1 doesn't match, READ THE CODE. Claude can understand any language — Python Flask, Go Gin, Ruby Rails, Rust Actix, gRPC protos, GraphQL schemas. Scan entry points, find route handlers/endpoints/RPC definitions, and extract the API surface.3435**Launch parallel searches:**361. Identify language from manifest files (package.json, go.mod, requirements.txt, Cargo.toml, etc.)372. Check for Tier 1 matches (MCP SDK, OpenAPI spec, Next.js routes, Express/Fastify)383. If no Tier 1 match: read entry points and routing files, extract endpoints by reading the actual code394. Identify auth pattern (API key, Bearer token, env var, session, none)4041**Output:** Detection report with:42- Project type and language43- List of endpoints/tools found (name, method, params, description)44- Auth pattern detected45- Suggested CLI name4647Present findings to user. **Asking the user to describe the API is the LAST resort** — only if Claude genuinely cannot find endpoints after reading the code.4849---5051## Phase 2: Plan CLI Structure5253Map each detected endpoint/tool to a CLI command. Read [references/command-patterns.md](references/command-patterns.md) for mapping rules.5455**Generate a plan:**56```57CLI: {name}-cli58Commands:59 {name}-cli login — Authenticate with API key60 {name}-cli logout — Remove credentials61 {name}-cli whoami — Show auth status62 {name}-cli doctor — Run diagnostic checks63 {name}-cli {command-1} — {description}64 {name}-cli {command-2} — {description}65 ...6667Global flags: --json, --quiet, --api-key, --profile, --verbose68Auth: {API_KEY_ENV_VAR} env var + ~/.config/{name}-cli/credentials.json69```7071**Naming rules:**72- Command names: kebab-case, verb-noun or just noun (e.g., `list-users`, `send-email`, `mrr`)73- Skip internal/health/webhook endpoints74- Group related endpoints if >20 commands (e.g., `users list`, `users get`, `users create`)7576Present plan to user. Wait for approval before generating code.7778---7980## Phase 3: Scaffold Infrastructure8182Generate the fixed boilerplate files. These are **identical for every CLI** — only names change. Read [references/cli-architecture.md](references/cli-architecture.md) for the exact file contents.8384**Files to generate:**8586### Config files (project root)87- `package.json` — deps: commander, @commander-js/extra-typings, @clack/prompts, picocolors, esbuild (dev), tsx (dev), typescript (dev), @types/node (dev), plus any project-specific SDK88- `tsconfig.json` — ES2022, bundler moduleResolution, strict89- `build.mjs` — esbuild bundle to single `dist/cli.cjs` with shebang90- `.gitignore` — node_modules, dist, .env, *.tgz, .DS_Store91- `LICENSE` — MIT9293### Infrastructure files (`src/lib/`)94- `constants.ts` — VERSION, CLI_NAME, CONFIG_DIR_NAME, USER_AGENT95- `config.ts` — XDG config, profiles, auth chain (flag > env > file), GlobalOpts96- `output.ts` — ExitCode enum, shouldOutputJson, outputResult, outputError, outputFormatted97- `table.ts` — hand-rolled column-aligned table renderer98- `tty.ts` — isInteractive() terminal detection99- `spinner.ts` — braille spinner for async operations100- `format.ts` — CSV and Markdown export formatters101- `banner.ts` — ASCII art banner (generated via `npx figlet-cli`)102103**Customization points** (change per project):104- `constants.ts`: CLI_NAME, CONFIG_DIR_NAME105- `config.ts`: env var names (e.g., `{NAME}_API_KEY`, `{NAME}_PROFILE`), GlobalOpts fields106- `banner.ts`: ASCII art — **always generate with `npx figlet-cli -f "ANSI Shadow" "{cli-name}"`**. Never hand-draw ASCII art.107- `package.json`: name, description, keywords, repository, project-specific dependencies108109After scaffolding, run `npm install` and `npm run build` to verify.110111---112113## Phase 4: Generate Commands114115For each endpoint in the plan, generate a command file in `src/commands/`. Read [references/command-patterns.md](references/command-patterns.md) for the exact patterns per project type.116117**Every command follows this pattern:**118119```typescript120import { Command } from '@commander-js/extra-typings'121import type { GlobalOpts } from '../lib/config.js'122import { resolveApiKey } from '../lib/config.js'123import { shouldOutputJson, outputError, ExitCode } from '../lib/output.js'124import { withSpinner } from '../lib/spinner.js'125126export function make{Name}Command(globalOpts: () => GlobalOpts): Command {127 return new Command('{command-name}')128 .description('{description}')129 .action(async (cmdOpts) => {130 const opts = globalOpts()131 const apiKey = resolveApiKey(opts)132 if (!apiKey) {133 outputError({ code: 'AUTH', message: 'No API key. Run `{cli-name} login` or set {ENV_VAR}.' }, opts)134 process.exit(ExitCode.AUTH_ERROR)135 }136137 try {138 const result = await withSpinner('Fetching...', () => callApi(apiKey, cmdOpts), opts)139140 if (shouldOutputJson(opts)) {141 process.stdout.write(JSON.stringify(result, null, 2) + '\n')142 return143 }144145 // Human output (tables, formatted text, etc.)146 } catch (err) {147 outputError({ code: 'API', message: err instanceof Error ? err.message : 'Unknown error' }, opts)148 process.exit(ExitCode.API_ERROR)149 }150 })151}152```153154**Also generate:**155- `src/commands/login.ts` — interactive auth with @clack/prompts156- `src/commands/logout.ts` — remove credentials157- `src/commands/whoami.ts` — show auth status158- `src/commands/doctor.ts` — CLI version, Node.js version, API key check, connection test159- `src/index.ts` — Commander program with all global options, register all commands160- `src/core/client.ts` — API client (HTTP fetch wrapper or SDK instantiation)161- `src/core/types.ts` — TypeScript interfaces for API responses162163After generating, run `npm run build` and `npx tsc --noEmit` to verify.164165---166167## Phase 5: Verify & Ship168169Run the verification checklist:1701711. `npm run build` — clean build, produces `dist/cli.cjs`1722. `node dist/cli.cjs --version` — prints version1733. `node dist/cli.cjs --help` — shows all commands1744. `node dist/cli.cjs` (no args) — shows banner + help1755. `node dist/cli.cjs doctor --json` — outputs valid JSON1766. Bundle size check: `ls -lh dist/cli.cjs` (target: <500 KB)177178**Generate SKILL.md** for AI agent discoverability:179- List all commands with JSON output schemas180- Document auth setup181- Include common workflows182- Document exit codes183184**Generate README.md:**185- Banner from `banner.ts` (plain text, no ANSI)186- Command tables match Commander `.description()` strings187- Quick start: 2-3 commands to first value188189Fix any build/type errors. Present the final CLI to the user.190191---192193## Gotchas194195- **MCP Zod schemas don't map 1:1 to Commander options.** `z.array(z.string())` needs special handling — use `--items item1,item2` with `.split(',')`. `z.object()` needs `--data '{json}'` with `JSON.parse()`.196- **OpenAPI specs can have hundreds of endpoints.** Only generate commands for paths with `operationId`. Skip paths without it. If >30 commands, group by tag into subcommands.197- **Auth validation differs per project.** MCP servers often don't need auth. APIs need a health check endpoint. Don't assume `accounts.retrieve()` exists — find the lightest endpoint to validate the key.198- **Restricted API keys may lack permissions.** Always wrap auth validation in try/catch with a fallback to a simpler endpoint.199- **`picocolors` uses ANSI codes that break `padEnd()`.** Never call `.padEnd()` on colored strings. Pad first, then color.200- **ESM imports need `.js` extensions.** Every import must end with `.js` even though source is `.ts`.201- **`process.stdout.isTTY` is undefined when piped.** `shouldOutputJson` checks this — never skip it.202- **Don't add chalk, ora, boxen, figlet, or ink.** picocolors + hand-rolled output is the pattern.203- **Never hand-draw ASCII art.** Always run `npx figlet-cli -f "ANSI Shadow" "{name}"` via Bash.204205---206207## Rules208209- **Always present the plan (Phase 2) before generating code.** Never skip to Phase 3.210- **The lib/ files are identical every time.** Don't reinvent them. Copy from the architecture reference.211- **Every command gets `--json` support.** No exceptions.212- **The build must pass before presenting to the user.** Run `npm run build` and fix errors.213- **5 production deps max** (excluding project-specific SDK): commander, @commander-js/extra-typings, @clack/prompts, picocolors, and optionally simple-ascii-chart.214- **Hand-roll visual output.** No table libraries, no chart libraries, no box-drawing libraries.215216---217> Source: [progrmoiz/skills](https://github.com/progrmoiz/skills) — distributed by [TomeVault](https://tomevault.io).218<!-- tomevault:4.0:skill_md:2026-05-20 -->