agentsclimarketplace

Word docx

Skill kennethkhoocy/legal-scholarship-skills/plugins/legal-scholarship/skills/word-docx

Claude Code and Codex skills for legal scholarship: verified citation placement (Bluebook/OSCOLA/McGill), law-review docx pipelines, document delivery tooling

Install
npx -y skills add kennethkhoocy/legal-scholarship-skills --skill word-docx

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 15 days oldThe repository was created 15 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 24 stars24 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Unified skill for Microsoft Word .docx workflows: extracting comments or tracked changes, summarizing reviewer feedback, generating response-to-comments documents, building Word memos or reports, applying tracked edits, auditing OOXML internals, validating and repairing documents, accepting revisions, adding or resolving comments, converting legacy .doc files, unpacking or repacking .docx files, simplifying redline markup, rendering .docx to images, and building Word documents with tables of contents, multi-column layouts, or page-numbered headers and footers. Use whenever a task involves reading, reviewing, building, editing, or analyzing .docx files. Prefer this skill over ad-hoc python-docx or docx2python usage. Route PDFs, spreadsheets, presentations, Google Docs, and LaTeX-to-Word conversion pipelines to their dedicated skills.

SKILL.md

13.0 KB, as published. Nobody here has run it

word-docx

Unified CLI for Microsoft Word .docx review and generation workflows. Converts .docx content into structured JSON/Markdown before any LLM reasoning, and builds new .docx files from structured specs.

Core Principle

Never modify source .docx files in place. Never ask the LLM to parse raw .docx XML directly. The pipeline always works in two steps:

  1. Extract structured data (JSON/Markdown) from the .docx
  2. Reason over the structured data, then build a new .docx if needed

CLI Entry Point

All commands run through a single entry point:

python scripts/word_docx.py <command> [options]

The scripts directory is at ~/.claude/skills/word-docx/scripts/.

Command Routing

User intentCommandPrimary library
Read comments / reviewer feedbackextract-commentsdocx2python
Read tracked changes / redlinesextract-revisionsdocx-revisions, OOXML fallback
Read ordinary text and tablesextract-textpython-docx
Full inspection (all of the above)inspectall
Build a new Word documentbuildpython-docx or docxtpl
Render to PDFrender-pdfLibreOffice
Apply edits (auto-detect mode)apply-editslxml + zipfile (OOXML)
Apply tracked edits (force)apply-tracked-editslxml + zipfile (OOXML)
Apply silent edits (force)apply-non-tracked-editslxml + zipfile (OOXML)

Backend Matrix

CommandBackendNotes
inspect, extract-comments, extract-revisions, extract-textPython (word-docx)docx2python / docx-revisions / python-docx
apply-edits, apply-tracked-edits, apply-non-tracked-editsPython (word-docx)lxml + zipfile
render-pdf, audit-ooxmlPython (word-docx)LibreOffice / lxml
buildPython or Nodeauto-routes via spec markers — see Build Reference
add-commentHybridunpack → Python edit → comment.py → pack
validate, accept-changes, convert-doc, unpack, pack, simplify-redlines, docx-to-imagesPython (anthropic)subprocess to anthropic-agent-skills plugin

Library Roles

Each library has a specific role. Do not substitute one for another:

  • docx2python: extraction of comments, headers, footers, text, footnotes, endnotes, properties, images
  • docx-revisions: reading tracked changes (insertions, deletions, replacements) with author/date metadata; optional fallback for writing tracked replacements
  • lxml + zipfile (apply_edits): writing paragraph-scoped tracked changes (replace, insert, delete) with author/date metadata via direct OOXML manipulation
  • python-docx: ordinary DOCX construction, paragraph/table reading, style manipulation
  • docxtpl: rendering Word templates from structured data (Jinja2 syntax inside Word)
  • lxml + zipfile: raw OOXML audit and diagnostics

Commands

inspect

Full extraction and audit in one pass.

python scripts/word_docx.py inspect INPUT.docx --out OUTDIR

Produces:

  • manifest.json — file list, timestamps, diagnostics
  • diagnostics.json — OOXML audit results and warnings
  • comments.json / comments.md — reviewer comments
  • revisions.json / revisions.md — tracked changes
  • document.md / paragraphs.json — body text

extract-comments

python scripts/word_docx.py extract-comments INPUT.docx --out OUTDIR

Uses docx2python. Cross-checks against raw OOXML comment count. Stable IDs: C001, C002, ...

extract-revisions

python scripts/word_docx.py extract-revisions INPUT.docx --out OUTDIR

Tries docx-revisions first, falls back to raw OOXML scanning. Stable IDs: R001, R002, ...

extract-text

