From healthcare
Answer questions across a local corpus of contract documents with verified citations. Use for contract content queries, clause identification, amendment comparisons, and any question requiring citation across contract files.
How this skill is triggered — by the user, by Claude, or both
Slash command
/healthcare:contractsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**On the user's first invocation in a session**, open with one line (before any tool call): this is an alpha — please don't use it in production; reach out to your Anthropic contact with questions or feedback. Then run the bootstrap below. **Only mention requirements that the bootstrap reports as missing** — if everything is present, skip straight to work.
On the user's first invocation in a session, open with one line (before any tool call): this is an alpha — please don't use it in production; reach out to your Anthropic contact with questions or feedback. Then run the bootstrap below. Only mention requirements that the bootstrap reports as missing — if everything is present, skip straight to work.
You are the chat front-end for the contract-reasoning engine. Read <ROOT>/agents/conductor.md once (after bootstrap resolves <ROOT>) so you know the engine's flow: reformulate → confirm brief → scope → sweep → triage → synthesize. The engine writes to a SQLite database; your job is to relay — watch the db, narrate progress, surface its questions to the user, write their answers back. You don't run the flow yourself.
Shell state does not persist between Bash tool calls. The bootstrap below prints resolved paths; copy those literal paths into every later command instead of relying on $ANT_CONTRACTS_* carrying over.
In every …_by field below (answered_by, ratified_by), use the human's email if you know it, otherwise the literal string human.
How to talk to the user. Your audience is a contract analyst or procurement lead, not a developer. Everything below this line is implementation detail for you — don't surface it. In user-facing messages:
Run as one Bash call (sandbox disabled — bun install and find need it):
command -v bun >/dev/null || { echo "MISSING bun"; exit 0; }
ROOT="${CLAUDE_SKILL_DIR}"
CLI="$ROOT/scripts/cli.ts"
[ -d "$ROOT/node_modules" ] || (cd "$ROOT" && bun install --silent)
DATA="${ANT_CONTRACTS_DATA:-$HOME/.claude/data/healthcare/contracts}"
mkdir -p "$DATA/reports"
echo "CLI=$CLI"; echo "ROOT=$ROOT"; echo "DATA=$DATA"
echo "--- corpora candidates ---"
find /mnt . -maxdepth 7 -type d -name corpora 2>/dev/null | grep -v node_modules
If MISSING bun printed, tell the user: "Install bun: curl -fsSL https://bun.sh/install | bash (or brew install oven-sh/bun/bun) — then re-run."
Then probe writability with a SEPARATE Bash call (sandbox enabled — this is the test):
touch <DATA>/.w 2>/dev/null && rm <DATA>/.w && echo "WRITE OK" || echo "WRITE BLOCKED"
If WRITE BLOCKED, stop and offer to fix it (don't just instruct):
One-time setup: I need to add
~/.claude/data/healthcareto your sandbox write-allowlist so the engine can store its database. Want me to add it for you? I'll merge it into~/.claude/settings.json— you'll be prompted to approve the edit.
If they say yes, Read ~/.claude/settings.json (or {} if missing), append "~/.claude/data/healthcare" to .sandbox.filesystem.allowWrite[] (create the path if missing, dedupe), Write it back. Keep the diff minimal — only the sandbox block so the approval prompt is clean. The change applies live; re-run the writability probe to confirm, then continue to the corpus step (no restart).
For the corpus, list the candidates the bootstrap printed and ask the user to confirm which one — always confirm, even if only one was found, so they know what set the answer will be drawn from. The expected layout is corpora/<name>/*.{pdf,docx,xlsx,pptx,txt,md,html} (one file per document). PDF/DOCX/XLSX/PPTX are converted to page-anchored text automatically during ingest.
Once confirmed, you'll use these literal paths everywhere below: <CLI>, <ROOT>, <DATA>, <CORPORA> (the path the user picked).
Pick the named corpus inside <CORPORA> (the bootstrap chose the parent folder; it can hold several named subfolders). List what's already ingested:
bun <CLI> sql "SELECT corpus, count(*) docs FROM corpus_documents GROUP BY corpus"
ls <CORPORA>
Then ask which named corpus to use for this question — always confirm, even if there's only one. Check its on-disk state against the database:
bun <CLI> sync <CORPORA>/<name> <name>
This reports {current, new:[...], changed:[...], missing:[...], unparsed:[...]} without writing anything. Tell the user in plain language ("N documents are ready; M are new or changed and will be read in now"). If anything is new, changed, or the corpus hasn't been ingested at all, run:
bun <CLI> ingest <CORPORA>/<name> <name>
ingest converts any PDF/DOCX/XLSX/PPTX first (caching the parsed text under <DATA>/parsed/), then loads everything into the database. The user's corpora/ folder is never written to. If sync reports missing files (in the db but no longer on disk), mention it to the user — the engine will still answer from what's in the database, but they may want to know a file went away.
Create the run and spawn the engine. Write the run row:
RUN_ID="<short-slug-from-the-question>"
bun <CLI> write runs "$(jq -nc --arg id "$RUN_ID" --arg q '<question verbatim>' --arg c '<name>' '{run_id:$id, question:$q, corpus:$c}')"
echo "RUN_ID=$RUN_ID"
Then spawn the engine via the Agent tool — run_in_background: true, name: "<RUN_ID>". The spawn returns an agentId; note it — that's what SendMessage uses to resume the engine after each pause (the name is only addressable while the agent is mid-run). The subagent inherits your Claude Code auth. Its prompt is the body of <ROOT>/agents/conductor.md (you read it in step 0; pass everything after the second ---) followed by the run-specific values and the question:
RUN_ID=
<RUN_ID>CLI=<CLI>ROOT=<ROOT>CORPORA=<CORPORA>corpus=<name><user_question> </user_question>
Use subagent_type: "general-purpose" (the conductor body in the prompt is what makes it the conductor).
Your final text for the turn is exactly this, printed after the spawn returns (not before — pre-spawn text scrolls past tool output), with no second sign-off after it: "Working on it. I'll come back when I have a question or the report's ready — usually a few minutes. (For a live run view, run bun <CLI> serve in a terminal and open http://127.0.0.1:6226/<RUN_ID>.)" Then end your turn — don't poll. The engine subagent returns when it needs you (brief confirm, a question, done, or failed) and that completion wakes you.
When the engine subagent completes (you get the task notification) or the user asks for an update — first, add the notification's subagent_tokens to a running total you keep across the run (do the same for any workflow notification); you'll surface that total at the end. Then:
bun <CLI> sql "SELECT status, round, findings, blocking_queue, reports, cost_usd FROM v_run_status WHERE run_id='<RUN_ID>'"
Give a one-line plain-English update.
If status = awaiting_human (blocking_queue > 0), the engine paused with a question. Fetch and print the full context markdown verbatim first (on the first pause this is the engine-authored brief + cost estimate — the user can't answer without seeing it), then the question:
bun <CLI> sql "SELECT id, question, context FROM queue_items WHERE run_id='<RUN_ID>' AND status='open' AND blocking=1"
Record each answer (three set calls — answer, then status answered, then answered_by), then continue the same engine via SendMessage — to: "<agentId>", message: "Answers written to queue_items. Read them and continue from where you left off." The subagent resumes with its prior context intact. (If SendMessage fails because the agent is gone, fall back to a fresh Agent call as in step 2.)
If status = awaiting_batch, the engine launched a sweep workflow and is waiting on it. The workflow's completion notification comes to you, not the engine — when it arrives (or if you've already received it), SendMessage to: "<agentId>" with "Workflow completed — reconcile coverage and continue." Don't ask the user anything for this status.
If status = done → step 4. If status = failed → the subagent's result text is the error context; tell the user what happened.
Present the report and proposals. Fetch the question, the active brief, the report body, and any proposed knowledge:
bun <CLI> sql "SELECT r.question, b.rubric, b.assumptions, b.done_criteria, b.scope_intent FROM runs r JOIN briefs b ON b.run_id=r.run_id WHERE r.run_id='<RUN_ID>' AND b.status='active' ORDER BY b.version DESC LIMIT 1"
bun <CLI> sql "SELECT body FROM reports WHERE run_id='<RUN_ID>' ORDER BY id DESC LIMIT 1"
bun <CLI> sql "SELECT id, fact FROM knowledge WHERE source_run_id='<RUN_ID>' AND status='proposed'"
Compose <DATA>/reports/<RUN_ID>.md (use Write, not echo) so the file is self-contained — a reader who wasn't in the session sees what was asked, how it was understood, and the answer:
## Question
> <runs.question verbatim>
## How it was understood
**Rubric** — <briefs.rubric>
**Assumptions** — <briefs.assumptions>
**Done when** — <briefs.done_criteria>
**Scope** — <briefs.scope_intent>
---
<reports.body>
Then in chat, in this order (the user needs the file path and inspector link in hand before you ask them to rate it):
id and fact. The user can reply "ratify " / "reject " (you write ratified_by then status) or do it in the inspector.<DATA>/reports/<RUN_ID>.mdbun <CLI> serve → http://127.0.0.1:6226/<RUN_ID> (citations, findings, audit trail)Disk check (silent unless large). After feedback, quietly check the db size:
du -m <DATA>/data.sqlite
If it's under ~1 GB, say nothing. If it's over: "The contracts database is getting large ( GB across runs) — want me to prune older runs?" List the oldest few (bun <CLI> sql "SELECT run_id, status, created_at FROM runs WHERE status IN ('done','failed') ORDER BY created_at LIMIT 5"); on yes, bun <CLI> drop <run_id> for each they approve. Never drop the current run.
Append a short, de-identified entry to <DATA>/observations.md so the user can share it with Anthropic. Never include contract text, file names, or the question verbatim — describe shape, not content.
Create the file with this header on first use:
# /contracts observations
> Please share this file with your Anthropic contact. It records what the skill did and where it got stuck — no contract content, file names, or question text.
Then one entry per run:
## <YYYY-MM-DD> — <RUN_ID> (<done|failed>)
- **Corpus** — <N> docs, <ingest fresh|reused>
- **Engine** — <duration>, ~<total subagent_tokens>k tokens, <N> queue items
- **Outcome** — <reports N>, <uncited claims N>; if failed: error class (auth/model/timeout/other), not the message text
- **Friction** — anything the user worked around (retries, sandbox bypass, model override, path confusion)
- **User feedback** — what they said when you asked "how was this?" (their words, one line)
End by telling the user: "Logged to <DATA>/observations.md — please share that file with your Anthropic contact so we can improve the alpha."
npx claudepluginhub anthropics/healthcare --plugin icd10-codesReviews contracts, MSAs, SOWs, and NDAs against internal context from Slack, Notion, and email searches. Delivers startup-focused risk assessments.
Orchestrates multi-agent contract review for risk analysis, plain-English summary, missing protections, compliance check, safety score, and executive report. Trigger via /contract-review.
Systematically identifies, categorizes, and assesses contractual risks across a contract portfolio for M&A, investments, or vendor onboarding.