Search FDA drug recall records by drug, firm, recency, or recall number — keyless, with a safety contract that never calls a drug "safe".
A keyless CLI over the openFDA drug enforcement endpoint. The check, firm, recent, and reference commands wrap FDA recall search with pre-built queries; every result cites the recall number, prints the FDA class legend, and carries an enforcement-not-medical-advice disclaimer. A drug with no recall is reported as 'no recall records found', never as safe.
Quick Start
# confirm the CLI and openFDA endpoint are reachable
drug-enforcement-pp-cli doctor --dry-run
# recalls mentioning a drug
drug-enforcement-pp-cli check "ibuprofen"
# narrow to the most serious (Class I) recalls
drug-enforcement-pp-cli check "metformin" --class 1
# recalls initiated in the last 30 days
drug-enforcement-pp-cli recent --days 30
Unique Features
These capabilities aren't available in any other tool for this API.
Recall lookups
-
check — Find active FDA recalls that mention a drug, optionally filtered to the most serious class.
Reach for this when an agent needs the recall status of a specific medication by name.
drug-enforcement-pp-cli check "ibuprofen" --class 1
-
firm — List every recall attributed to a recalling firm or manufacturer.
Use this to audit a manufacturer's recall history.
drug-enforcement-pp-cli firm "Teva"
-
recent — List recalls initiated in the last N days, most recent first.
Use this for a periodic sweep of newly initiated drug recalls.
drug-enforcement-pp-cli recent --days 30
-
reference — Show full detail for a single recall number, with the FDA class legend.
Use this to expand one recall's full facts after a check/firm/recent lookup surfaces its number.
drug-enforcement-pp-cli reference D-0183-2023
Usage
Run drug-enforcement-pp-cli --help for the full command reference and flag list.
Paths & environment variables
This CLI separates local files into four path kinds:
| Kind | Contents |
|---|
config | User-editable settings such as config.toml and saved profiles |
data | Durable local data such as data.db |
state | Runtime state such as persisted queries, jobs, and teach.log |
cache | Regenerable HTTP/cache files |
Each kind resolves independently. The ladder is:
- Per-kind env var:
DRUG_ENFORCEMENT_CONFIG_DIR, DRUG_ENFORCEMENT_DATA_DIR, DRUG_ENFORCEMENT_STATE_DIR, or DRUG_ENFORCEMENT_CACHE_DIR
--home <dir> for this invocation
DRUG_ENFORCEMENT_HOME for a flat relocated root
- XDG env vars:
XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME, XDG_CACHE_HOME
- Platform defaults matching existing installs
For containers and agent sandboxes, prefer a single relocated root:
export DRUG_ENFORCEMENT_HOME=/srv/drug-enforcement
drug-enforcement-pp-cli doctor
Under DRUG_ENFORCEMENT_HOME=/srv/drug-enforcement, the four dirs resolve to /srv/drug-enforcement/config, /srv/drug-enforcement/data, /srv/drug-enforcement/state, and /srv/drug-enforcement/cache.
MCP servers do not receive CLI flags from the host. Put relocation in the host env block:
{
"mcpServers": {
"drug-enforcement": {
"command": "drug-enforcement-pp-mcp",
"env": {
"DRUG_ENFORCEMENT_HOME": "/srv/drug-enforcement"
}
}
}
}
Precedence matters in fleets: an ambient per-kind variable such as DRUG_ENFORCEMENT_DATA_DIR overrides an explicit --home for that kind. Use DRUG_ENFORCEMENT_HOME or the per-kind variables for durable fleet relocation; treat --home as the weaker per-invocation lever.
Relocation is one-way. Unsetting DRUG_ENFORCEMENT_HOME does not move files back to platform defaults, and doctor cannot find files left under a former root. Move the files manually before unsetting relocation variables.
Existing installs keep working because the platform-default rung matches the legacy layout. Run drug-enforcement-pp-cli doctor --fail-on warn to check path warnings in automation.
Commands
enforcement
FDA drug recall enforcement records (openFDA /drug/enforcement.json)
drug-enforcement-pp-cli enforcement - Search drug recall enforcement records with an openFDA Lucene search expression
Output Formats
# Human-readable table (default in terminal, JSON when piped)
drug-enforcement-pp-cli enforcement
# JSON for scripting and agents
drug-enforcement-pp-cli enforcement --json
# Filter to specific fields
drug-enforcement-pp-cli enforcement --json --select id,name,status
# Dry run — show the request without sending
drug-enforcement-pp-cli enforcement --dry-run
# Agent mode — JSON + compact + no prompts in one flag
drug-enforcement-pp-cli enforcement --agent
Agent Usage
This CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--json output to stdout, errors to stderr
- Filterable -
--select id,name returns only fields you need
- Previewable -
--dry-run shows the request without sending
- Read-only by default - this CLI does not create, update, delete, publish, send, or mutate remote resources
- Offline-friendly - sync/search commands can use the local SQLite store when available
- Agent-safe by default - no colors or formatting unless
--human-friendly is set
Exit codes: 0 success, 2 usage error, 3 not found, 5 API error, 7 rate limited, 10 config error.
Health Check
drug-enforcement-pp-cli doctor
Verifies configuration and connectivity to the API.
Configuration
Run drug-enforcement-pp-cli doctor to see the resolved config, data, state, and cache directories. The platform-default config path is ~/.config/drug-enforcement/config.toml; --home, DRUG_ENFORCEMENT_HOME, and per-kind env vars can relocate it.
Static request headers can be configured under headers; per-command header overrides take precedence.
Troubleshooting
Not found errors (exit code 3)
- Check the resource ID is correct
- Run the
list command to see available items
Generated by CLI Printing Press
API-specific
- check returns 'no recall records found' — This means no FDA enforcement record matched — it is not a statement that the drug is safe. Consult a pharmacist or doctor.
- HTTP 429 from openFDA — openFDA is rate limited to 240 requests/minute per IP; wait and retry.