Ask Claude Code, Cursor, or Copilot to add a dependency and it names one β instantly, confidently. That confidence comes from training recall: a snapshot of scraped code frozen at a cutoff date. So the agent can't know your team already has an internal, audited library for this. It can't know the package it just named went unmaintained six months ago, or that a supply-chain advisory landed last week. It picks anyway, with identical confidence either way.
Here's the part that compounds: a wrong pick doesn't bounce off. It gets written into your codebase β a hand-rolled auth flow, a dependency on an abandoned package, a second module that duplicates something you already own. That's tech debt the agent created and you inherit. And it's debt with interest: the agent builds on the bad choice, the problem surfaces downstream, and then you pay again β in tokens, review time, and rework β to unwind and redo it.
That's not a prompt problem. You can't fix it by asking the model to "be careful." The model is doing recall where it should be doing evaluation, and recall is frozen.
A few findings that should make you nervous about an agent picking dependencies unsupervised β and notice not one of these is only a security problem:
Each is a place recall fails, and a smarter prompt can't fix a frozen snapshot. The fix is putting real, dated, structured facts in front of the model at the moment it decides.
When the agent chooses from memory instead of facts, you pay on four fronts. Security is the one everyone leads with; it's the smallest of the four for most teams.
All four share one cause: the decision got made without the facts. That's the thing Starlog targets.
Starlog puts authoritative facts about a package in front of your agent β license, maintenance status, CVEs, supply-chain incidents β dated, local, no account:
npx starloghq facts ua-parser-js
You get the verified facts on file (here: the 2021 maintainer-account compromise), with an "as of" date. Sub-second, zero setup, no network call. It plugs into your agent three ways:
starlog facts <pkg>
),starlog_facts
) the agent calls itself,npm install
/ pnpm add
/ pip install
β One command wires all three into Claude Code (and drops instruction files for Cursor, Copilot, and Codex):
npx starloghq init
That's the pitch. The rest of this post is whether it actually works β because "give the model more context" is easy to claim and easy to fake.
I ran a controlled before/after. Control = a fresh agent answering from recall only. Treatment = the same agent, same prompt, given the package's Starlog facts. The only variable is the facts.
My first private-package test gave the agent a fact that said "POLICY: you must use @acme/flags, do not build custom." The agent used
@acme/flags
2/2. Clean flip!It's also worthless as evidence. A fact that says "you must use X" only proves the agent follows instructions β not that the information changed its mind. (A reviewer caught this; it's a tautology trap, and exactly the kind of thing a vendor demo quietly leans on.)
So I re-ran it with an informational-only fact: it states that an active internal package exists, with no "must use," no "don't build custom." Then I let the agent use its own judgment.
| Need | Control (recall only) | Treatment (informational-only fact) | Ξ |
|---|---|---|---|
| feature flags | build custom | ||
@acme/flags |
|||
| DIY β internal | |||
| auth / session | build custom | ||
@acme/session-core |
|||
| DIY β internal |
With no facts, the agent reaches for build custom on both β including a hand-rolled, unaudited auth layer, the textbook tech-debt-and-security liability in one object. Given only the information that an active internal library exists β with no instruction to prefer it β it chooses the internal library over building custom, 2/2, on its own judgment.
That's a hand-rolled module that never gets written: debt avoided at the exact moment it would have been created, plus consistency with whatever the rest of your team already ships. And it's the case the model structurally cannot recall β it has never seen your private @acme/*
packages. Facts are the only way it learns they exist.
Public packages are a weak venue for this β and saying so is more useful than hiding it. Claude's public recall is genuinely good, so most of the time the facts just agree with what it already knew:
| Package | Control | Treatment (+facts) | Read |
|---|---|---|---|
zod , fastify |
|||
| ADOPT | ADOPT | healthy decoys β no spurious flip β | |
posthog-node |
|||
| ADOPT | ADOPT + "pin away from the malicious 4.18.1 / 5.11.3 / 5.13.3" | ||
action changed β a post-cutoff supply-chain advisory (MAL-2025-190925 ) the model provably can't know |
|||
node-cache |
|||
| AVOID | ADOPT | changed, but ambiguous β "maintenance-only" is a longevity/debt signal, not a clean security verdict; no ground truth, so not counted as a win |
The one clean, information-carrying public change is posthog-node
: a supply-chain pin from after the training cutoff. That's the thesis in one row β facts matter precisely where recall can't reach. And the decoys didn't flip, so the agent isn't just rubber-stamping whatever the tool says.
The thing I'm proudest of is node-cache
not counting as a win. The fact ("maintenance-only") is ambiguous, there's no ground truth, so it doesn't go in the tally. A tool that books every change as a victory is lying to you. Same reason starlog facts some-unknown-pkg
returns an honest "no facts on file" instead of a confident guess β telling the agent "I don't know this one" is a feature, not a gap.
The before/after above confirms the mechanism on real model calls. The statistical backbone is a prior powered benchmark across four model vendors, measuring the one thing that drives all four payoffs β decision correctness: correct adopt/avoid decisions moved from ~20% to ~78%, with 100% unprompted adoption β when the facts are available, agents reach for them every time. They want this signal; they just don't have it by default. Every correct decision is debt not taken on, rework not paid for, and the occasional CVE caught.
npx starloghq facts event-stream
npx starloghq init
Source-available under BUSL-1.1 (free to use, modify, and self-host; converts to Apache-2.0 in 2030), listed in the official MCP Registry as io.github.starloghq/starlog
.
Repo, the 42-package corpus, and the full validation runbook: https://github.com/starloghq/index
If you build agents, the takeaway generalizes past dependency choice: anywhere the model is doing recall where it should be doing evaluation β anything time-sensitive, anything private β a small local index of dated, honest facts (one willing to say "I don't know") beats asking the model to try harder. The debt it never takes on, and the rework you never pay for, is the quiet win sitting right next to the CVE it catches. It can't recall what it never saw.