Back to skills
SkillHub ClubShip Full StackFull StackBackend

api-documenting

Generate API documentation from code. Use when the user wants to document APIs, create API reference, generate endpoint documentation, or needs help with OpenAPI/Swagger specs.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
254
Hot score
98
Updated
March 19, 2026
Overall rating
C3.2
Composite score
3.2
Best-practice grade
B82.7

Install command

npx @skill-hub/cli install huangjia2019-claude-code-engineering-02-progressive-skill

Repository

huangjia2019/claude-code-engineering

Skill path: 04-Skills/projects/02-progressive-skill

Generate API documentation from code. Use when the user wants to document APIs, create API reference, generate endpoint documentation, or needs help with OpenAPI/Swagger specs.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Backend.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: huangjia2019.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install api-documenting into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/huangjia2019/claude-code-engineering before adding api-documenting to shared team environments
  • Use api-documenting for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: api-documenting
description: Generate API documentation from code. Use when the user wants to document APIs, create API reference, generate endpoint documentation, or needs help with OpenAPI/Swagger specs.
allowed-tools:
  - Read
  - Grep
  - Glob
  - Write
---

# API Documentation Generator

Generate comprehensive API documentation from source code.

## Quick Reference

For common documentation patterns, see `PATTERNS.md`.

## Documentation Standards

See `STANDARDS.md` for our documentation conventions.

## Process

### Step 1: Identify API Endpoints

Look for:
- Route definitions (Express, FastAPI, etc.)
- Controller methods
- Handler functions

### Step 2: Extract Information

For each endpoint, extract:
- HTTP method (GET, POST, PUT, DELETE, etc.)
- Path/route
- Parameters (path, query, body)
- Request/response schemas
- Authentication requirements

### Step 3: Generate Documentation

Use the template in `templates/endpoint.md` for consistent formatting.

### Step 4: Create Overview

Generate an index of all endpoints with the template in `templates/index.md`.

## Output Formats

### Markdown (Default)
Generate markdown documentation suitable for README or docs site.

### OpenAPI/Swagger
If requested, generate OpenAPI 3.0 spec. See `templates/openapi.yaml` for structure.

## Examples

See `EXAMPLES.md` for sample inputs and outputs.

## Scripts

To auto-detect routes in common frameworks:
```bash
python scripts/detect_routes.py <source_directory>
```

To validate generated OpenAPI spec:
```bash
./scripts/validate_openapi.sh <spec_file>
```


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/detect_routes.py

