I kept running eslint and thinking my codebase was fine — then someone opened a PR and the first comment was "this function needs JSDoc."
The problem: linters check your syntax. Nobody checks whether your exported API is actually documented. Those are two very different things.
So I built jsdocscan — a zero-dependency CLI that walks your JS/TS files and flags every exported function or class that is missing JSDoc, or has undocumented parameters.
What it catches
Errors — exported function or class with no /** … */ block at all:
✗ src/api.js:12 fetchUser missing JSDoc
✗ src/utils.js:34 formatDate missing JSDoc
Warnings — JSDoc exists but a parameter has no @param tag:
! src/render.js:7 renderCard undocumented params: opts
Exit codes are 0 (all clean), 1 (issues found), 2 (usage error) — pipe-friendly.
How to use it
# scan a directory
npx jsdocscan src/
# Python version
pip install jsdocscan
jsdocscan src/
# skip @param checks — just verify JSDoc exists
npx jsdocscan --no-params src/
# machine-readable output
npx jsdocscan --json src/ | jq '.[].findings'
# summary line only
npx jsdocscan --quiet src/
# custom extensions
npx jsdocscan --ext .js,.ts src/
What it skips (intentionally)
- Non-exported functions and internal helpers — these are implementation details
- Destructured params
({ a, b })— too many valid@param optspatterns - TypeScript type annotations on params —
name: stringis stripped,@param nameis still required
Zero dependencies
No parsers, no AST, no require("typescript"). It uses a line-by-line scanner that:
- Detects
export function/const/classpatterns via regexes - Walks backwards to find a preceding
/** */block - Compares
@paramnames in the JSDoc against the actual parameter list
npx jsdocscan works with zero install time. pip install jsdocscan brings in nothing extra.
Links
- npm: npmjs.com/package/jsdocscan
- PyPI: pypi.org/project/jsdocscan
- GitHub (Node): jjdoor/jsdocscan
- GitHub (Python): jjdoor/jsdocscan-py
Both versions pass the same 38-test suite. Same exit codes, same output format.
Top comments (2)
How does your CLI handle complex JSDoc cases like nested callbacks or promises, and are there plans to integrate it with existing linting tools like eslint?
How does your CLI handle complex JSDoc scenarios, such as documenting nested functions or async/await syntax?