How to Work with DOCX Files Using Claude Skills: A Complete Guide
Claude Skills provides a dual-language toolkit for Microsoft Word documents, combining high-level JavaScript creation via docx-js with low-level Python OOXML editing for tracked changes, comments, and complex manipulations.
The ComposioHQ/awesome-claude-skills repository delivers a complete stack for handling .docx files programmatically. Whether you need to generate new Word documents from scratch or perform surgical edits with revision tracking on existing contracts, the architecture splits cleanly between creation (JavaScript/TypeScript) and editing (Python).
Creating New DOCX Files with JavaScript
For generating fresh documents, the toolkit uses the docx-js library—a thin wrapper around the Office Open XML (OOXML) format. The implementation resides in document-skills/docx/docx-js.md.
Before writing code, read the full tutorial to understand required components and style overrides. Then instantiate a Document, populate it with Paragraph and TextRun objects, and pack the buffer:
const { Document, Packer, Paragraph, TextRun, HeadingLevel } = require('docx');
const fs = require('fs');
const doc = new Document({
sections: [{
children: [
new Paragraph({
heading: HeadingLevel.TITLE,
children: [new TextRun("Report Title")]
}),
new Paragraph({
children: [new TextRun("First paragraph of the report.")]
})
]
}]
});
Packer.toBuffer(doc).then(buffer =>
fs.writeFileSync("Report.docx", buffer)
);
The Packer.toBuffer() method (or toBlob() for browsers) handles the OOXML serialization automatically.
Reading and Analyzing Existing DOCX Files
Text Extraction with Pandoc
For quick plain-text analysis while preserving tracked changes, use Pandoc to convert the document to Markdown:
pandoc --track-changes=all path/to/file.docx -o output.md
This approach, documented in document-skills/docx/SKILL.md (lines 31-40), is fastest when you only need readable content.
Raw XML Access
When you need comments, custom formatting, or embedded media, unpack the archive and edit XML directly:
python ooxml/scripts/unpack.py <office_file.docx> <out_dir>
Key XML parts include word/document.xml, word/comments.xml, and word/media/. This low-level access is required for surgical edits that preserve complex formatting.
Editing DOCX Files with Python and OOXML
For modifying existing documents—especially those requiring tracked changes—use the Python Document class implemented in document-skills/docx/ooxml/scripts/document.py. This class abstracts the OOXML boilerplate, automatically managing temporary unpacked copies, relationships, and content-type entries.
Basic Editing Workflow
from scripts.document import Document
# Unpack first (one time)
# python ooxml/scripts/unpack.py source.docx workdir
doc = Document('workdir', author="Alice", initials="AL", track_revisions=True)
# Example: change "30 days" to "45 days" while preserving formatting
node = doc["word/document.xml"].get_node(tag="w:r", contains="30 days")
rpr = node.getElementsByTagName("w:rPr")[0].toxml() if node.getElementsByTagName("w:rPr") else ""
replacement = f'''
<w:r w:rsidR="00AB12CD">{rpr}<w:t>within </w:t></w:r>
<w:del><w:r>{rpr}<w:delText>30</w:delText></w:r></w:del>
<w:ins><w:r>{rpr}<w:t>45</w:t></w:r></w:ins>
<w:r w:rsidR="00AB12CD">{rpr}<w:t> days</w:t></w:r>
'''
doc["word/document.xml"].replace_node(node, replacement)
doc.save() # Validates and repacks automatically
The Document constructor accepts track_revisions=True to enable redlining mode, ensuring all modifications follow the OOXML revision tracking specification.
Implementing Tracked Changes (Redlining)
Claude Skills enforces a strict "minimal, precise edit" policy for tracked changes:
- Surround only the changed text with
<w:del>(deletion) or<w:ins>(insertion) tags. - Preserve the original
<w:r>elements for unchanged runs to maintain RSIDs (revision save IDs) and styling integrity.
Batch your edits (3-10 changes per batch) to keep debugging manageable, then call doc.save() once to validate against XML schemas and repack the ZIP archive.
Adding Comments and Replies
Attach comments to specific content ranges using the add_comment method:
# Find nodes marking the change span
start_node = doc["word/document.xml"].get_node(tag="w:del", attrs={"w:id":"1"})
end_node = doc["word/document.xml"].get_node(tag="w:ins", attrs={"w:id":"2"})
doc.add_comment(
start=start_node,
end=end_node,
text="Why this change?"
)
doc.save()
This modifies both word/document.xml (comment range markers) and word/comments.xml (the comment content).
Inserting Images and Media
Images require placement in word/media/ plus relationship entries in word/_rels/document.xml.rels and content-type declarations in [Content_Types].xml. The Python helper automates this boilerplate:
from PIL import Image
import shutil, os
# 1. Copy image to media directory
media_dir = os.path.join(doc.unpacked_path, 'word/media')
os.makedirs(media_dir, exist_ok=True)
shutil.copy('logo.png', os.path.join(media_dir, 'image1.png'))
# 2. Calculate EMUs (English Metric Units: inches × 914400)
img = Image.open(os.path.join(media_dir, 'image1.png'))
width_emus = int(6.5 * 914400)
height_emus = int(width_emus * img.size[1] / img.size[0])
# 3. Add relationship (rid generated automatically)
rels = doc['word/_rels/document.xml.rels']
rid = rels.get_next_rid()
rels.append_to(rels.dom.documentElement,
f'<Relationship Id="{rid}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png"/>')
# 4. Register content type
doc['[Content_Types].xml'].append_to(
doc['[Content_Types].xml'].dom.documentElement,
'<Default Extension="png" ContentType="image/png"/>'
)
# 5. Insert drawing markup at specific location
node = doc["word/document.xml"].get_node(tag="w:p", line_number=100)
# ... (drawing XML insertion code)
See document-skills/docx/ooxml.md (lines 44-70) for the complete drawing markup template.
Converting DOCX to Images for Visual Inspection
For AI visual verification or human review, convert documents to JPEGs via PDF:
# Convert to PDF
soffice --headless --convert-to pdf document.docx
# Extract pages as images
pdftoppm -jpeg -r 150 document.pdf page
This workflow, detailed in document-skills/docx/SKILL.md (lines 56-81), produces 150 DPI JPEGs suitable for previewing layout changes.
Required Dependencies
Install these tools before working with DOCX files using Claude Skills:
| Tool | Purpose | Install Command |
|---|---|---|
| pandoc | Text extraction | sudo apt-get install pandoc |
| docx (npm) | JavaScript creation | npm install -g docx |
| LibreOffice | PDF conversion | sudo apt-get install libreoffice |
| poppler-utils | PDF to image (pdftoppm) |
sudo apt-get install poppler-utils |
| defusedxml | Secure XML parsing | pip install defusedxml |
Summary
- Use JavaScript (
docx-js) viadocument-skills/docx/docx-js.mdwhen creating new documents from templates or scratch. - Use Python (
Documentclass inooxml/scripts/document.py) when editing existing files with tracked changes, comments, or image insertions. - Unpack first using
ooxml/scripts/unpack.pybefore Python editing, then letdoc.save()handle repacking and validation. - Preserve formatting during edits by extracting existing
<w:rPr>run properties and re-injecting them into replacement XML. - Validate changes against OOXML schemas in
ooxml/scripts/validation/to ensure Microsoft Word compatibility.
Frequently Asked Questions
How do I preserve tracked changes when converting DOCX to Markdown?
Use Pandoc with the --track-changes=all flag: pandoc --track-changes=all input.docx -o output.md. This preserves insertion and deletion markup in the Markdown output, allowing Claude to see the edit history even in plain text format.
Can I edit a DOCX file without unpacking it first?
No. The Python OOXML workflow requires unpacking the ZIP archive first using python ooxml/scripts/unpack.py <file.docx> <directory>. The Document class then operates on the unpacked XML files and repacks them automatically when you call doc.save().
What is the difference between w:delText and w:t in tracked changes?
Use <w:delText> inside <w:del> elements to mark deleted content, and <w:t> inside <w:ins> elements for inserted content. This distinction allows Microsoft Word to render deletions with strikethrough while correctly identifying new text as insertions.
How do I calculate image dimensions for OOXML?
OOXML uses English Metric Units (EMUs), where 1 inch = 914,400 EMUs. Calculate width in EMUs as inches * 914400, then derive height proportionally: height_emus = width_emus * (original_height / original_width). Always use integer values for the final attributes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →