ai · tutorial · agents
Stop AI Hallucinating Packages (It Almost Installed Malware)
Agents invent npm packages that don't exist. A 3-rule file plus a 30-second pre-install ritual ends it. The exact rules inside.

npm install for a package that never existed
The agent finishes the feature, the code looks clean, and npm run build dies: Cannot find module 'stripe-event-normalizer'. No such package exists. The agent invented it — plausible name, correct-looking API, total fiction.
This is the most common agent failure in JavaScript: models trained on millions of repos autocomplete import statements the way they autocomplete sentences — confidently, sometimes fictionally. And npm install obeys without judgment, pulling typosquat malware when the invented name happens to be registered by someone malicious.
Stop AI hallucinating packages is not a model problem you can prompt away. It is a process problem with a three-rule fix.
Phantom deps vs real supply chain
| Failure | What happens | Cost |
|---|---|---|
| Phantom package | Build dies, 20 min lost | Annoying, recoverable |
| Typosquat install | Malware runs postinstall | Credentials stolen |
| Dep bloat (real but unneeded) | 400MB node_modules, slow builds | Every deploy slower |
| Abandoned micro-dep | Breaks in 6 months | Weekend lost to migration |
| Version drift per session | Lockfile churn, conflicts | Teammate builds break |
Three details make invented packages worse than wasted minutes:
- Typosquats wait for typos. Attackers register the exact plausible names agents invent. The agent that hallucinates
resend-edge-clientmay find it installable — owned by a stranger running a postinstall script. Fiction becomes intrusion in one command. - Each dep is a stranger's code in prod. The average agent-added package pulls dozens of transitive deps. Every one runs with your Stripe keys in scope. Fewer deps is not minimalism — it is access control.
- Lockfile churn hides the crime. Ten sessions each adding "one small package" produce a lockfile nobody reads. The phantom hides among the real, and
npm auditreports on fiction it cannot see.
The hallucinated-packages post told the war story. This one installs the prevention.
The 3-rule file plus the ritual
BoringPush ships this as part of AGENTS.md — the zero-dependency law, enforced by the gate and the lockfile.
Step 1 — Write the three rules where the agent reads them.
## Dependencies (never violate)
1. Never run npm install or add packages without a written argument
(what, why, what breaks without it) approved by a human.
2. Every import must resolve to package.json + lockfile — if it is not
listed, it does not exist. No exceptions, no "try installing."
3. Node and Next built-ins first: fs, fetch, crypto, AsyncLocalStorage,
Server Components, Route Handlers. Nine times in ten, no package needed.Rule 2 is the phantom-killer: it flips the default from "install what I import" to "imports must pre-exist." An agent that invents stripe-event-normalizer now fails its own rule before touching the network — the fiction dies at the whiteboard instead of in node_modules.
Step 2 — Run the 30-second pre-install ritual for the tenth time.
# human runs this before approving any new dep:
npm view <name> time --json | tail -5 # exists? maintained?
npm view <name> dependencies --json # what does it drag in?
npx --dry-run -p <name> 2>&1 | head -3 # sanity, no installFive lines that answer: real or phantom, alive or abandoned, lean or bloated. The ritual takes thirty seconds and has killed every phantom before install — including two typosquat near-misses where the name existed but the owner was three weeks old with zero dependents.
Step 3 — Audit the lockfile monthly like a dependency diet.
npx depcheck # find imports nobody uses
npm ls --depth=0 # what do we actually depend on
# remove one unused dep per month — momentum beats purgesdepcheck names the dead weight agents left behind; one removal per month keeps the list honest without purge-day drama. Fewer deps mean fewer postinstall scripts, fewer advisories, faster builds — and a smaller blast radius the next time an agent gets creative.
That's the arrangement — the dependency list fits in memory, and phantoms never board.
Before and after the 3-rule file
| Month of agent sessions | No rules | 3-rule file + ritual |
|---|---|---|
| Phantom installs | 4 | 0 |
| Typosquat near-misses | 1 (caught by luck) | 2 (caught by ritual) |
| Unasked real deps added | 5 | 0 |
| node_modules size trend | Growing weekly | Shrinking monthly |
| Approval overhead | 0 min | ~2 min per request |
Full disclosure: the ritual taxes genuine needs — occasionally a session waits hours for a human to approve a truly necessary package.
BoringPush accepts the delay because the default direction matters: friction on adding, none on removing. Dependencies should be hard to adopt and easy to divorce. Most repos have it exactly backwards.
FAQ
How do I stop ai hallucinating packages in editors without AGENTS.md support?
Put the same three rules in whatever instruction file the tool reads (project rules, workspace instructions, .cursorrules) and add the lockfile check to your own review habit: git diff --stat package.json on every agent session, before anything else. The file location varies by tool; the rule content never does. One source of truth, symlinked everywhere.
What if the agent needs a package for a genuinely hard problem?
Then it writes the argument: problem, candidate, why built-ins fail, transitive cost, maintenance evidence (npm view output pasted in). You read five lines and approve or redirect. Nine times in ten the redirect works (fetch instead of axios, Web Crypto instead of a lib, Route Handlers instead of a framework). The tenth time, you gain a dependency deliberately — with its reason committed beside it.
Are lockfiles enough protection without the rules?
No — lockfiles record decisions, they do not make them. A phantom installed once enters the lockfile like a legitimate resident, and every later npm ci faithfully reproduces the fiction (or the malware). Rules prevent entry; lockfiles preserve state. You need the bouncer and the ledger, in that order.
Should I use npm audit or a scanner instead of rituals?
Both, layered: the ritual prevents entry, monthly depcheck removes dead weight, and npm audit watches what remains. Scanners report on known-bad residents; they cannot judge whether a resident should live there at all. Prevention (rules), hygiene (audits), surveillance (scanners) — three jobs, three tools, no substitutes.
How do transitive dependencies factor into approval?
npm view <name> dependencies is step two of the ritual for exactly this reason: a 5KB utility dragging 40MB of transitive tree fails the leanness test. Prefer zero-dependency packages (check dependencies: {} in the manifest) and treat every transitive stranger as your own attack surface — because at runtime, with your env keys loaded, it is.
What about frontend component libraries the agent loves adding?
Same rules, stricter stakes: UI kits import hundreds of components to use three, bloat the client bundle, and stamp a foreign design language over yours. Pin Tailwind plus inline SVG and forbid component libraries by rule — every agent-built screen stays coherent, light, and reviewable.
Keep reading
- Claude Hallucinated a Package That Doesn't Exist — the war story behind these rules
- OpenCode SaaS Starter: Stop the Every-Session Redesign — the file these rules live in
- Will Claude Code Respect Your Boilerplate? 6 Tests — the scorecard that grades dependency discipline
+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)
Command from your phone.
Built so autonomous AI agents build what you want without breaking what's already paying you.
- Built-in analytics — cookie-free mode, $0 forever, no PostHog bill
- SQLite ↔ Supabase: one setting, same field names
- Full digital marketplace & feedback boards included
- 3 payment rails: Stripe, LemonSqueezy & Dodo Payments
- Agent fences: lint gate, read-only data access, auto-rollback
- Ship from your phone via SSH & WireGuard/Tailscale in under a minute
$199
Get BoringPushOne-time payment · Lifetime updates · Unlimited projects.
Keep reading


