Docx
Word documents Jarvis can open, read, edit and write via python-docx: contracts, letters, quotations, meeting minutes, reports. Use whenever a .docx is the input or the output — '睇下份合約', '幫我改份報價單', '整封信', '轉做 Word'. For a .doc (old format) convert first; for PDFs use pdf-toolkit / ocr-and-documents.
Skill metadata
| Source | Bundled (installed by default) |
| Path | skills/document/docx |
| Version | 1.0.0 |
| Author | Claway Agent |
| License | MIT |
| Platforms | linux, macos |
| Tags | docx, word, document, contract, 合約, 報價單, 公文 |
Reference: full SKILL.md
The following is the complete skill definition that Claway loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
Word documents
Routing
.doc(pre-2007) — python-docx cannot open it. Convert first, if LibreOffice is installed (command -v soffice):soffice --headless --convert-to docx file.doc. Say that you converted; a converted contract is not byte-identical to what the user holds. Withoutsoffice, say the.doccannot be opened here and ask for a.docx— never download or install LibreOffice at runtime.- A PDF →
pdf-toolkit(manipulate) orocr-and-documents(extract text). - A deck →
powerpoint.
Read it before you talk about it
python3 - <<'PY'
import docx
d = docx.Document("contract.docx")
for i, p in enumerate(d.paragraphs):
if p.text.strip():
print(f"[{i}] ({p.style.name}) {p.text[:110]}")
for ti, t in enumerate(d.tables):
print(f"-- table {ti}: {len(t.rows)}x{len(t.columns)}")
for row in t.rows[:4]:
print(" ", [c.text.strip() for c in row.cells])
PY
Tables are not paragraphs. d.paragraphs skips every word inside a table,
so a quotation whose prices live in a table reads as an empty document if you
only walk paragraphs. Amounts, dates and party names are usually in the tables.
Headers and footers are separate again — section.header.paragraphs — and that
is where letterheads and reference numbers live.
Editing without wrecking the formatting
A paragraph's look lives on its runs, not on the paragraph. Assigning to
p.text destroys every run and takes the bold, the font and the language with
it — the document comes back looking like a different company wrote it.
# WRONG — flattens formatting
p.text = p.text.replace("2025", "2026")
# RIGHT — edit the run that holds the text
for r in p.runs:
if "2025" in r.text:
r.text = r.text.replace("2025", "2026")
Word often splits one visible sentence across several runs, so a phrase you can
see may not exist in any single run.text. When a replacement has to span runs,
put the new text in the first run and blank the rest of the matched span rather
than rebuilding the paragraph.
Writing a document
python3 - <<'PY'
import docx
from docx.shared import Pt, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
d = docx.Document()
# CJK needs the east-asian font set explicitly; setting .name alone leaves
# Chinese glyphs falling back to whatever the reader's machine picks.
style = d.styles["Normal"]
style.font.name = "Calibri"
style.font.size = Pt(11)
style.element.rPr.rFonts.set(
docx.oxml.ns.qn("w:eastAsia"), "Microsoft JhengHei") # 繁體; PingFang on macOS
d.add_heading("報價單", level=1)
p = d.add_paragraph("敬啟者:")
p.paragraph_format.space_after = Pt(12)
t = d.add_table(rows=1, cols=3)
t.style = "Table Grid" # default has NO borders — set one
for c, h in zip(t.rows[0].cells, ["項目", "數量", "金額 (HKD)"]):
c.text = h
c.paragraphs[0].runs[0].bold = True
row = t.add_row().cells
row[0].text = "顧問服務"; row[1].text = "1"; row[2].text = "12,000.00"
row[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT # money right-aligns
d.save("報價單.docx")
PY
Start from the user's own template whenever there is one —
docx.Document("template.docx") keeps their styles, letterhead and margins.
A document that arrives in the company's own format needs no explanation; one
in python-docx defaults announces that a machine made it.
What python-docx cannot do
It does not render, paginate, or recalculate anything. There is no page count and no "what does this look like" without converting:
command -v soffice >/dev/null 2>&1 \
&& soffice --headless --convert-to pdf 報價單.docx \
|| echo "soffice not installed - skipping render check"
Do that before sending anything a person will sign or print — it is the only
way to catch a table that spills off the page. If soffice is not installed,
skip it (never download or install LibreOffice at runtime) and say in one line
that the layout was not render-checked on this machine.
Track-changes and comments are not exposed by the API. If a contract has revision marks, say so rather than reading through them as if they were the final text.
Before you answer
- Quote the clause you are relying on, and say where it is ("clause 7.2", "the table under 付款條款"), so the user can check you.
- When you changed a document, send the file back. Describing an edit and leaving the user to make it is not the job.