| name | docx |
| description | Use this skill whenever the user wants to create, edit, or extract content from Word documents (.docx files). Includes creating new documents, editing existing ones, extracting text, working with tables, images, tracked changes, headers/footers, and format conversion. |
DOCX Processing
Strategy by Task
| Task | Approach |
|---|
| Create new document | JavaScript docx npm package |
| Edit existing document | Unpack XML → edit → repack |
| Extract text | pandoc or unpack |
| Convert to other formats | pandoc |
Text Extraction
pandoc input.docx -t plain -o output.txt
pandoc input.docx -t markdown -o output.md
uv run --with python-docx - <<'EOF'
from docx import Document
doc = Document("input.docx")
for para in doc.paragraphs:
print(para.text)
EOF
Creating New Documents (docx npm)
Preferred for new documents — richer API than python-docx.
npm install docx
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, WidthType } = require("docx");
const fs = require("fs");
const doc = new Document({
sections: [{
properties: {
page: {
size: { width: 12240, height: 15840 },
},
},
children: [
new Paragraph({
children: [new TextRun({ text: "Hello World", bold: true })],
}),
],
}],
});
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("output.docx", buffer));
Critical Rules for docx-js
- Page size: Default is A4; use
{ width: 12240, height: 15840 } for US Letter
- Tables: Set both
columnWidths array AND individual cell width with WidthType.DXA — never use percentage widths (breaks Google Docs compatibility)
- Bullet lists: Use
LevelFormat.BULLET with numbering config; never insert Unicode bullet characters •
- Page breaks: Must be nested inside
Paragraph elements
- Images: Require explicit
type parameter: png, jpg, gif, bmp, or svg
Editing Existing Documents (XML)
.docx files are ZIP archives — unpack, edit XML, repack:
mkdir unpacked && cp input.docx unpacked/input.zip
cd unpacked && unzip input.zip -d contents
cd contents && zip -r ../output.docx .
XML Editing Standards
- Use smart quotes as XML entities:
’ (apostrophe), “/” (open/close quotes)
- Tracked changes:
<w:ins> for insertions, <w:del> for deletions, preserving <w:rPr> formatting blocks
- Comments: marker elements are siblings of text runs, never nested inside them
uv run --with lxml - <<'EOF'
from lxml import etree
tree = etree.parse("unpacked/contents/word/document.xml")
tree.write("unpacked/contents/word/document.xml", xml_declaration=True, encoding="UTF-8")
EOF
Python (python-docx) for Simple Tasks
For straightforward creation/editing when the docx npm approach is overkill:
uv run --with python-docx - <<'EOF'
from docx import Document
from docx.shared import Inches, Pt
doc = Document()
doc.add_heading("Title", 0)
doc.add_paragraph("Body text.")
table = doc.add_table(rows=2, cols=3)
table.cell(0, 0).text = "Header"
doc.save("output.docx")
EOF
Format Conversion (pandoc)
pandoc input.docx -o output.pdf
pandoc input.docx -o output.html
pandoc input.md -o output.docx
pandoc input.md --reference-doc=template.docx -o output.docx
Arch package: sudo pacman -S pandoc