How to Use the docx Skill to Create Word Documents Programmatically
The docx skill combines JavaScript's docx library with Python validation scripts to generate, edit, and validate Microsoft Word files through a declarative three-layer architecture.
The anthropics/skills repository provides a self-contained docx skill that enables programmatic creation of .docx files. Whether you need to generate reports from templates or build complex documents with tables and images, this skill offers a structured workflow using the open-source docx NPM package alongside Python utilities for validation and repair.
Architectural Overview of the docx Skill
The docx skill follows a three-layer architecture designed to ensure cross-platform compatibility with Microsoft Word, Google Docs, and LibreOffice.
Specification Layer
The SKILL.md file at skills/docx/SKILL.md defines the skill's purpose, triggers, and high-level workflows. It specifies critical conventions such as using DXA units (twentieths of a point) for measurements and requiring explicit page sizes to avoid default A4 formatting.
Generation Layer
JavaScript code utilizes the docx NPM package to assemble document models including sections, paragraphs, tables, images, headers, footers, and tables of contents. The library writes binary .docx files that conform to Office Open XML standards.
Validation & Packaging Layer
Python helper scripts in skills/docx/scripts/office/ handle post-processing:
validate.py– Runs schema validation against Microsoft Office Open XML schemas and auto-repairs broken relationship IDs.unpack.py– Extracts the ZIP archive, prettifies XML, merges adjacent text runs, and converts smart quotes for reliable find-and-replace operations.pack.py– Re-assembles XML into a.docxfile, optionally running validation and preserving original file metadata.
Creating New Documents with JavaScript
Installing Dependencies
First, install the docx library globally or in your project:
npm install docx
Building a Complete Document Example
The following example demonstrates the strict conventions required by the skill, including dual-width table definitions, explicit page sizing, and proper list formatting:
const {
Document, Packer, Paragraph, TextRun, HeadingLevel,
PageOrientation, WidthType, Table, TableRow, TableCell,
BorderStyle, ShadingType, ImageRun, PageBreak, Header, Footer, PageNumber, TableOfContents, LevelFormat
} = require('docx');
const fs = require('fs');
const doc = new Document({
sections: [{
properties: {
page: {
size: {
width: 12240, // US Letter width in DXA (8.5")
height: 15840, // US Letter height in DXA (11")
orientation: PageOrientation.PORTRAIT
},
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }
}
},
headers: {
default: new Header({
children: [new Paragraph({ children: [new TextRun('My Header')] })]
})
},
footers: {
default: new Footer({
children: [new Paragraph({
children: [new TextRun('Page '), new TextRun({ children: [PageNumber.CURRENT] })]
})]
})
},
children: [
// Title
new Paragraph({
heading: HeadingLevel.HEADING_1,
children: [new TextRun('Quarterly Report')]
}),
// Table of Contents (auto-generated on open)
new Paragraph({
children: [
new TableOfContents('Table of Contents', {
hyperlink: true,
headingStyleRange: '1-3'
})
]
}),
// Simple bullet list using LevelFormat.BULLET
new Paragraph({
numbering: { reference: 'bullets', level: 0 },
children: [new TextRun('First bullet')]
}),
new Paragraph({
numbering: { reference: 'bullets', level: 0 },
children: [new TextRun('Second bullet')]
}),
// Table with dual width rule (columnWidths + per-cell width)
new Table({
width: { size: 9360, type: WidthType.DXA }, // 9.36 in total (US Letter - 2 in margins)
columnWidths: [4680, 4680],
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 4680, type: WidthType.DXA },
borders: { top: { style: BorderStyle.SINGLE, size: 1, color: 'CCCCCC' } },
shading: { type: ShadingType.CLEAR, fill: 'D5E8F0' },
margins: { top: 80, bottom: 80, left: 120, right: 120 },
children: [new Paragraph('Header 1')]
}),
new TableCell({
width: { size: 4680, type: WidthType.DXA },
borders: { top: { style: BorderStyle.SINGLE, size: 1, color: 'CCCCCC' } },
shading: { type: ShadingType.CLEAR, fill: 'D5E8F0' },
margins: { top: 80, bottom: 80, left: 120, right: 120 },
children: [new Paragraph('Header 2')]
})
]
})
]
}),
// Image with mandatory type field
new Paragraph({
children: [
new ImageRun({
type: 'png',
data: fs.readFileSync('logo.png'),
transformation: { width: 200, height: 150 },
altText: { title: 'Logo', description: 'Company logo', name: 'logo' }
})
]
}),
// Page break
new Paragraph({ children: [new PageBreak()] }),
// Closing paragraph
new Paragraph('End of report.')
]
}]
});
// Write the .docx file
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync('QuarterlyReport.docx', buffer);
});
Critical conventions demonstrated:
- Explicit page sizing: Set to US Letter (12240×15840 DXA) rather than relying on defaults.
- Dual-width tables: Both
columnWidthsarray and per-cellwidthproperties useWidthType.DXA. - Proper list formatting: Uses
LevelFormat.BULLETvia thenumberingconfiguration instead of raw Unicode characters. - Image requirements: The
typefield is mandatory forImageRun.
Editing Existing Word Documents
Unpacking and Modifying Templates
For template-based workflows, use the Python helper scripts to manipulate existing files. First, unpack the document:
python skills/docx/scripts/office/unpack.py Template.docx unpacked/
The unpack.py script normalizes smart quotes, merges adjacent text runs, and prettifies the XML structure, making it suitable for reliable find-and-replace operations.
Repacking and Validating
After editing the XML files (for example, replacing {{TITLE}} with actual content), repackage the document:
python skills/docx/scripts/office/pack.py unpacked/ NewDocument.docx --original Template.docx
The pack.py script automatically runs validate.py to ensure schema compliance. You can skip validation with --validate false if you are certain the XML is clean.
Validating Document Integrity
The validate.py script in skills/docx/scripts/office/validate.py performs schema validation against Microsoft Office Open XML standards and auto-repairs common issues such as broken relationship IDs.
For documents with tracked changes, use the accept changes helper:
python skills/docx/scripts/accept_changes.py Draft.docx Cleaned.docx
This script uses LibreOffice in headless mode to apply all insertions and deletions, producing a clean final document.
Summary
- The docx skill provides a three-layer architecture: specification (
SKILL.md), generation (docxNPM package), and validation (Python scripts). - New documents are built using JavaScript with strict conventions: explicit DXA units, dual-width table definitions, and proper list formatting via
LevelFormat. - Existing documents are modified using
unpack.pyfor extraction, manual or scripted XML editing, andpack.pyfor repackaging with automatic validation. - Quality assurance is handled by
validate.pyfor schema compliance andaccept_changes.pyfor finalizing tracked changes.
Frequently Asked Questions
What is the docx skill in the anthropics/skills repository?
The docx skill is a self-contained module that enables programmatic generation, editing, and validation of Microsoft Word documents. It combines JavaScript generation via the docx NPM package with Python helper scripts for XML unpacking, schema validation, and repackaging, following strict conventions defined in skills/docx/SKILL.md.
Why must I use DXA units when creating tables with the docx skill?
DXA (twentieths of a point) is the native measurement unit in Office Open XML. The docx skill requires explicit DXA values for table widths and cell widths to ensure documents render identically across Microsoft Word, Google Docs, and LibreOffice. Using relative percentages or default units often causes layout inconsistencies or validation errors when processed by validate.py.
How do I edit an existing Word template using the docx skill helper scripts?
First, run python skills/docx/scripts/office/unpack.py Template.docx unpacked/ to extract the ZIP archive and normalize the XML structure. Edit the extracted XML files (such as replacing placeholder text in document.xml), then repackage with python skills/docx/scripts/office/pack.py unpacked/ NewDocument.docx --original Template.docx. The pack script automatically runs schema validation to ensure the output is compliant.
What is the difference between pack.py and validate.py in the docx skill?
pack.py (located at skills/docx/scripts/office/pack.py) is responsible for re-assembling unpacked XML directories into .docx files and optionally running validation. validate.py (at skills/docx/scripts/office/validate.py) is a dedicated schema validator that checks Office Open XML compliance, auto-repairs broken relationship IDs, and can be run independently or automatically via pack.py.
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 →