About doc-extract
doc-extract is a stateless document-to-text skill that emits JSON without writing files. It is intended for other skills and scripts that need local extraction, with page anchors and the method used included in its output.
Key features
- 01Extracts text and outputs JSON
- 02Supports PDF, DOCX, XLSX, PPTX, and RTF
- 03Adds page anchors to paged documents
- 04Accepts a MIME type to identify files
- 05Exports functions for use in Bun TypeScript
Use cases
- 01Extracting text from clinical document attachments
- 02Passing page-anchored content to another skill
- 03Reusing extraction logic in Bun TypeScript projects
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ anthropics/ healthcare --skill doc-extractAfter installing, type/doc-extractin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
.gitignore.npmrcpackage.jsontsconfig.jsonscripts/decoders.mjsextract.tsDetails
From the project READMEdoc-extract
Shared document-to-text extraction. One script, no state: reads an input file, prints JSON to stdout, writes nothing to disk (PHI-safe — no caches, no temp files; callers own any caching).
Setup (once)
cd <this skill dir> && bun install
This pulls liteparse (the lit bin, used for PDF/DOCX/XLSX/PPTX, OCR included) and rtf-to-text (RTF). Without it, PDFs still work via a pdftotext -layout fallback if poppler is installed; other binary formats require liteparse.
Use
bun <this skill dir>/scripts/extract.ts <input-file> [--content-type <mime>]
Output on stdout:
{ "text": "...", "method": "liteparse | pdftotext | rtf-to-text | passthrough", "pages": 12 }
textis page-anchored for paged formats:=== [page N] ===markers between pages.pagesis present when page markers exist.methodis the extractor that actually produced the text.- Format is taken from the file extension; pass
--content-type(e.g.application/pdf) when the file has no useful extension, as with downloaded EHR attachments. Note liteparse refuses extension-less files, so those PDFs go through thepdftotextfallback. - Errors print
{"error": "..."}to stderr and exit 1.
Table caveat
Tables with multiple value columns (option A vs option B, in-tier vs out-of-tier) can interleave columns line-by-line in the extracted text: fragments of adjacent cells alternate, and a cell's text can even land mid-sentence inside a neighboring column. Values usually survive, but which column a value belongs to can become ambiguous. When an answer comes from one column of a multi-column table and the document has no redundant restatement of the value elsewhere, verify it by reading the original page directly before treating it as ground truth. The extracted text's === [page N] === anchor tells you which page: pass it to the Read tool's pages parameter (e.g. pages: "37") to render just that page to vision instead of the whole document.
For other skills
Import the functions instead of shelling out when you're already in bun TS:
import { extract, resolveLit } from "../doc-extract/scripts/extract";
const lit = resolveLit([myRoot]); // also checks myRoot/node_modules/.bin/lit
const text = extract(lit, "/path/to/file.pdf"); // string | null
The contracts skill consumes it this way (its ingest caching stays on the contracts side).