```python
#!/usr/bin/env python3
"""
Route Detection Script

Automatically detects API routes in common web frameworks.
Supports: Express.js, FastAPI, Flask, Spring Boot, Go (Gin/Echo)

Usage:
    python detect_routes.py <source_directory>

Output:
    JSON list of detected routes with metadata
"""

import os
import re
import sys
import json
from pathlib import Path

# Route patterns for different frameworks
PATTERNS = {
    'express': [
        # app.get('/path', handler)
        r"app\.(get|post|put|delete|patch)\s*\(\s*['\"]([^'\"]+)['\"]",
        # router.get('/path', handler)
        r"router\.(get|post|put|delete|patch)\s*\(\s*['\"]([^'\"]+)['\"]",
    ],
    'fastapi': [
        # @app.get("/path")
        r"@app\.(get|post|put|delete|patch)\s*\(\s*['\"]([^'\"]+)['\"]",
        # @router.get("/path")
        r"@router\.(get|post|put|delete|patch)\s*\(\s*['\"]([^'\"]+)['\"]",
    ],
    'flask': [
        # @app.route('/path', methods=['GET'])
        r"@app\.route\s*\(\s*['\"]([^'\"]+)['\"].*?methods\s*=\s*\[([^\]]+)\]",
        # @blueprint.route('/path')
        r"@\w+\.route\s*\(\s*['\"]([^'\"]+)['\"]",
    ],
    'spring': [
        # @GetMapping("/path")
        r"@(Get|Post|Put|Delete|Patch)Mapping\s*\(\s*['\"]?([^'\")\s]+)",
        # @RequestMapping(value="/path", method=...)
        r"@RequestMapping\s*\([^)]*value\s*=\s*['\"]([^'\"]+)['\"]",
    ],
    'go_gin': [
        # r.GET("/path", handler)
        r"\w+\.(GET|POST|PUT|DELETE|PATCH)\s*\(\s*['\"]([^'\"]+)['\"]",
    ],
}

def detect_framework(content: str) -> str:
    """Detect which framework is being used based on imports/requires."""
    if 'express' in content.lower() or "require('express')" in content:
        return 'express'
    elif 'fastapi' in content.lower() or 'from fastapi' in content:
        return 'fastapi'
    elif 'flask' in content.lower() or 'from flask' in content:
        return 'flask'
    elif '@RestController' in content or '@RequestMapping' in content:
        return 'spring'
    elif 'gin.Default()' in content or 'echo.New()' in content:
        return 'go_gin'
    return None

def extract_routes(file_path: Path) -> list:
    """Extract routes from a single file."""
    routes = []

    try:
        content = file_path.read_text()
    except Exception as e:
        print(f"Warning: Could not read {file_path}: {e}", file=sys.stderr)
        return routes

    framework = detect_framework(content)
    if not framework:
        return routes

    patterns = PATTERNS.get(framework, [])

    for pattern in patterns:
        matches = re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE)
        for match in matches:
            groups = match.groups()
            if len(groups) >= 2:
                method = groups[0].upper()
                path = groups[1]
            else:
                method = 'GET'  # Default
                path = groups[0]

            routes.append({
                'method': method,
                'path': path,
                'file': str(file_path),
                'line': content[:match.start()].count('\n') + 1,
                'framework': framework,
            })

    return routes

def scan_directory(directory: str) -> list:
    """Scan a directory for route definitions."""
    all_routes = []

    # File extensions to scan
    extensions = {'.js', '.ts', '.py', '.java', '.go', '.kt'}

    path = Path(directory)
    if not path.exists():
        print(f"Error: Directory {directory} does not exist", file=sys.stderr)
        sys.exit(1)

    for file_path in path.rglob('*'):
        if file_path.suffix in extensions and file_path.is_file():
            # Skip node_modules, venv, etc.
            if any(skip in str(file_path) for skip in ['node_modules', 'venv', '.git', 'dist', 'build']):
                continue

            routes = extract_routes(file_path)
            all_routes.extend(routes)

    return all_routes

def main():
    if len(sys.argv) < 2:
        print("Usage: python detect_routes.py <source_directory>", file=sys.stderr)
        sys.exit(1)

    directory = sys.argv[1]
    routes = scan_directory(directory)

    # Sort by path for readability
    routes.sort(key=lambda r: (r['path'], r['method']))

    # Output as JSON
    print(json.dumps(routes, indent=2))

    # Summary to stderr
    print(f"\nFound {len(routes)} routes in {directory}", file=sys.stderr)

if __name__ == '__main__':
    main()

```

### scripts/validate_openapi.sh

```bash
#!/bin/bash
# OpenAPI Specification Validator
#
# Validates an OpenAPI spec file for correctness.
# Requires: npx (Node.js) or swagger-cli
#
# Usage:
#   ./validate_openapi.sh <spec_file>
#
# Example:
#   ./validate_openapi.sh api-spec.yaml

set -e

SPEC_FILE="$1"

if [ -z "$SPEC_FILE" ]; then
    echo "Usage: $0 <spec_file>"
    echo "Example: $0 api-spec.yaml"
    exit 1
fi

if [ ! -f "$SPEC_FILE" ]; then
    echo "Error: File '$SPEC_FILE' not found"
    exit 1
fi

echo "Validating OpenAPI spec: $SPEC_FILE"
echo "=================================="

# Check if swagger-cli is available
if command -v swagger-cli &> /dev/null; then
    echo "Using swagger-cli..."
    swagger-cli validate "$SPEC_FILE"

# Check if npx is available (Node.js)
elif command -v npx &> /dev/null; then
    echo "Using @apidevtools/swagger-cli via npx..."
    npx @apidevtools/swagger-cli validate "$SPEC_FILE"

# Check if Python spectral is available
elif command -v spectral &> /dev/null; then
    echo "Using Spectral..."
    spectral lint "$SPEC_FILE"

else
    echo "Warning: No OpenAPI validator found."
    echo "Install one of:"
    echo "  - npm install -g @apidevtools/swagger-cli"
    echo "  - npm install -g @stoplight/spectral-cli"
    echo ""
    echo "Performing basic YAML syntax check instead..."

    # Basic YAML check
    if command -v python3 &> /dev/null; then
        python3 -c "import yaml; yaml.safe_load(open('$SPEC_FILE'))" && echo "YAML syntax: OK"
    elif command -v ruby &> /dev/null; then
        ruby -ryaml -e "YAML.load_file('$SPEC_FILE')" && echo "YAML syntax: OK"
    else
        echo "Cannot perform YAML check without Python or Ruby"
        exit 1
    fi
fi

echo ""
echo "Validation complete!"

```

