npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jsdoc-scribe

v2.5.3

Published

Automated, AST-based JSDoc comment generator and static documentation site builder for JavaScript & TypeScript. Fast, deterministic, and 100% local (No AI involved).

Readme

jsdoc-scribe

npm version npm downloads License: MIT Node.js Types: included Documentation

Reads your code's actual AST and writes the JSDoc for it — no AI, no guessing, same input always gives the same output.

Why this exists

Docs go stale because writing them by hand is boring and nobody updates them when the code changes. Asking an AI to write them instead just trades "stale" for "confidently wrong" — it can describe what a function probably does, not what it actually does. jsdoc-scribe skips both problems: it reads the real AST — actual parameter names, actual types, actual return paths — and generates from that. If the code changes, regenerate. There's nothing to keep in sync by memory, and nothing invented to fact-check.

See it work

Input — a plain function and method, no comments:

function calculateTotal(items, taxRate) {
  return items.reduce((sum, item) => sum + item.price * item.qty, 0) * (1 + taxRate);
}

async function getUserOrders(userId, db) {
  return db.orders.find({ userId });
}

gen-comments orders.js --write → this, in place, nothing else touched:

/**
 * Calculates the total.
 * @param {any} items - array of items.
 * @param {any} taxRate - tax rate.
 * @returns {any}
 */
function calculateTotal(items, taxRate) {
  return items.reduce((sum, item) => sum + item.price * item.qty, 0) * (1 + taxRate);
}

/**
 * Returns the user orders.
 * @async
 * @param {any} userId - user unique identifier.
 * @param {any} db - database connection.
 * @returns {any}
 */
async function getUserOrders(userId, db) {
  return db.orders.find({ userId });
}

That's really it — this is plain untyped JS, so the types come back any (see Known limitations). Run it against a TypeScript file and the same param/return types you already wrote show up in the JSDoc instead. gen-docs then turns files like this into a browsable HTML site — live preview below.

Quick start

npx jsdoc-scribe src --write     # try it on your own code, right now, no install

Once it's actually installed (npm install --save-dev jsdoc-scribe — see Install), gen-docs src --out docs builds a browsable HTML site from what you just wrote.

Nothing gets sent anywhere — no network calls, no API key, no account. It's a CLI reading files on your disk and writing files back to your disk, backed by one runtime dependency (typescript, used purely as a syntax parser) and a self-test suite that runs on every npm test and before every publish.

Should you use this?

Yes, if: you want JSDoc coverage that doesn't drift from the code, want a docs site without wiring up a separate static-site generator, or want a CI gate that fails when something ships undocumented — without adding an LLM call to your pipeline.

Skip it if: you want prose that explains why the code does something, not just its shape. jsdoc-scribe only knows what's structurally true in the AST — a param name, a return type, a class hierarchy. It will never write "this exists to work around a vendor API quirk" for you, because it doesn't know that and won't pretend to.

Supported

jsdoc-scribe works on any plain JavaScript or TypeScript file — it reads the real AST, not framework-specific conventions, so there's no allowlist of "supported frameworks" gating whether gen-comments/gen-docs will run. What is framework-aware is the Architecture Insight page (gen-docs's auto-generated read of your stack) — it explicitly detects and names these, from your package.json dependencies (a .tsx/.vue file extension is used as a lower-confidence fallback when no dependency evidence exists):