python scripts/word_docx.py extract-text INPUT.docx --out OUTDIR

Paragraphs and tables via python-docx. Outputs Markdown and JSON.

build

python scripts/word_docx.py build --spec SPEC.json --out OUTPUT.docx
python scripts/word_docx.py build --spec SPEC.json --out OUTPUT.docx --template TEMPLATE.docx

Build spec JSON shape:

{
  "title": "Document Title",
  "subtitle": "Optional subtitle",
  "sections": [
    {"heading": "Section heading", "paragraphs": ["Para 1 with a citation.[^1]"]}
  ],
  "items": [
    {
      "comment_id": "C001",
      "comment": "Reviewer comment",
      "response": "Response text",
      "revision_made": "Revision description"
    }
  ],
  "footnotes": {"1": "See Smith (2020) at 15."}
}

Footnotes use [^N] markers in paragraph text. The footnotes dict maps each N to the footnote content. The build command creates proper OOXML footnotes (word/footnotes.xml + w:footnoteReference elements) via post-processing.

audit-ooxml

python scripts/word_docx.py audit-ooxml INPUT.docx --out OUTDIR

Fast structural lint over the raw OOXML: counts paragraphs, tables, tracked-change elements, comments, footnotes, endnotes. Writes diagnostics.json to --out. Use validate instead for schema-grade checks with auto-repair.

render-pdf

python scripts/word_docx.py render-pdf INPUT.docx --out OUTPUT.pdf

Requires LibreOffice. Reports a clear error if unavailable.

apply-tracked-edits

python scripts/word_docx.py apply-tracked-edits INPUT.docx --edits EDITS.json --out OUTPUT.docx

Applies tracked edits via direct OOXML manipulation (lxml + zipfile), producing w:ins and w:del elements that appear as tracked changes when the output is opened in Microsoft Word.

Supported operations:

  • replace: Wraps old_text in w:del and inserts new_text in w:ins at the matched location. Handles text that spans multiple runs within a paragraph.
  • insert: Appends new_text as a tracked insertion (w:ins) at the end of the target paragraph.
  • delete: Wraps old_text in w:del as a tracked deletion in the target paragraph.

