anthropics/fraud-detection
Screen a Medicare/Medicaid claims corpus for fraud, waste, and abuse and produce ranked, fully-cited investigation referrals for an SIU / program-integrity team. Use when asked to run a fraud sweep, screen claims for FWA, find billing anomalies, or generate investigation referrals over a claims dataset.
npx skills add https://github.com/anthropics/healthcare --skill fraud-detection
Screens a Medicare/Medicaid claims corpus against the public rulebook (NCCI MUE, OIG LEIE,
CMS enrollment, PFS) and produces ranked, fully-cited investigation referrals for an SIU.
The skill orchestrates a three-tier investigation: a deterministic floor does the detection,
the model judges and narrates on top, and every dollar/rule allegation traces back to the floor.
— that's a downstream investigative/legal determination. This is standard SIU language and the
framing the renderers use.
$CLAUDE_HEALTHCARE_DATA/fraud-detection/out/; the payer's SIU workflowdecides what to do with them. The model does not send/publish on its own.
corpus.duckdb (canonical 6-table schema: claims-schema.sql). Gettingthis is step 1 below — without it nothing else matters.
2026q3).medicare / medicaid).All fetched/generated state lives outside the plugin install path (which is wiped on upgrade)
at ~/.claude/data/healthcare/fraud-detection/ — override the parent dir with
$CLAUDE_HEALTHCARE_DATA (each skill appends its own name). Below, data-cache/ and out/ are
subdirectories of $CLAUDE_HEALTHCARE_DATA/fraud-detection. Resolve it once at the start of a run:
export CLAUDE_HEALTHCARE_DATA="${CLAUDE_HEALTHCARE_DATA:-$HOME/.claude/data/healthcare}"
corpus.duckdb. Open with: *"Where do your adjudicated claimslive?"* and follow ${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/LOAD-CLAIMS.md — it walks you
and the user from "I don't know" to a populated $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/corpus.duckdb. If they
already have a .duckdb with the canonical tables (schema:
${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/claims-schema.sql), use it directly.
Draft the brief (corpusDb path, quarter, line of business) and confirm scope.
$CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/reference/<quarter>/reference.duckdb. If that file is missing for the
requested quarter, fetch it now — this prints per-source ✓ name (size) progress as ~34 sources land:
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/fetch-reference.js" 2026q3
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/fetch-enrichment.js"
Requires unzip and pdftotext (poppler) on PATH; both ship with most distros / `brew install
poppler`. Needs real network egress — if you see "Could not resolve host" for cms.gov / oig.hhs.gov,
the command sandbox is blocking it; re-run with sandbox disabled. Policy PDFs (NCCI manual, MLN articles) land under reference/<q>/policy/*.txt
for grep; everything keyed lands in reference.duckdb. Skip if already present. If a fetch fails
or a table is missing, see REFERENCE-DATA.md for source URLs and recovery.
runs are preserved side-by-side. Every script honors FRAUD_OUT_DIR:
export FRAUD_OUT_DIR="$CLAUDE_HEALTHCARE_DATA/fraud-detection/out/run-$(date +%Y%m%d-%H%M)"
mkdir -p "$FRAUD_OUT_DIR"
echo "$FRAUD_OUT_DIR"
Use the printed absolute path verbatim as outDir in the next step.
scriptPath: ${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/workflows/investigate.jsargs: { "corpusDb": "<abs path to corpus.duckdb>", "quarter": "2026q3", "lob": "medicaid", "pluginRoot": "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection", "dataRoot": "<abs $CLAUDE_HEALTHCARE_DATA/fraud-detection>", "outDir": "<abs FRAUD_OUT_DIR from step 3>" }The workflow runs three stages (see "How it works"):
scripts/screen.js, zero model) → $FRAUD_OUT_DIR/referrals.detect.json.status + adjudication.reason; mechanical detectors auto-confirm. Adjudicate may dismiss or downgrade, never add.Tell the user they can watch the fan-out live with /workflows.
workflow sandbox has no filesystem, so write its return to disk and let apply-stages.js produce
the auditable spine. FRAUD_OUT_DIR does not persist across separate Bash calls — re-export
it (to the same absolute path you printed in step 3) at the top of every shell block that needs it:
Use the Write tool to save the workflow's return JSON verbatim to
$FRAUD_OUT_DIR/workflow-result.json (it can be 50KB+ — don't heredoc it through Bash). Then:
export FRAUD_OUT_DIR="<abs path from step 3>"
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/apply-stages.js"
This writes $FRAUD_OUT_DIR/referrals.adjudicated.json, referrals.final.json, referrals.json
(canonical, = final), and the renderer sidecars (source-excerpts.json, providers.json).
Then render the packets FIRST, then the dashboard (the dashboard only links a provider row to its
packet if that packet file already exists), then the xlsx:
export FRAUD_OUT_DIR="<abs path from step 3>"
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/render-packet.js" --all
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/render-dashboard.js"
node "${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/scripts/render-xlsx.js"
→ $FRAUD_OUT_DIR/provider-packet-<npi>.html ×N, index.html, referrals.xlsx.
in the side-pane preview — npx serve "$FRAUD_OUT_DIR" (the dashboard is index.html,
so the root URL is the dashboard; packet links resolve as siblings).
$FRAUD_OUT_DIR/index.html — try in order, stop at the first that works:
f="$FRAUD_OUT_DIR/index.html"
open "$f" 2>/dev/null \ # macOS
|| xdg-open "$f" 2>/dev/null \ # Linux
|| wslview "$f" 2>/dev/null \ # WSL
|| powershell.exe start "$(wslpath -w "$f")" 2>/dev/null \ # WSL→Windows fallback
|| cmd.exe /c start "" "$f" 2>/dev/null \ # Windows
|| echo "Could not auto-open; open manually: $f"
Skip this entirely in a headless/non-interactive run (eval, CI, Cowork) — just report the path.
Don't fail the run if opening/serving fails.
the workflow result, verbatim where it cites numbers. Surface meta.disclaimer if it is set. Do
not add any dollar or rule the deterministic floor did not produce. **End the response with the
run-directory path on its own line** so downstream graders/tools can locate the artifacts:
Run directory: <absolute $FRAUD_OUT_DIR>
${CLAUDE_PLUGIN_ROOT}/skills/fraud-detection/PROPOSE-DETECTORS.mdto mine this run for new detector candidates and payer-specific adjudicate-time checks.
The model adjudicates, explores, and narrates freely, but **any dollar or rule allegation must trace
to a detect-stage deterministic recompute (the gate in scripts/gate.js). Adjudicate may dismiss
or downgrade** a finding (with an auditable reason) — it never adds one or changes its dollars.
Synthesize narratives are separate, clearly-marked model output and never introduce a number the
floor did not compute.
The deterministic pipeline reads enrichment from local cached files (scripts/fetch-enrichment.js
→ $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/enrichment/, loaded via scripts/enrichment.js) — no runtime auth, no drift, fully
reproducible. The healthcare plugin's bundled MCP servers (CMS Coverage / ICD-10 / NPI Registry) are
for interactive adjudicate/synthesize exploration only; the pipeline does not depend on them.
workflows/investigate.js (Claude Code dynamic Workflow): Detect → Adjudicate → Synthesize.scripts/screen.js <corpus.duckdb> <quarter> <lob> runs all detectors andwrites $FRAUD_OUT_DIR/referrals.json. Zero model calls.
scripts/dNN-*.js (one deterministic module each, sharing the Finding shape).scripts/pipeline.js (run → gate → roll up → rank → referrals.json).scripts/gate.js (independently recomputes every cited number; uncited ornon-reproducing findings are dropped — "citation-or-zero").
scripts/reference-data.js loads $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/reference/ (NCCI/MUE, LEIE, PFS,enrollment), fetched by scripts/fetch-reference.js, versioned by date-of-service quarter.
scripts/enrichment.js loads $CLAUDE_HEALTHCARE_DATA/fraud-detection/data-cache/enrichment/, fetched by fetch-enrichment.js.scripts/apply-stages.js (workflow return → referrals.adjudicated.json / .final.json).scripts/render-dashboard.js (→ index.html), render-packet.js, render-xlsx.js → $FRAUD_OUT_DIR/.Every allegation cites a public rule with a value the gate independently recomputes, or it is dropped.
Take anthropics/fraud-detection from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npx, brew.
Without those the skill loads but fails at the first command.