Level 5Lesson 41⏱️ 60 min

Documenting Code with AI

Docs that never get written are useless. AI removes the friction — learn to generate, maintain, and sync docs at speed.

Why Documentation is an AI Superpower

Documentation is the task developers most reliably skip. It's tedious, it goes stale, and it feels disconnected from "real work." AI removes every excuse — it writes faster than you and never complains about boring tasks.

What AI docs do well:
  • JSDoc / Python docstrings from existing code
  • README files from repo structure + code
  • Inline comments explaining complex logic
  • API documentation from route/controller code
  • Changelog entries from diffs
  • Architecture decision records (ADRs)

Generating JSDoc / TypeScript Docs

// Select this function and use /doc in Copilot Chat,
// or ask Claude: "Write JSDoc for this function"

function mergeUserPreferences(
  defaults: UserPreferences,
  overrides: Partial<UserPreferences>,
  options?: { deep?: boolean; allowNull?: boolean }
): UserPreferences {
  if (options?.deep) {
    return deepMerge(defaults, overrides, options.allowNull)
  }
  return { ...defaults, ...overrides }
}

// AI generates:
/**
 * Merges user preferences with optional deep merge support.
 *
 * @param defaults - Base preferences applied to all users
 * @param overrides - User-specific overrides (partial object)
 * @param options - Merge behaviour configuration
 * @param options.deep - If true, performs recursive deep merge (default: false)
 * @param options.allowNull - If true, null values in overrides replace defaults
 * @returns Merged UserPreferences object
 *
 * @example
 * const prefs = mergeUserPreferences(
 *   { theme: 'light', language: 'en' },
 *   { theme: 'dark' }
 * )
 * // Returns: { theme: 'dark', language: 'en' }
 */

Python Docstrings

# Ask: "Write a Google-style docstring for this function"

def calculate_invoice_total(
    line_items: list[dict],
    tax_rate: float,
    discount_code: str | None = None
) -> dict:
    # AI generates:
    """Calculate the total for an invoice including tax and optional discount.

    Args:
        line_items: List of items, each with 'price' (float) and
            'quantity' (int) keys.
        tax_rate: Tax rate as a decimal (e.g. 0.2 for 20% VAT).
        discount_code: Optional promotional code. Valid codes reduce
            the subtotal by a fixed percentage before tax.

    Returns:
        Dictionary with keys:
            - subtotal (float): Sum of all line items before tax/discount
            - discount_amount (float): Amount saved via discount code
            - tax_amount (float): Tax calculated on discounted subtotal
            - total (float): Final amount due

    Raises:
        ValueError: If any line item is missing 'price' or 'quantity'.
        InvalidDiscountError: If discount_code is not recognised.

    Example:
        >>> calculate_invoice_total(
        ...     [{'price': 10.0, 'quantity': 3}],
        ...     tax_rate=0.2
        ... )
        {'subtotal': 30.0, 'discount_amount': 0.0, 'tax_amount': 6.0, 'total': 36.0}
    """

README Generation with Claude Code

# In Claude Code, generate a README for your whole project:
> Generate a comprehensive README.md for this project.
  Include: project overview, tech stack, prerequisites,
  setup instructions, environment variables, running tests,
  deployment, and API endpoints overview.
  Base it entirely on what you find in the codebase.

# Generate an API reference from route files:
> Read all files in src/routes/ and generate
  an API reference in markdown table format.
  Include: method, path, description, auth required,
  request body, and response format for each endpoint.

# Update an existing README after changes:
> Compare the current README.md with the actual codebase.
  What's out of date? Update only the sections that
  no longer match reality.

Inline Comments for Complex Logic

// Ask: "Add inline comments to explain this algorithm"

function buildQueryPlan(filters: Filter[], indexes: Index[]): QueryPlan {
  // Score each index by how many filters it satisfies
  const indexScores = indexes.map(idx => ({
    index: idx,
    score: filters.filter(f =>
      idx.columns.includes(f.column) && idx.supportsOperator(f.operator)
    ).length
  }))

  // Select the index with the highest score; fall back to full scan
  const bestIndex = indexScores.sort((a, b) => b.score - a.score)[0]

  // If no index covers any filter, return a sequential scan plan
  if (bestIndex.score === 0) {
    return { type: 'seq_scan', estimatedCost: Infinity }
  }

  // Build a plan that uses the best index for filtered columns
  // and handles remaining filters as post-index predicates
  const indexedFilters = filters.filter(f =>
    bestIndex.index.columns.includes(f.column)
  )
  const residualFilters = filters.filter(f =>
    !bestIndex.index.columns.includes(f.column)
  )

  return {
    type: 'index_scan',
    index: bestIndex.index,
    indexFilters: indexedFilters,
    residualFilters,
    estimatedCost: bestIndex.score * 0.1
  }
}

Hands-on: Document a Real Module

Challenge: Pick any undocumented file in a project you work on.

  1. Paste the whole file into Claude and ask: "Write complete JSDoc/docstrings for every function"
  2. Add inline comments to the 3 most complex functions using /doc or Claude
  3. Ask Claude Code: "Generate a section for the README explaining what [module] does and how to use it"
  4. Review all AI-generated docs for accuracy — fix anything wrong

Stretch: Set up a pre-commit hook that uses Claude Code to flag functions over 20 lines with no docstring, so new code always gets documented.

Lesson 41 Quick Reference
/doc (Copilot)

Select a function, run /doc in chat — generates full JSDoc

Google docstring

Ask: "Write a Google-style docstring" for clean Python docs with Args/Returns/Raises

README from repo

Claude Code: "Generate README based on what you find in the codebase"

API reference

"Read all files in src/routes/ and generate API reference in markdown"

Stale docs check

"Compare README.md with the codebase — what is out of date?"

Inline comments

"Add inline comments to explain this algorithm" — ask for complex functions