| Stack | Detected via | Try it against a real fixture | |---|---|---| | React | react dependency, or .tsx/.jsx files | sample/react/ — function components, props, hooks | | Next.js | next dependency | sample/nextjs/ — App Router route handler, app/ page, pages/ dynamic route | | Angular | @angular/core dependency | sample/angular/ — component, service, pipe, directive | | Vue | vue dependency, or .vue files | detected via dependency/file-extension signals; no dedicated sample/vue fixture yet | | Express | express dependency | sample/express/ — app entry, routes, a controller, a service, auth middleware | | NestJS | @nestjs/core dependency | sample/nestjs/ — @Controller/@Injectable classes, a guard, a module | | Plain JavaScript (CommonJS, no framework) | always — this is the baseline case | sample/vanilla-js/ — logger, event emitter, retry helper, validators | | Plain TypeScript (no framework) | always | sample/*.ts top-level — DI container, error hierarchy, event bus, HTTP middleware, models, API layer |

Node.js >=14 is the only runtime requirement (see engines); CI tests against Node 22/24/26. typescript (>=5.0.0 <7.0.0) is the one runtime dependency, used purely as a syntax parser — every file jsdoc-scribe touches goes through it, .js included, not just .ts.

Run any CLI directly against a sample to see real output on real code, not a toy snippet:

gen-comments sample/nestjs --dry-run   # decorator-heavy NestJS classes
gen-comments sample/express --check    # coverage check on an undocumented Express app
gen-docs sample --out docs --title "jsdoc-scribe sample" --quality

What's in the box

| Tool | What it does | |---|---| | gen-comments | Inserts /** */ JSDoc blocks into your source by reading the AST | | gen-docs | Builds a static, multi-page HTML documentation site from your documented source |

  • JSDoc linting without ESLint. --lint runs the same category of checks eslint-plugin-jsdoc's recommended config does; --lint --fix auto-corrects what's mechanically safe (tag order, stray asterisks) and leaves a TODO: placeholder for what needs a human, never invented text. Already on ESLint? The same rules ship as a native flat-config plugin — eslint-plugin-jsdoc-scribe — not yet published to npm standalone; this repo dogfoods it directly via npm workspaces (see eslint.config.js, npm run eslint).
  • ESLint + Prettier, set up the way any other Node project would be. npm run eslint lints lib//bin//scripts//packages/* using eslint-plugin-jsdoc-scribe's own configs.recommended preset as-is — no project-specific rule overrides. npm run format/ npm run format:check runs Prettier. Both run in CI (.github/workflows/test.yml, report-only for now — see that workflow's inline comment for why).
  • --check-drift flags JSDoc that no longer matches the code it's describing — a param renamed or removed, a return type that changed — the "docs quietly went stale" problem, caught in CI before merge.
  • Architecture Insight page. Every gen-docs run includes a plain-English read of your folder structure, detected framework, and architecture-pattern signals — each shown with the actual evidence (a bin entry, matching directory names), never a bare guess. Details.
  • Optional Code Health dashboard (--quality, via the optional code-multivitals peer dependency) — complexity, maintainability, duplicate-code, and orphan-file stats on the same files you just documented.

Three ways to use it

| | Comments | Docs | Lint | |---|---|---|---| | CLI | gen-comments src --write | gen-docs src --out docs | gen-comments src --lint --fix | | In your code | require('jsdoc-scribe').processFile(file, opts) | require('jsdoc-scribe/docs').generateSite(['src'], opts) | require('jsdoc-scribe/lint').lintModule(data) | | CI (GitHub Actions) | npx gen-comments src --check (PR gate) | npx gen-docs src --out _site (Pages deploy) | npx gen-comments src --lint (PR gate) |

Every flag is a plain 0/1 exit code, so any row above drops straight into a run: step — this repo's own test.yml and docs.yml are the same pattern, running live. Full walkthroughs: CLI Usage · Programmatic API · GitHub Actions.

Preview

Real gen-docs output against sample/ — not a mockup.

jsdoc-scribe docs preview

jsdoc-scribe Code Health dashboard preview

Benchmarks

No caching between runs, measured directly against the CLIs:

| Source size | gen-comments --dry-run | gen-docs (single file) | |---|---|---| | 231 LOC | 1.15s | 0.49s | | 23K LOC | 1.47s | 0.71s | | 233K LOC | 4.17s | 2.29s |

A real 1,000-file/70K-LOC project finishes gen-comments --write in ~1s. Both CLIs scale close to linearly with source size — gen-docs's multi-file build had a superlinear ceiling past ~300-500 files, fixed and now enforced continuously in CI via npm run bench:perf-gate, not just measured once. Full numbers: CHANGELOG.

Known limitations

Said plainly, not buried:

  • Inline anonymous callbacks (arr.map(x => x * 2)) aren't documented — named declarations only.
  • Type inference is 100% syntactic — no evaluation, no imports, no type-checking. Untyped JS gets any, same as the example above.
  • Multi-declarator statements (const a = 1, b = 2;) get one combined block.
  • .d.ts files are skipped.
  • gen-docs doesn't serve its output — use npx serve docs or deploy statically.
  • gen-docs holds every generated page in memory until the whole site is built, then writes it all at once — a memory-footprint concern at very large (thousands-of-files) scale, not yet sized against real hardware.
  • Not yet compatible with TypeScript 7 — the typescript npm package's programmatic API isn't available at all under 7.0 (a stable API is expected in 7.1, ~October 2026); typescript is pinned to <7.0.0 until then.

Install

npx jsdoc-scribe . --write            # run once, no install
npm install --save-dev jsdoc-scribe   # add to project
npm install -g jsdoc-scribe           # or install globally

Documentation

Full docs, quick-start, and every flag reference: imchintoo.github.io/jsdoc-scribe. Real multi-framework sample code (Express, NestJS, plain JS) to try the CLIs against without writing your own fixtures lives in sample/.

Contributing

Bug reports and PRs welcome — see CONTRIBUTING.md (determinism is non-negotiable, no new runtime dependency without discussion first). This project follows the Code of Conduct. Found a security issue? See SECURITY.md rather than opening a public issue with exploit details.

License

MIT © Chintan