Creates, fills, and converts Microsoft Word (.docx) documents from Markdown or existing templates using pandoc and python-docx, with optional PDF export via LibreOffice.
Say it in your own words; the assistant finds this recipe by itself. Examples:
Use this skill when the user needs to generate a new Word document from text or Markdown, fill in specific fields within an existing .docx template, or convert a Word document to PDF. It is also appropriate when the user provides a custom .docx template and wants the output to retain specific styles, headers, or footers.
Word documents from the sandbox: write Markdown, convert with pandoc,
style with the customer's own template, fill placeholders, export PDF.
Everything writes to /work/out/.
| Situation | Do |
|---|---|
| New document from content you are writing | A. Markdown → docx (pandoc) |
| Customer gave a template or an example .docx whose look must be kept | A with --reference-doc |
Customer gave a form/letter with {{fields}} to fill |
B. Fill placeholders |
| You must read an existing .docx first | C. Read |
| They want a PDF | finish with D. PDF |
Write the document as Markdown (headings #/##, bullet lists, numbered
lists, tables in pipe syntax, bold/italic, > quotes). Then:
pandoc /work/draft.md -o /work/out/document.docx
# with the customer's styles (headers, footers, fonts, logo come from the template):
pandoc /work/draft.md -o /work/out/document.docx --reference-doc=/work/in/their-template.docx
Rules that keep pandoc output clean:
- Start with a title block only if wanted: a first line % Title renders as the Title style.
- Keep one blank line between paragraphs and before lists and tables.
- Danish letters and quotes are fine; pandoc is UTF-8 throughout.
- A Danish date at the start of a line (21. oktober 2026) is an ordered list to Markdown: write 21\. oktober 2026.
- Page breaks: insert a raw block ```{=openxml} <w:p><w:r><w:br w:type="page"/></w:r></w:p> ```.
- A reference doc must be a .docx; if the customer gave .dotx, convert first:
soffice --headless --convert-to docx --outdir /work /work/in/template.dotx.
For a letter use scripts/letter.py: it writes the Markdown skeleton with
date, recipient block, subject, greeting and sign-off in Danish or English,
then runs pandoc:
python /skills/docx-writer/scripts/letter.py --to "Mette Hansen, Nordisk ApS" \
--subject "Tilbud på rådgivning" --lang da --body /work/body.md \
--sender "Elfar Thorarinsson, Percerno" --out /work/out/brev.docx [--template /work/in/letterhead.docx]
The template contains {{name}}-style fields anywhere: body, tables,
headers, footers. Provide values as JSON and run:
python /skills/docx-writer/scripts/fill_template.py /work/in/contract.docx /work/out/contract-filled.docx \
--values '{"customer": "Nordisk ApS", "date": "21. oktober 2026", "amount": "48.000 kr."}'
Unfilled fields are reported on stderr so you can ask the user for them. Formatting around a field is preserved because the script edits runs, not paragraphs; a field split across runs by Word is joined first.
markitdown /work/in/file.docx > /work/file.md # Markdown, tables kept
pandoc /work/in/file.docx -t markdown -o /work/file.md # alternative
python /skills/docx-writer/scripts/describe.py /work/in/file.docx # styles, headers/footers, {{fields}}
soffice --headless --convert-to pdf --outdir /work/out /work/out/document.docx
Always list /work/out at the end so the links can be handed to the user.
python /skills/docx-writer/scripts/describe.py /work/out/document.docx to confirm headings, tables and fields.--reference-doc.SKILL.mdscripts/describe.pyscripts/fill_template.pyscripts/letter.pyWritten by Percerno, MIT licence.