### templates/endpoint.md

```markdown
# Endpoint Documentation Template

Use this template for each API endpoint:

```markdown
## {METHOD} {PATH}

{Brief description of what this endpoint does.}

### Authentication
{Required | Optional | None}

### Parameters

| Name | Location | Type | Required | Description |
|------|----------|------|----------|-------------|
| {name} | {path/query/header/body} | {type} | {Yes/No} | {description} |

### Request Body
{If applicable}

```json
{
  "field": "value"
}
```

### Responses

#### {Status Code} {Status Text}
{Description of when this response occurs}

```json
{
  "example": "response"
}
```

### Example

**Request**:
```bash
curl -X {METHOD} '{BASE_URL}{PATH}' \
  -H 'Content-Type: application/json' \
  -d '{request_body}'
```

**Response**:
```json
{
  "example": "response"
}
```

### Notes
{Any additional information, caveats, or related endpoints}
```

```

### templates/index.md

```markdown
# API Index Template

Use this template for the API overview page:

```markdown
# {API Name} API Reference

{Brief description of the API}

## Base URL
`{BASE_URL}`

## Authentication
{Description of authentication methods}

## Endpoints

### {Resource Group 1}
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /resource | List all resources |
| POST | /resource | Create a resource |
| GET | /resource/:id | Get a specific resource |
| PUT | /resource/:id | Update a resource |
| DELETE | /resource/:id | Delete a resource |

### {Resource Group 2}
| Method | Endpoint | Description |
|--------|----------|-------------|
| ... | ... | ... |

## Common Response Codes

| Code | Description |
|------|-------------|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 500 | Internal Server Error |

## Rate Limiting
{Rate limiting information if applicable}

## Versioning
{API versioning strategy}
```

```

### templates/openapi.yaml

```yaml
# OpenAPI Template
# Use this as a starting point for generating OpenAPI specs

openapi: 3.0.0

info:
  title: API Title
  description: API description goes here
  version: 1.0.0
  contact:
    name: API Support
    email: [email protected]

servers:
  - url: https://api.example.com/v1
    description: Production server
  - url: https://staging-api.example.com/v1
    description: Staging server

paths:
  /example:
    get:
      summary: Example endpoint
      description: Detailed description of what this endpoint does
      operationId: getExample
      tags:
        - Examples
      parameters:
        - name: id
          in: query
          required: false
          schema:
            type: string
          description: Filter by ID
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Example'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

components:
  schemas:
    Example:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: string
          description: Unique identifier
        name:
          type: string
          description: Resource name
        createdAt:
          type: string
          format: date-time
          description: Creation timestamp

    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: Error code
        message:
          type: string
          description: Error message

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

security:
  - bearerAuth: []

tags:
  - name: Examples
    description: Example endpoints

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### EXAMPLES.md

```markdown
# API Documentation Examples

## Example 1: Simple Express.js Endpoint

### Input Code
```javascript
// routes/users.js
router.get('/users/:id', async (req, res) => {
  const { id } = req.params;
  const user = await User.findById(id);
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }
  res.json(user);
});
```

### Generated Documentation
```markdown
## GET /users/:id

Retrieve a user by their unique identifier.

### Parameters

| Name | Location | Type | Required | Description |
|------|----------|------|----------|-------------|
| id | path | string | Yes | The unique identifier of the user |

### Responses

#### 200 OK
Returns the user object.

```json
{
  "id": "123",
  "name": "John Doe",
  "email": "[email protected]",
  "createdAt": "2024-01-15T10:30:00Z"
}
```

#### 404 Not Found
User with specified ID does not exist.

```json
{
  "error": "User not found"
}
```
```

---

## Example 2: FastAPI with Pydantic