All operations are scoped to the paragraph specified by paragraph_index (zero-based index into the document's w:p elements). Each tracked change carries w:author and w:date attributes; if date is omitted from the edit spec, the current UTC timestamp is used.

Diagnostic behaviour:

  • Warns and skips when paragraph_index is out of range.
  • Warns and skips when old_text is not found in the target paragraph (for replace and delete).
  • Reports applied/skipped counts.

apply-edits (auto-detect)

python scripts/word_docx.py apply-edits INPUT.docx --edits EDITS.json --out OUTPUT.docx

Auto-detects whether the input document contains existing tracked changes (w:ins/w:del elements). If tracked changes are present, applies edits as tracked changes (same as apply-tracked-edits). Otherwise, applies edits silently (same as apply-non-tracked-edits). This is the recommended default command for applying edits.

apply-non-tracked-edits

python scripts/word_docx.py apply-non-tracked-edits INPUT.docx --edits EDITS.json --out OUTPUT.docx

Same operations as apply-tracked-edits (replace, insert, delete) but without tracked-change markup. The output reads as if the text was always written that way. Uses the same JSON format; author and date fields are accepted for compatibility but have no effect on output.

Edits spec & matching semantics (all apply-* commands)

Verified against apply_edits.py internals (2026-07-08); these are the gotchas that cause silent misfires:

  • EDITS.json is a top-level ARRAY of operation objects, not an object wrapping them:
    [
      {"operation": "replace", "paragraph_index": 12,
       "old_text": "and—subject to exceptions—is",
       "new_text": "and (subject to exceptions) is"}
    ]
    
    Wrapping in {"edits": [...]} fails with EditOperation() argument after ** must be a mapping, not str.
  • paragraph_index counts DIRECT children of w:body only (body.findall('w:p')). Paragraphs inside tables/textboxes are excluded, so indices from python-docx, docx2python, or an .//w:p sweep will drift. Derive the index by locating which direct-child paragraph contains old_text, not by counting from another extraction.
  • Replacement flattens formatting to the FIRST matched run's rPr. The whole matched span is re-emitted as one run cloned from the first affected run. Never let old_text span an italicized case name, bold phrase, or other formatting change — anchor the span so it starts and ends in uniformly formatted text (e.g. for Foss—the rule that, match —the rule that …, leaving the italic Foss outside the splice).
  • Matches cannot cross group boundaries. Runs with no w:t (footnote references, fields) and non-run children (hyperlinks, bookmarks, existing w:ins/w:del) split the paragraph into contiguous run groups; old_text must sit inside ONE group. An old_text spanning a footnote marker will report "not found".
  • Pre-validate anchors programmatically before applying a large batch: for each old_text, assert (1) it occurs exactly once in the whole document, (2) within a single run group, (3) the run containing the match start is not italic/styled. This catches every misfire before it silently skips.

Typical LLM Workflow

1. inspect marked_up.docx --out ./review
2. LLM reads review/comments.json and review/revisions.json
3. LLM writes response_spec.json
4. build --spec response_spec.json --out response_to_comments.docx

Output Conventions

  • All outputs go into an explicit output directory — never alongside the source file.
  • JSON files use UTF-8 with ensure_ascii=False.
  • Comment IDs: C001, C002, ... Revision IDs: R001, R002, ...
  • Diagnostics record warnings rather than crashing.
  • Manifest files track what was produced and any issues.

Install Prerequisites

word-docx's Python-native commands work standalone. The Anthropic-backed commands require the document-skills plugin; the JS-routed build path requires Node >= 18 and the docx npm package.

claude plugin marketplace add anthropics/skills
claude plugin install document-skills@anthropic-agent-skills
npm install -g docx   # only needed for js-routed builds

If a command needs a backend that is not installed, it raises a clear error with the exact install command. No silent failures.

add-comment reference

Three sub-modes, one .docx output per invocation.

Reply to existing comment

python scripts/word_docx.py add-comment INPUT.docx --out OUTPUT.docx \
    --reply-to C001 --text "Your reply." --author "Claude"

Anchor a new comment on a span

python scripts/word_docx.py add-comment INPUT.docx --out OUTPUT.docx \
    --anchor-paragraph 3 --anchor-text "the term is 30 days" \
    --text "Should this be 60?" --author "Claude"

Mark a comment as resolved

python scripts/word_docx.py add-comment INPUT.docx --out OUTPUT.docx \
    --resolve C001

build spec reference

build accepts a JSON spec. Routing is auto by default; set runtime explicitly to override.

Python-routed example (no js-only features)

{
  "title": "Quarterly Review",
  "page": {"size": "letter", "margins": {"top": 1, "bottom": 1, "left": 1, "right": 1}},
  "sections": [{"heading": "Overview", "paragraphs": ["Revenue grew 15%."]}],
  "footnotes": {"1": "Source: 10-K"}
}

JS-routed example (toc + page numbers + native footnotes)

{
  "title": "Annual Report",
  "toc": {"title": "Contents", "heading_range": "1-3", "hyperlinks": true},
  "columns": 2,
  "page_sections": [{
    "header": [{"type": "text", "value": "Annual Report 2026"}],
    "footer": [{"type": "text", "value": "Page "}, {"type": "page_number"}]
  }],
  "sections": [
    {"heading": "Executive Summary", "paragraphs": ["..."]},
    {"heading": "Results", "paragraphs": ["..."]}
  ],
  "native_footnotes": {"1": "All figures in USD millions."}
}

Failure-mode reference

ErrorFix
AnthropicSkillNotInstalledErrorRun the two claude plugin commands above.
BuildSpecRequiresJSErrorEither remove the js-only spec field, or set "runtime": "auto" (or omit).
NodeNotInstalledErrorInstall Node >= 18 from nodejs.org.
DocxPackageMissingErrorRun npm install -g docx.

Gives 0 of the 12 instructions most pdf office docs skills give

Counted across 635 of the 690 authors here whose files we hold, read 2026-08-06

  • extract text using pdfplumberin 92 of 635, across 25 files
  • create PDFs using reportlabin 83 of 635, across 16 files
  • read FORMS.md to fill out PDF formsin 80 of 635, across 13 files
  • OCR scanned PDFs using pytesseractin 77 of 635, across 10 files
  • merge or split PDFs using qpdfin 70 of 635, across 3 files
  • use Excel formulas instead of hardcoded calculated valuesin 68 of 635, across 12 files
  • unpack edit xml and repack existing documentsin 63 of 635, across 8 files
  • document sources for hardcoded valuesin 61 of 635, across 9 files
  • write minimal python code without unnecessary commentsin 59 of 635, across 7 files
  • run the recalculation script after adding or modifying formulasin 58 of 635, across 6 files
  • fix all identified formula errors and recalculatein 58 of 635, across 6 files
  • format years as text stringsin 57 of 635, across 5 files

Said here and by no other author read

  • Extract structured data from the docx
  • Reason over structured data before building
  • Run all commands through the single entry point
  • Do not substitute one library for another
  • Validate edit anchors programmatically before batch applying
  • Pre-validate that the old text occurs exactly once

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.