# Ingesting Clinical Documents

Turn scanned faxes, images, and CSV/CDA exports into clean text ready for OpenMed...

- Repository: https://github.com/maziyarpanahi/openmed (5755 stars)
- Category: Writing
- License: Apache-2.0
- Last updated: 2026-10-31
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add maziyarpanahi/openmed --skill ingesting-clinical-documents -g -a claude-code -y`
Codex: `npx skills add maziyarpanahi/openmed --skill ingesting-clinical-documents -g -a codex -y`
Cursor: `npx skills add maziyarpanahi/openmed --skill ingesting-clinical-documents -g -a cursor -y`
Gemini CLI: `npx skills add maziyarpanahi/openmed --skill ingesting-clinical-documents -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add maziyarpanahi/openmed`

## Description

Turn scanned faxes, images, and CSV/CDA exports into clean text ready for OpenMed de-identification and NER, fully on-device. Use when the user has clinical documents (image scans, photographed/faxed notes, tabular CSV/TSV exports, C-CDA XML) and needs OCR or structured intake before openmed.deidentify and openmed.analyze_text, asks about openmed.multimodal, OCR engines (Tesseract / PaddleOCR), tabular redaction, or layout and reading order. Covers the verified ocr() and redact_document() entry points and the ExtractedDocument contract. Pairs before deidentifying-clinical-text and extracting-clinical-entities.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Ingesting Clinical Documents

Clinical text often arrives as scanned faxes, photographed notes, CSV exports, or
C-CDA XML, not plain text. `openmed.multimodal` converts these into a normalized
`ExtractedDocument` (clean text + character-offset → source-location spans) so you
can run de-identification and NER. It runs **on-device**: OCR backends are local,
no document leaves the machine.

## When to use

- You have **images / scanned faxes** of clinical notes and need text out (OCR).
- You have **CSV/TSV** patient exports that need column-aware handling.
- You have **C-CDA XML** to flatten into text.
- You are building the **intake stage** that feeds `openmed.deidentify` and
  `openmed.analyze_text`.

This is the **first** stage. After intake, hand off to
`deidentifying-clinical-text` then `extracting-clinical-entities`.

## What is supported today

`redact_document` dispatches by file extension. Live handlers:

| Input | Extensions | Path |
| --- | --- | --- |
| Images / scans | `.png .jpg .jpeg .tif .tiff .bmp .gif .webp` | OCR (`ocr()` / image handler) |
| Tables | `.csv .tsv` | column-aware tabular redaction |
| C-CDA | `.xml` (detected as CDA) | stdlib CDA adapter |

**PDF and DOCX have no live handler yet**, `redact_document("x.pdf")` raises
`UnsupportedDocumentError`. Convert PDFs to page images first (or to text with your
own tool) and feed the images through OCR. See
[references/multimodal-ingest.md](references/multimodal-ingest.md) for the full
contract, engines, and the tabular pipeline.

## Install

```bash
pip install "openmed[multimodal]"      # document intake contract + image deps
pip install "openmed[ocr-paddle]"      # add the PaddleOCR engine
# Tesseract engine also needs the system binary, e.g.:  brew install tesseract
```

## Quick start: OCR an image, then de-identify

The clean two-step intake path. `ocr()` lives in the submodule (it is intentionally
not re-exported from `openmed.multimodal`):

The rest: https://github.com/maziyarpanahi/openmed/blob/HEAD/skills/ingesting-clinical-documents/SKILL.md
