Skip to content
Security
Skill

/coding-icd10

Suggests candidate ICD-10-CM diagnosis codes (and ICD-10-PCS procedure codes) for diagnoses and procedures extracted by OpenMed, with rationale and a human-coder caveat. Use when the user wants to code a problem list, map a diagnosis span to a billable ICD-10-CM code, route a

BOOST
From plugin
openmed
5.7k74 skills
Install
$ npx -y skills add maziyarpanahi/openmed --skill coding-icd10 --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/coding-icd10

Context preview

The summary Claude sees to decide when to auto-load this skill.

Suggests candidate ICD-10-CM diagnosis codes (and ICD-10-PCS procedure codes) for diagnoses and procedures extracted by OpenMed, with rationale and a human-coder caveat. Use when the user wants to code a problem list, map a diagnosis span to a billable ICD-10-CM code, route a

SKILL.md

coding-icd10.SKILL.md
name: coding-icd10
description: "Suggests candidate ICD-10-CM diagnosis codes (and ICD-10-PCS procedure codes) for diagnoses and procedures extracted by OpenMed, with rationale and a human-coder caveat. Use when the user wants to code a problem list, map a diagnosis span to a billable ICD-10-CM code, route a finding to the right chapter, cross-walk ICD-9 via GEMs, or pre-fill an encounter for coder review. Trigger keywords: ICD-10-CM, ICD-10-PCS, diagnosis coding, billable code, GEMs, problem list coding, encounter diagnosis, chapter range, CMS code lookup. references/icd10-chapters.md holds the chapter/section ranges. Pairs after OpenMed NER: consume Disease/Pathology entities from openmed.analyze_text and propose codes a certified coder validates. ICD-10-CM/PCS files are public domain from CMS — no license barrier (unlike CPT, which is restricted and out of scope)."
license: Apache-2.0
metadata:
  project: OpenMed
  category: terminology-coding
  pairs: after
  version: "1.0"

Coding OpenMed diagnoses to ICD-10-CM / PCS

Suggest **ICD-10-CM** diagnosis codes (and **ICD-10-PCS** for inpatient procedures) for the diagnosis and procedure spans OpenMed extracts. This is **decision support for a certified coder**, not autonomous billing: OpenMed + this skill narrow the candidate set and explain *why*; a human validates the final, billable code.

ICD-10-CM and ICD-10-PCS are **public domain**. CMS publishes the complete annual code files, addenda, and indexes for free. (CPT/HCPCS procedure codes are **AMA-licensed and restricted** — out of scope here; obtain those separately under the user's own AMA license.)

When to use

  • A note yields diagnoses ("type 2 diabetes with diabetic CKD", "community-

acquired pneumonia") and you want candidate ICD-10-CM codes plus rationale.

  • You need to **route** a span to the right chapter quickly

(see `references/icd10-chapters.md` for code ranges).

  • You hold legacy ICD-9 codes and need an approximate **GEM** cross-walk.
  • You are pre-filling encounter diagnoses for a coder's review queue.

For clinical-meaning codes use `mapping-to-snomed`; for HCC/risk capture use `coding-hcc-risk-adjustment`; this skill is for the ICD-10 classification.

Quick start (public data + public FHIR lookup)

Two complementary paths, both license-clean:

**A) CMS files, loaded locally** (public domain; you download once):

# CMS publishes the order/addenda file; load the code->description table.
# Columns: code (no dot), description; you insert the dot for display.
icd10cm = {}                       # "E1122" -> "Type 2 diabetes mellitus with diabetic chronic kidney disease"
with open("icd10cm_order_2025.txt", encoding="latin-1") as fh:
    for line in fh:
        code = line[6:13].strip()
        billable = line[14] == "1"     # '1' = valid billable code
        long_desc = line[77:].strip()
        if billable:
            icd10cm[code] = long_desc

def search_local(term: str, limit: int = 5):
    t = term.lower()
    hits = [(c, d) for c, d in icd10cm.items() if t in d.lower()]
    return sorted(hits, key=lambda cd: len(cd[1]))[:limit]

**B) A FHIR terminology server that hosts ICD-10-CM** (public servers exist; e.g. an NLM Clinical Tables endpoint or your own HAPI/Ontoserver):

import requests

# NLM Clinical Tables (public, no key) — ICD-10-CM autocomplete/search:
def search_icd10cm(term: str, count: int = 7):
    r = requests.get(
        "https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search",
        params={"sf": "code,name", "terms": term, "maxList": count}, timeout=10,
    )
    r.raise_for_status()
    _total, codes, _extra, display = r.json()
    return list(zip(codes, [d[1] for d in display]))   # [(code, name), ...]

print(search_icd10cm("type 2 diabetes nephropathy"))

Workflow

1. **Extract** diagnosis/procedure spans with OpenMed (Disease/Pathology models). 2. **Route to a chapter** using the span's clinical theme and `references/icd10-chapters.md` (e.g. endocrine → E00–E89, circulatory → I00–I99). This shrinks the search space and catches obvious mis-hits. 3. **Search** the code text (local CMS table or the NLM API) for candidates. 4. **Apply ICD-10-CM specificity rules** in your rationale: laterality, acute/chronic, episode of care, "with"/"due to" combination codes, and "code first / use additional code" notes. Flag where the note lacks the detail a billable code requires. 5. **Rank** candidates; present the top few **with rationale and the missing- detail caveat**, not a single auto-selected code. 6. **Emit** `{system: "http://hl7.org/fhir/sid/icd-10-cm", code, display}` marked `status: needs-coder-review`, with OpenMed source offsets.

Hand-off from OpenMed

`openmed.analyze_text(..., output_format="dict")` returns `entities`, each a dict with `text`, `label`, `confidence`, `start`, `end`. Consume Disease/Pathology spans:

import openmed

note = "Assessment: type 2 diabetes with diabetic nephropathy; CAP."
result = openmed.analyze_text(
    note,
    model_name="disease_detection_superclinical",   # Disease category
    output_format="dict",
)

DX_LABELS = {"DISEASE", "CONDITION", "PATHOLOGY"}
for ent in result["entities"]:
    if ent["label"] in DX_LABELS:
        candidates = search_icd10cm(ent["text"], count=5)
        print(ent["text"], ent["start"], ent["end"],
              f"(conf {ent['confidence']:.2f}) ->", candidates)
        # surface as SUGGESTIONS for a coder — never auto-bill

Keep OpenMed's `start`/`end` offsets next to each suggested code so the coder can jump to the exact supporting text. Store offsets and codes only — never the raw note in your suggestion log.

Edge cases & gotchas

  • **Human-in-the-loop is mandatory.** ICD-10-CM coding has legal/financial

weight. Output candidates with rationale; a certified coder assigns the final billable code. Never present a suggestion as an authorized claim.

  • **Specificity & unspecified codes.** Man
Read more
Ships withopenmed

Local-first healthcare AI: clinical NER and HIPAA PII de-identification on hardware you control. 2,200+ medical models, 35 model-backed PII languages, and Python, MLX, Android and browser runtimes. Apache-2.0 SDK.

Get the whole plugin

Other skills on openmed.