### Input Code
```python
from pydantic import BaseModel
from fastapi import FastAPI, HTTPException

class UserCreate(BaseModel):
    name: str
    email: str
    password: str

class UserResponse(BaseModel):
    id: str
    name: str
    email: str

@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
    """Create a new user account."""
    # ... implementation
    return new_user
```

### Generated Documentation
```markdown
## POST /users

Create a new user account.

### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | User's display name |
| email | string | Yes | User's email address |
| password | string | Yes | User's password |

**Example**:
```json
{
  "name": "Jane Smith",
  "email": "[email protected]",
  "password": "securePassword123"
}
```

### Responses

#### 201 Created
User successfully created.

```json
{
  "id": "456",
  "name": "Jane Smith",
  "email": "[email protected]"
}
```
```

---

## Example 3: OpenAPI Spec Output

### Generated OpenAPI YAML
```yaml
openapi: 3.0.0
info:
  title: User API
  version: 1.0.0
paths:
  /users/{id}:
    get:
      summary: Get user by ID
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: User not found
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        email:
          type: string
```

```

### README.md

```markdown
# 示例项目:渐进式披露 Skill

这个项目展示完整的 Skill 结构,演示渐进式披露(Progressive Disclosure)模式。

## 目录结构

```
02-progressive-skill/
├── SKILL.md              # 主指令文件(入口点)
├── PATTERNS.md           # 框架路由模式参考
├── STANDARDS.md          # 文档标准规范
├── EXAMPLES.md           # 使用示例
├── templates/            # 文档模板
│   ├── endpoint.md       # 单个端点模板
│   ├── index.md          # API 索引模板
│   └── openapi.yaml      # OpenAPI 规范模板
└── scripts/              # 辅助脚本
    ├── detect_routes.py  # 自动检测路由
    └── validate_openapi.sh # 验证 OpenAPI 规范
```

## Skill 说明

这是一个 API 文档生成 Skill。当用户需要为代码生成 API 文档时,Claude 会:

1. 首先加载 `SKILL.md`(主指令)
2. 根据需要加载其他文件(如模式、标准、模板)
3. 可以执行脚本来辅助工作

## 渐进式披露演示

### 场景 1:简单请求
用户:"帮我生成 API 文档"

Claude 加载:
- `SKILL.md` ✓
- 其他文件暂不加载

### 场景 2:需要模式参考
用户:"这是 Express.js 项目,帮我提取路由"

Claude 加载:
- `SKILL.md` ✓
- `PATTERNS.md` ✓(因为涉及框架特定模式)

### 场景 3:需要生成 OpenAPI
用户:"生成 OpenAPI 规范"

Claude 加载:
- `SKILL.md` ✓
- `templates/openapi.yaml` ✓(需要模板结构)
- `STANDARDS.md` ✓(确保符合标准)

### Token 消耗对比

| 场景 | 传统方式 | 渐进式披露 |
|------|----------|-----------|
| 简单请求 | ~3000 tokens | ~800 tokens |
| 框架特定 | ~3000 tokens | ~1200 tokens |
| 完整生成 | ~3000 tokens | ~2000 tokens |

## 关键学习点

### 1. SKILL.md 保持简洁

主文件只包含:
- 高层流程
- 文件引用(告诉 Claude 去哪找详细信息)
- 基本指令

详细内容放在引用文件中。

### 2. 有意义的文件名

```
PATTERNS.md     # 清楚表示"模式"
STANDARDS.md    # 清楚表示"标准"
EXAMPLES.md     # 清楚表示"示例"
```

Claude 通过文件名快速判断需要哪个文件。

### 3. 脚本封装复杂逻辑

```bash
# 不需要 Claude 理解每行代码
python scripts/detect_routes.py <directory>
```

Claude 可以执行脚本而不需要将整个脚本内容放入上下文。

### 4. 模板提供一致性

`templates/` 目录包含标准化模板,确保输出格式一致。

## 测试方法

尝试以下请求观察 Claude 的行为:

1. "帮我为 src/api 目录生成 API 文档"
2. "这是 FastAPI 项目,提取所有路由"
3. "生成 OpenAPI 3.0 规范"
4. "按照团队标准格式化这个端点文档"

观察 Claude 会加载哪些文件。

## 扩展建议

可以添加更多内容:
- `reference/` 目录:详细的 API 参考
- `validation/` 目录:验证规则
- 更多框架支持的 pattern 文件

```

api-documenting | SkillHub