api2cli
npx skills add https://github.com/alexknowshtml/api2cli --skill api2cli
Agent 安装分布
Skill 文档
api2cli
Generate a working Node.js CLI from any API, then wrap it in a Claude Code skill. Discovers endpoints, scaffolds a dual-mode Commander.js CLI with a full-featured API client, and creates a skill folder so Claude knows how to use it.
Workflow
- Identify the API — user provides a docs URL, a live API base URL, or a peek-api capture
- Discover endpoints — parse docs, probe the API, or read a peek-api catalog
- Build endpoint catalog — normalize all discovered endpoints into a standard format
- Generate CLI — scaffold Commander.js CLI from the catalog
- User chooses destination — scaffold into current project or create standalone project
- Generate skill — create a SKILL.md that teaches Claude how to use the generated CLI
Step 1: Identify the API
Ask the user:
- “What API do you want to wrap? Share a docs URL, a base URL, or point me at a peek-api capture.”
Determine which discovery paths to use based on what they provide:
| Input | Discovery Path |
|---|---|
Docs URL (e.g., https://docs.stripe.com/api) |
Docs parsing + active probing |
Base URL (e.g., https://api.example.com/v1) |
Active probing |
peek-api capture dir (e.g., ./peek-api-linkedin/) |
Read existing catalog |
| Live website URL | Suggest running peek-api first, then active probing |
Also ask:
- “What auth does this API use?” (API key, Bearer token, cookies, OAuth, none)
- “Do you want this CLI in your current project or as a standalone project?”
Step 2: Discover Endpoints
Use all applicable discovery paths. Combine results into a single catalog.
Path A: Docs Parsing
- Fetch the docs URL with WebFetch
- Extract endpoint information: method, path, description, parameters, request/response examples
- Look for pagination patterns, auth requirements, rate limit info
- Follow links to sub-pages for individual endpoint docs if the main page is an index
Path B: Active Probing
- Check well-known paths for API specs:
/.well-known/openapi.json,/.well-known/openapi.yaml/openapi.json,/openapi.yaml,/swagger.json,/swagger.yaml/api-docs,/docs,/api/docs/graphql(with introspection query)
- Try
OPTIONSon the base URL and common resource paths - Probe common REST patterns:
/api/v1/,/api/v2/,/v1/,/v2/ - For each discovered resource, try standard CRUD:
GET /resources,GET /resources/:id,POST /resources, etc. - Parse response shapes to understand data models
- Check response headers for rate limit info (
X-RateLimit-*,Retry-After) - Check for pagination patterns in responses (
next,cursor,page,offset)
See references/discovery-strategies.md for detailed probing patterns.
Path C: peek-api Capture
- Read the capture directory:
endpoints.json,auth.json,CAPTURE.md - Parse endpoints into the standard catalog format
- Extract auth headers and cookies from
auth.json
If peek-api is not installed or no capture exists, tell the user:
To capture endpoints from a live site, install peek-api:
git clone https://github.com/alexknowshtml/peek-api
cd peek-api && npm install
node bin/cli.js https://example.com
Step 3: Build Endpoint Catalog
Normalize all discovered endpoints into this format:
interface EndpointCatalog {
service: string; // e.g., "stripe", "nexudus"
baseUrl: string;
auth: {
type: 'api-key' | 'bearer' | 'cookies' | 'oauth' | 'none';
headerName?: string; // e.g., "Authorization", "X-API-Key"
envVar: string; // e.g., "STRIPE_API_KEY"
};
pagination?: {
style: 'cursor' | 'offset' | 'page' | 'link-header';
paramName: string; // e.g., "starting_after", "offset", "page"
responseField: string; // e.g., "has_more", "next", "next_page_url"
};
rateLimit?: {
requests: number;
window: string; // e.g., "1m", "1h"
};
resources: ResourceGroup[];
}
interface ResourceGroup {
name: string; // e.g., "customers", "invoices"
description: string;
endpoints: Endpoint[];
}
interface Endpoint {
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
path: string; // e.g., "/v1/customers/:id"
description: string;
parameters: Parameter[];
requestBody?: object; // JSON schema or example
responseExample?: object;
}
interface Parameter {
name: string;
in: 'path' | 'query' | 'header';
required: boolean;
type: string;
description: string;
}
Present the catalog to the user for review before generating:
Found 24 endpoints across 5 resources:
customers (6 endpoints): list, get, create, update, delete, search
invoices (5 endpoints): list, get, create, send, void
...
Ready to generate the CLI?
Step 4: Generate CLI
Generate a dual-mode CLI using Commander.js. The CLI auto-detects human vs agent output via process.stdout.isTTY.
File Structure
In-project scaffold:
scripts/
{service}.ts # Entry point with shebang
{service}/
lib/
client.ts # API client (auth, pagination, retry, caching)
envelope.ts # Agent JSON envelope helpers
commands/
{resource}.ts # One file per resource group
Standalone project:
{service}-cli/
package.json
tsconfig.json
bin/
{service}.ts # Entry point with shebang
src/
lib/
client.ts
envelope.ts
commands/
{resource}.ts
Code Generation Patterns
See these references for the patterns to apply during generation:
references/api-client-template.md— API client class with pagination, retry, rate limiting, cachingreferences/agent-first-patterns.md— JSON envelope, HATEOAS next_actions, context-safe output, error fix suggestionsreferences/commander-patterns.md— Commander.js subcommands, global options, interactive prompts, colored output
Key Generation Rules
Entry point ({service}.ts):
- Shebang:
#!/usr/bin/env npx tsx - Self-documenting root command (no args â prints full command tree as JSON)
- Global options:
--json(force JSON output),--verbose,--config <path>
API client (lib/client.ts):
- Constructor takes base URL + auth config
- Auth from env var (name based on
catalog.auth.envVar) - Built-in pagination matching the API’s pattern
- Retry with exponential backoff for 5xx and 429 errors
- Rate limiting based on discovered limits
- Optional response caching
Envelope helpers (lib/envelope.ts):
const isAgent = !process.stdout.isTTY;
function respond(command: string, result: any, nextActions: Action[] = []) {
if (isAgent) {
console.log(JSON.stringify({ ok: true, command, result, next_actions: nextActions }));
} else {
return result; // caller handles human rendering
}
}
function respondError(command: string, message: string, code: string, fix: string, nextActions: Action[] = []) {
if (isAgent) {
console.log(JSON.stringify({ ok: false, command, error: { message, code }, fix, next_actions: nextActions }));
} else {
console.error(`Error: ${message}`);
console.error(`Fix: ${fix}`);
}
process.exit(1);
}
Command files (commands/{resource}.ts):
- One file per resource group
- Each endpoint becomes a subcommand:
mycli customers list,mycli customers get <id> listcommands: support--limit,--offset/--cursor,--status(if filterable)getcommands: take ID as argumentcreate/updatecommands: accept--data <json>or individual--fieldflags- Every command includes contextual
next_actionsfor agent mode - Errors include
fixsuggestions
Standalone project extras:
package.jsonwithcommander,tsxas dependencies,binfield pointing to entrytsconfig.jsonfor TypeScript.env.examplewith the required env var
Step 5: Verify
After generating the CLI:
- Verify it runs: Execute with no args, confirm the self-documenting root works
- Test one endpoint: Pick a simple GET endpoint, run it, verify output
- Move on to Step 6 to wrap the CLI in a skill
Step 6: Generate Skill
Create a Claude Code skill folder that teaches Claude how to use the generated CLI. This is the final step — it turns the CLI into something any Claude session can pick up and use without reading the code.
Skill Structure
.claude/skills/{service}/
SKILL.md # Skill instructions
SKILL.md Template
Generate a SKILL.md with this structure:
---
name: {service}
description: Interact with the {Service} API via CLI. Use when user wants to
{list of actions based on discovered resources, e.g., "list customers,
create invoices, check order status"}. Commands: {service} {resource} {action}.
---
# {Service} CLI
CLI wrapper for the {Service} API.
## Setup
Set the `{SERVICE_ENV_VAR}` environment variable:
\`\`\`bash
export {SERVICE_ENV_VAR}=your-api-key-here
\`\`\`
## Commands
{For each resource group, list commands with examples:}
### {Resource}
\`\`\`bash
# List {resources}
npx tsx {path/to/cli}.ts {resource} list
# Get a specific {resource}
npx tsx {path/to/cli}.ts {resource} get <id>
# Create a {resource}
npx tsx {path/to/cli}.ts {resource} create --field value
\`\`\`
## Common Workflows
{Generate 2-3 practical workflows combining multiple commands:}
### Example: {Workflow name}
\`\`\`bash
# Step 1: Find the customer
npx tsx {path/to/cli}.ts customers list --status=active
# Step 2: Get their invoices
npx tsx {path/to/cli}.ts invoices list --customer-id=abc123
\`\`\`
## Agent Usage
When piped, all commands return JSON with `next_actions`:
\`\`\`bash
npx tsx {path/to/cli}.ts {resource} list | cat
\`\`\`
Key Rules for Skill Generation
- Description is critical — include specific trigger phrases and list the actions the CLI supports. This is what Claude reads to decide when to use the skill.
- Include real command examples — use the actual CLI path and real subcommand names from the generated CLI.
- Generate practical workflows — combine multiple commands into realistic multi-step scenarios based on how the API’s resources relate to each other.
- Keep it lean — the skill should be a quick reference, not a restatement of
--help. Focus on what Claude needs to know that it can’t infer.
Tell the User
After generating both the CLI and the skill:
CLI generated at {cli_path}
Skill generated at .claude/skills/{service}/SKILL.md
To use the CLI directly:
npx tsx {cli_path} # See all commands
npx tsx {cli_path} customers list # List customers
Claude will now automatically use this skill when you ask about {service}.
Reference Files
references/discovery-strategies.md— Detailed probing patterns, well-known paths, GraphQL introspection, response parsingreferences/api-client-template.md— Full API client class with pagination, retry, rate limiting, cachingreferences/agent-first-patterns.md— Agent JSON envelope, HATEOAS, context-safe output, error handlingreferences/commander-patterns.md— Commander.js subcommands, nested commands, interactive prompts, colored output, config files, testing