gledach / the shelf / recall

recall · slot 05 · shipped

Tell me when something
I own is recalled.
And how sure you are.

Recalls are published. Nobody reads them, because they are published as a firehose about everyone's belongings. This keeps a list of the things you actually own and checks it against four public registers.

MIT licensed · no account for any of the four registers · 0 runtime dependencies · 98 offline tests

gledach-recall check real output
  HIGH  Something scanned off the box
      Tickit Sensory Blocks Set of 16
      The toy could rupture and the filling of the inside could come
      out. The sand inside contains asbestos (measured value up to
      1.92% by weight). Asbestos could cause cancer.
      exact: barcode 5060138820289 matches exactly  ·  Fri, 25/09

  HIGH  The stomach tablets
      Shortage: Pantoprazol-Micro Labs 40 mg
      Expected to last until 28.10.2026. Flagged as relevant to
      hospital supply.
      exact: PZN 10516704 matches exactly  ·  Mon, 28/09

  Sources
      source      checked  result
  ──  ──────────  ───────  ──────────  ──────────────────
  ok  safetygate  3 items  2 findings  EU register only
  ok  bfarm       1 item   2 findings  DE register only
  ok  endoflife   1 item   0 findings  every jurisdiction
  ok  nhtsa       1 item   0 findings  US register only

  Absence of a notice is not proof a product is safe.
Both of those are genuine notices published that week, found by matching digits printed on the packaging. That last line is the point of the tool.

The situation

The notice for the thing in your kitchen was published. Nobody sent it to you.

A regulator puts out a notice, a manufacturer writes to whoever registered a warranty card in 2019, and the sand in your child's toy turns out to contain asbestos. You find out because someone mentions it.

Register Covers Scope Account
EU Safety Gatesafetygate Consumer products, toys, appliances, electronics, vehicles EU none
BfArMbfarm Medicine supply shortages, which is availability rather than safety DE none
NHTSAnhtsa Vehicle safety campaigns US none
endoflife.dateendoflife Software past its security support date everywhere none

Safety Gate is the one that matters most in Europe. There is no documented API, but there is a weekly report export in XML, which is better for this purpose: a report reference is a stable cursor, so a refresh only fetches weeks it has not seen, and a published week never changes so its cache never expires. BfArM reports availability, not safety: a hit means a manufacturer has declared a delivery shortage, so your pharmacy may not be able to fill a repeat prescription. Every notice from that source carries that sentence with it, because out of context shortage is easily misheard as unsafe.

Running it

Tell it what you own, then check.

The local inventory is gitignored, which is where a list of your possessions belongs. It is a plain JS file, not a config format to learn.

git clone https://github.com/gledach/recall && cd recall
npm test                  # 98 tests, offline, about two seconds
cp config/inventory.default.mjs config/inventory.local.mjs
node bin/recall.mjs check  # after listing what you own

No npm install. There is nothing to install, including its own CSV and XML readers. Needs Node 22 or newer. The command is gledach-recall. npm link puts that name on your PATH. Nothing named recall is installed: npm already publishes an unrelated package under that name.

Five kinds, each with the fields it needs

Kind Needs Also accepts
appliancemake, modelbarcode
devicemake, modelbarcode
vehiclemake, model, yearvin
softwareproduct, as an endoflife.date slugcycle
medicinenamepzn, the 8 digits on the pack

A missing required field is a startup error, not a skipped entry. An entry silently ignored looks exactly like an entry with nothing wrong, and it would be the one thing you cared about that never got checked.

Add the barcode. Everything else here is text matching: your spelling of a model number against a regulator's. A barcode is not matching at all, because the manufacturer printed those digits and the register reprinted them. Roughly half the EU alerts carry one, and every German shortage report carries a PZN. Only add digits you can read off the thing itself: a wrong barcode is worse than no barcode, because it will match something unrelated and be reported as certain.

How sure is it

It reports generously and grades honestly.

Two failure modes, and they are not symmetrical. Match loosely and every run reports a dozen unrelated things, people stop reading, then they miss the real one. Match tightly and the recall that mattered is never mentioned, which is worse and completely invisible.

Grade What it means
exactA barcode, PZN or VIN matched, or the register matched it for us.
strongMake and model both appear in the notice.
weakA distinctive model number appears but the make does not. Check it yourself. Included by default.
mentionOnly the make appears. Almost always noise, and hidden unless you ask for it.

weak is shown by default, because missing a real recall is worse than showing you something to dismiss. Nothing in the output ever says you are affected. It says what matched and how.

For agents

Five read-only tools, and read only on purpose.

It cannot add to your inventory and it cannot acknowledge a notice. Acknowledging is a person deciding they have dealt with something, and an assistant should not make that call on your behalf, so it stays a command you type.

npm run mcp
claude mcp add gledach-recall -- node /absolute/path/to/recall/mcp-server.mjs

check_inventory  ·  list_inventory  ·  notice_history
describe_sources  ·  blind_spots

Every result carries its coverage and the confidence grade of each match, because a model asked is my car recalled? will otherwise turn no notices found into your car is fine, which is a much stronger claim than the data supports.

What it cannot see

Stated here, because this tool is dangerous precisely when it is trusted more than it deserves.

A source that is unreachable is reported as unreachable, never as clean. Nothing found and could not look must never render the same way, and that distinction is the single most important thing in the codebase.

  • No UK, Swiss, Australian, Canadian or Japanese register. Not covered at all.

  • German vehicle recalls are not checked. That register sits behind a proof-of-work challenge. Vehicle coverage is US campaigns plus whatever the EU register happens to carry, which is not the same thing as German coverage.

  • Medicine coverage is German shortages only. There is no medicine safety register wired in.

  • Registers publish late. Days to weeks after a decision. A recall agreed this morning is not here.

  • Matching is text against text. A regulator who describes your product differently from how you wrote it down produces a low grade or nothing at all.

  • It checks your list, not your house. Anything you did not write down does not exist as far as this is concerned.

Tests: 98, offline, no network. A separate live suite answers a different question, namely whether the outside world still looks the way the parsers assume, and it is kept apart because a gate that fails when a public API has a bad afternoon teaches you to ignore the gate. The most dangerous bug this tool can have is a parser that returns zero records from a document full of them, because that is indistinguishable from good news. It has happened twice, which is why the live suite fails on a suspiciously empty result rather than reporting success.

This is not legal, medical or safety advice. If a notice concerns you, go to the register's own page and read the original. Data belongs to the European Commission, BfArM, NHTSA and endoflife.date respectively, and each source carries its own attribution.