Let’s be honest: npm audit is a necessary evil. If you manage a monorepo, a large scale-backend microservice architecture, or even just have fifty toy projects in your /dev folder, you know the dread. You run an audit, get 400 vulnerabilities, and standard npm audit fix just breaks things.
The real problem isn't fixing the vulnerability; the problem is the management of the vulnerabilities.
Manually cd-ing into 30 different directories, running the audit, deciphering the output, deciding which package.json to edit, and then doing the work? That's an efficient way to burn out an afternoon.
Here is the tool you didn’t know you needed.
The Problem: Multi-Directory Triage
You are working across multiple contexts (multiple directories). You have dozens of tasks:
- Find the
package.json. - Navigate to that folder.
- Run the audit.
- Decide if it’s a manual fix (Mocha 11x, looking at you) or an
audit fix --forcecandidate. - Mark it done and move on.
The standard Unix toolbox doesn’t have a built-in interactive "loop through directories and run commands, pausing for input" command.
The Solution: fzf as an Interactive Runner
/home/tonymet/dev/
> api-gateway-service │ Path: ./api-gateway-service
auth-provider │
legacy-reporting-tool │ 🔒 npm audit report
frontend-dashboard │
shared-auth-library │ 📉 Low 1
│ 📈 High 3
│ 💥 Critical 1
│
│ Found 5 vulnerabilities in 890 scanned packages.
│ 3 vulnerabilities require manual review.
│
│ Run `npm audit fix` to fix 2 of them.
│
│ =========================================================
│ Critical: Remote Code Execution
│ Package: serialize-javascript
│ Dependency of: mocha [dev]
│ Path: mocha > serialize-javascript
│ More info: https://github.com/advisories/GHSA-hxcc-f52p
│
│ =========================================================
│ High: Prototype Pollution
│ ... (rest of audit output scrolled)
[5/5] -----------------------------------------------------------------│
> _
The solution is combining the powerhouse finder fzf with some standard find commands.
We are going to use fzf not just to select a file, but as an interactive dashboard.
The One Command to Rule Them All
Here is the command (Unix/Linux/macOS):
find . -name "package.json" -not -path "*/node_modules/*" \
| fzf --preview 'echo $(dirname {}) && cd $(dirname {}) && npm audit' \
--preview-window=right:80%
What is happening here?
This looks complicated, but it's remarkably elegant:
-
find . -name "package.json" -not -path "*/node_modules/*": This is our discovery engine. It searches the entire directory tree (.) forpackage.jsonfiles, but critically skips anything inside anode_modulesfolder (we don’t want to audit dependencies' dependencies, only the root projects). This feeds a clean list of file paths to the next command. -
| fzf: We pipe that list intofzf, the interactive finder. This creates the interface. -
--preview '...': This is the magic. When you highlight a path infzf, this entire script runs in the side-pane:-
echo $(dirname {}): Shows you the clean path to the directory containing thepackage.json. -
cd $(dirname {}): Temporarily navigates the preview process into that directory. -
npm audit: Executes the audit specifically inside that folder.
-
-
--preview-window=right:80%: We give the preview window 80% of the screen. Why? Becausenpm auditoutput is verbose, and you need to be able to read the specifics of the dependency tree to make triage decisions.
How to Use the Interface
When you run this command, your terminal transforms:
-
Left Side: A list of every project in your
/devfolder that has apackage.json. -
Right Side: The live output of
npm auditfor whichever project you highlight.
Now you can triage! Use the up and down arrow keys to quickly review the security status of every project without leaving the dashboard.
Actually "Doing Work"
The standard configuration above is a read-only view. It lets you quickly see where the major problems are (e.g., "Oh, all these old 2022 projects need Mocha 12").
If you want to actually execute fixes from within the interface, we need to bind a key:
find . -name "package.json" -not -path "*/node_modules/*" \
| fzf --preview 'echo $(dirname {}) && cd $(dirname {}) && cat package.json' \
--preview-window=right:80% \
--bind 'enter:execute(cd $(dirname {}) && npm audit fix && echo -n DONE | read)+down'
What this version does:
-
Default Preview: Shows
package.json(runningauditconstantly in preview can be slow). -
Enter (Binding): When you hit
Enter:- It runs
npm audit fixin that folder. - It uses
echo -n DONE | readto pause the interface (pressing any key resumes). -
+down: After you resume, it automatically moves the selection to the next directory on the list.
- It runs
It mimics the exact "triage and advance" workflow of an interactive rebase.
When the interface is painless, you are more likely to run it. When the effort of auditing 100 directories is reduced to "holding down the down arrow," security gets addressed.
Top comments (0)