Create, edit, and analyze Microsoft Word .docx files (reports, contracts, proposals) with styles, tables, headers/footers, template filling, content extraction, and conversion to HTML; support review...
This skill covers creation, editing, review, extraction, and release workflows for .docx documents.
Modern best practices (Jul 2026):
.docx as the editable source and PDF as a release artifact..docm, .dotm) as untrusted by default.docxtpl with a Word-authored template.python-docx.docx.mammoth, then sanitize before rendering or storing the output.MarkItDown or Docling..docx and use Word Compare, or switch to OOXML-specialized tooling..doc, convert to .docx first. If it is .docm or .dotm, do not trust embedded macros.| Task | Tool/Library | Language | When to Use |
|---|---|---|---|
| Create/edit DOCX | python-docx |
Python | Structural edits, reports, contracts, section/table/image work |
| Create/edit DOCX | docx |
Node.js | Server-side generation in TypeScript-heavy stacks |
| Template fill | docxtpl |
Python | Word-authored templates, mail merge, batch documents |
| Add/access comments | python-docx + Word review workflow |
Python / Word | Review notes without tracked revisions |
| Convert DOCX to HTML | mammoth |
Node.js | Semantic HTML from trusted documents |
| Convert DOCX to Markdown | MarkItDown |
Python | LLM/RAG ingestion where Markdown is preferred |
| Convert DOCX to Markdown/HTML/JSON | Docling |
Python / CLI | Multi-format ingestion, structured extraction, batch conversion |
| Parse text/tables/metadata | python-docx + OOXML inspection |
Python | Extraction, audits, migration tooling |
| Parse tracked changes/comments | OOXML, Open XML SDK, docx4j, Aspose.Words | Python / .NET / Java | Revision-heavy workflows and interoperability edge cases |
| Convert DOCX to PDF | Word automation / LibreOffice headless | OS tooling | Release artifacts and cross-platform smoke checks |
docxtpl when a legal, ops, or business user needs to maintain the template in Word.python-docx for moderate formatting complexity where you control the document structure in code.docx when the surrounding service and tests already live in Node.js.mammoth for trusted, text-first conversion to HTML; it is not a fidelity-preserving renderer.MarkItDown for simple DOCX-to-Markdown pipelines.Docling when DOCX is only one input among many formats or you need HTML/JSON/Markdown/text output from a unified pipeline.DOCX request
|
v
Classify file + trust level
|-- .docx / .dotx -----> normal OOXML workflow
|-- .doc -------------> convert to .docx first
|-- .docm / .dotm ----> treat macros as untrusted
|
v
Choose lane
|-- Word-owned template ------> docxtpl
|-- Python structural edit ---> python-docx
|-- Node service generation --> docx
|-- trusted HTML conversion --> mammoth + sanitizer
|-- Markdown / JSON ingest ---> MarkItDown or Docling
|-- tracked-change review ----> revised DOCX + Word Compare
|
v
Generate, edit, or extract
|
v
Quality gate
|-- parseability + unresolved tags ---> scripts/docx_quality_gate.py
|-- comments / revisions / OOXML ----> scripts/docx_inspect_ooxml.py
|
v
Viewer, accessibility, and release checks
.docx and .dotx are Office Open XML packages; .doc is legacy binary and needs conversion first..docm and .dotm are macro-enabled; do not treat them as safe content inputs.python-docx can add and read comments in the main document body, but not threaded replies/resolved states, and not comment anchors in headers/footers.python-docx does not provide reliable tracked-change authoring.mammoth performs no sanitization of generated HTML or links from untrusted source documents.Do not assume the environment has a current library. This is the single most common way this skill causes a confident-but-wrong answer:
Document.add_comment() only exists from python-docx 1.2.0 onward. On an older pinned version it raises AttributeError, not a graceful fallback. Check first: python -c "import docx; print(docx.__version__)"..alt_text on InlineShape) as of the current 1.x line — InlineShape only documents height, width, and type. The OOXML workaround in references/accessibility-compliance.md reaches into the private _inline attribute; treat that as an implementation detail that can move between releases, re-verify after any python-docx upgrade, and prefer python-docx's own comment/style APIs wherever a public one exists instead of private attributes.<w:ins>/<w:del>) will fail any real redline/legal review because it carries no revision metadata..docx/.dotx vs .docm/.dotm vs legacy .doc.docxtplpython-docx or docxMarkItDown, Docling, or mammothscripts/docx_quality_gate.py and, when needed, scripts/docx_inspect_ooxml.py.python-docx)from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Inches
doc = Document()
title = doc.add_heading("Quarterly Review", 0)
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc.add_paragraph("Executive summary goes here.")
table = doc.add_table(rows=2, cols=2)
table.style = "Table Grid"
table.rows[0].cells[0].text = "Metric"
table.rows[0].cells[1].text = "Value"
table.rows[1].cells[0].text = "Revenue"
table.rows[1].cells[1].text = "$1.2M"
doc.add_picture("chart.png", width=Inches(4.5))
doc.save("quarterly-review.docx")
python-docx)from docx import Document
doc = Document()
paragraph = doc.add_paragraph("This clause needs legal review.")
comment = doc.add_comment(
runs=paragraph.runs,
text="Clarify whether this applies to renewals as well.",
author="Legal",
initials="LG",
)
comment.paragraphs[0].add_run(" Add the renewal edge case explicitly.").bold = True
doc.save("reviewable.docx")
docxtpl)from docxtpl import DocxTemplate
doc = DocxTemplate("template.docx")
context = {
"company_name": "Acme Corp",
"contract_date": "2026-03-13",
"items": [
{"name": "Widget A", "price": 100},
{"name": "Widget B", "price": 200},
],
}
doc.render(context)
doc.save("filled-template.docx")
node scripts/docx_to_html.mjs input.docx output.html --style-map custom-style-map.txt --extract-images-dir output-assets/
python3 scripts/docx_extract.py input.docx --include headers footers hyperlinks comments images --out extracted.json
scripts/docx_quality_gate.py before shipping or batch-publishing.Use only when explicitly requested and policy-compliant.
Resources
Scripts
scripts/docx_inspect_ooxml.py - Dependency-free OOXML inspection for tracked changes and commentsscripts/docx_extract.py - Extract text, tables, metadata, and optional headers/footers/hyperlinks/comments/images to JSONscripts/docx_render_template.py - Render a docxtpl template from JSONscripts/docx_to_html.mjs - Convert trusted .docx to HTML with style maps and optional image extractionscripts/docx_quality_gate.py - Validate parseability, unresolved template tags, tracked-change/comment signals, and optional LibreOffice conversionTemplates
Related Skills
data/sources.json as the starting set of primary sources.Before applying this skill on a non-trivial task, read learnings.consolidated.md in this directory (and learnings.md if present).
After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to learnings.md via agents-skills-feedback-loop/scripts/append_learning.py. Do not modify SKILL.md itself.