Ever opened a Node.js project, ran it, and got hit with:
Error: Cannot find module 'axios'
You check package.json. It's not there. You add it. Then five minutes later, a different file throws the same error for a different package. You repeat the process three more times before the app actually starts.
Or the opposite: your package.json has 40 entries and you're pretty sure half of them haven't been imported anywhere in months — but you don't want to manually grep through 200 files to find out.
I got tired of this. So I built reqscan.
What is reqscan?
reqscan is a zero-dependency CLI tool that scans your Node.js project, finds every package you're importing across all your source files, and compares it against your package.json. It tells you exactly what's missing, what's unused, and lets you fix everything in one command.
npx reqscan check
That's it. Point it at any project and it gives you the full picture.
A real example
Say you have a project with these files scattered around:
// src/api.js
import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
// src/db.js
const mongoose = require('mongoose');
// lib/utils.ts
import { format } from 'date-fns';
import type { User } from '@myorg/types';
And your package.json only declares mongoose and jest.
Running reqscan check gives you:
📦 Project: my-app
──────────────────────────────────────────────────
Summary
Total imports found : 5
Declared in pkg.json : 2
Already installed : 1
Missing (not declared): 4
❌ Missing Packages (not in package.json)
──────────────────────────────────────────────────
✗ axios
✗ uuid
✗ date-fns
✗ @myorg/types
💡 Run this to install all missing packages:
npm install axios uuid date-fns @myorg/types
✅ Already Declared Packages
──────────────────────────────────────────────────
✓ mongoose ^7.0.0
⚠️ Declared but NOT imported in source (possibly unused)
──────────────────────────────────────────────────
~ jest (devDependencies)
Then you just run:
npx reqscan install
Done. All four packages installed in one shot.
The commands
| Command | What it does |
|---|---|
reqscan check |
Scan and report — missing, present, unused |
reqscan install |
Install all missing packages |
reqscan clean |
Remove declared-but-never-imported packages |
reqscan fix |
Install missing + clean unused in one go |
reqscan audit |
Full health report with a score |
reqscan list |
Every dependency with its current status |
The one I use most day-to-day is reqscan fix. Drop into any project, run it, and your dependencies are clean.
What it detects
reqscan understands every import style you'd encounter in a modern JS/TS codebase:
// CommonJS
const express = require('express');
require.resolve('some-pkg');
// ESM
import something from 'lodash';
import * as ns from 'ramda';
import { useState } from 'react';
// Side-effect imports
import 'reflect-metadata';
// Dynamic imports
const mod = await import('dynamic-pkg');
// TypeScript type imports (still a real dependency!)
import type { User } from '@myorg/types';
export type { Config } from 'some-lib';
// Re-exports
export { helper } from 'shared-utils';
It also strips comments before scanning, so commented-out imports don't generate false positives. Scoped packages (@babel/core) and subpath imports (date-fns/format → date-fns) are both handled correctly.
Built-ins (fs, path, node:crypto, etc.) are filtered out automatically. So are node_modules, dist, .next, and the other usual suspects.
Flags that make it CI-friendly
# Preview what would change — no files touched
reqscan fix --dry-run
# Install missing packages as devDependencies
reqscan install --save-dev
# Remove unused without the confirmation prompt (great for scripts)
reqscan clean --force
# Machine-readable output for tooling
reqscan audit --json
The --json flag is particularly useful if you want to build on top of reqscan — pipe it into another tool, write it to a file, diff it across branches, whatever.
Use it programmatically
reqscan also exposes a clean API if you want to integrate it into your own tooling:
const { scanProject } = require('reqscan');
const result = await scanProject('./my-app');
console.log(result.missing); // ['axios', 'uuid']
console.log(result.unused); // ['jest']
console.log(result.present); // ['express', 'mongoose']
Zero config, returns plain arrays. Easy to plug into a custom script, a GitHub Action, or a monorepo tool.
Zero dependencies
The whole thing is zero external dependencies. No third-party parsers, no commander, no chalk. The bundle is just the source files — under 300 lines of scanner logic, a small color helper that respects NO_COLOR and non-TTY environments, and the CLI entry point.
That means it installs instantly, works anywhere Node ≥ 14 runs, and won't pollute your node_modules with its own transitive deps.
Install it
Global (recommended for everyday use):
npm install -g reqscan
Or just use npx — no install needed:
npx reqscan check
npx reqscan fix
Or add it to a project for CI:
npm install --save-dev reqscan
{
"scripts": {
"deps:check": "reqscan check",
"deps:fix": "reqscan fix --force"
}
}
What's next
A few things on the roadmap:
-
reqscan outdated— surface packages with newer versions available -
reqscan upgrade— update outdated packages interactively -
.reqscanrcconfig file for per-project ignore lists - Monorepo / workspace support
If you have a use case reqscan doesn't handle, or hit a false positive/negative on a pattern it's not detecting, open an issue. Real-world projects have edge cases I haven't seen yet.
npm: npmjs.com/package/reqscan
Give it a try and let me know what you think in the comments. And if it saves you time, a ⭐ on GitHub goes a long way.
Top comments (0)