Skip to main content

docx-editor

Release Build status codecov Commit activity License

Pure Python library for Word document track changes and comments, without requiring Microsoft Word.

Note: The PyPI package is named docx-editor because docx-edit was too similar to an existing package.

Features

  • Hash-Anchored Paragraph References: list_paragraphs() returns stable, hash-based paragraph IDs for safe, unambiguous targeting
  • Paragraph Location: get_paragraph_location(ref) reports whether a paragraph lives in the body or inside a table cell — with w:gridSpan-aware logical column, row, table index, and nesting depth. list_paragraph_locations() returns (ref, location) for every paragraph in one batch pass, avoiding a per-paragraph table rescan
  • Batch Editing: Atomic batch_edit() with upfront hash validation across all operations
  • Paragraph Rewrite: rewrite_paragraph() with automatic word-level diffing — specify desired text, get fine-grained tracked changes
  • Track Changes: Replace, delete, and insert text with revision tracking
  • Cross-Boundary Editing: Find and replace text spanning multiple XML elements and revision boundaries
  • Mixed-State Editing: Atomic decomposition for text spanning <w:ins>/<w:del> boundaries
  • Comments: Add, reply, resolve, and delete comments
  • Revision Management: List, accept, and reject tracked changes
  • Session Mode: Optional persistent kernel (docx-session start/exec/stop) keeps documents open across many small commands — ideal for AI agents (pip install docx-editor[session])
  • Cross-Platform: Works on Linux, macOS, and Windows
  • No Dependencies: Only requires defusedxml for secure XML parsing

Installation

pip install docx-editor

Claude Code Plugin

This repo includes a plugin for Claude Code that enables AI-assisted Word document editing.

This plugin extends the original Anthropic docx skill which requires Claude to manually manipulate OOXML. Instead, this plugin provides an interface (docx-editor) that handles all the complexity—Claude just calls simple Python methods like doc.replace() or doc.add_comment(), making document editing significantly faster and less error-prone.

Install as plugin

# Add the marketplace
/plugin marketplace add pablospe/docx-editor

# Install the plugin
/plugin install docx-editor@docx-editor-marketplace

# Install dependencies
pip install docx-editor python-docx

Manual install (alternative)

# Install dependencies
pip install docx-editor python-docx

# Copy skill to Claude Code skills directory
git clone https://github.com/pablospe/docx-editor /tmp/docx-editor
mkdir -p ~/.claude/skills
cp -r /tmp/docx-editor/skills/docx ~/.claude/skills/
rm -rf /tmp/docx-editor

Once installed, Claude Code can help you edit Word documents with track changes, comments, and revisions.

Quick Start

from docx_editor import Document
import os

author = os.environ.get("USER") or "Reviewer"
with Document.open("contract.docx", author=author) as doc:
    # Step 1: List paragraphs with hash-anchored references
    for p in doc.list_paragraphs():
        print(p)
    # Output: P1#a7b2| Introduction to the contract...
    #         P2#f3c1| The committee shall review...

    # Step 2: Edit — each method returns the new paragraph ref
    r = doc.replace("30 days", "60 days", paragraph="P2#f3c1")
    doc.replace("net", "gross", paragraph=r)  # chain without list_paragraphs()
    doc.delete("obsolete text", paragraph="P5#d4e5")
    doc.insert_after("Section 5", " (as amended)", paragraph="P3#b2c4")

    # Rewrite entire paragraph (automatic word-level diff)
    doc.rewrite_paragraph("P2#f3c1",
        "The board shall approve the updated proposal.")

    # Comments
    doc.add_comment("Section 5", "Please review")

    # Revision management
    revisions = doc.list_revisions()
    doc.accept_revision(revision_id=1)

    doc.save()

Cross-Boundary Text Operations

Text in Word documents with tracked changes can span revision boundaries. docx-editor handles this transparently:

from docx_editor import Document
import os

author = os.environ.get("USER") or "Reviewer"
with Document.open("reviewed.docx", author="Editor") as doc:
    # Get visible text (inserted text included, deleted excluded)
    text = doc.get_visible_text()

    # List paragraphs to find hash-anchored references
    refs = doc.list_paragraphs()

    # Page through large documents — you choose the page size; refs stay
    # globally indexed (page 2 with size 50 starts at P51, not P1)
    total = doc.paragraph_count()
    page_size = 50
    for start in range(1, total + 1, page_size):
        for ref in doc.list_paragraphs(start=start, limit=page_size):
            print(ref)  # process this page of refs

    # Find text across element boundaries
    match = doc.find_text("Aim: To")
    if match and match.spans_revision:
        print("Text spans a revision boundary")

    # Replace works even across revision boundaries
    doc.replace("Aim: To", "Goal: To", paragraph="P1#a7b2")

    doc.save()

Batch Editing

Apply multiple edits atomically with upfront hash validation:

from docx_editor import Document, EditOperation

with Document.open("contract.docx", author="Editor") as doc:
    refs = doc.list_paragraphs()
    doc.batch_edit([
        EditOperation.replace("old", "new", paragraph="P2#f3c1"),
        EditOperation.delete("remove this", paragraph="P5#d4e5"),
    ])
    doc.save()

Saving into synced folders

docx-editor is safe to use inside cloud-synced folders (OneDrive, Dropbox, Google Drive, iCloud) and while Word is running.

  • Atomic save. save() writes the new document to a temporary file in the destination's own directory and promotes it with a single atomic rename, flushed to disk. The destination is never observed half-written, so a sync client can never upload a torn file. If the write (or validate=True) fails, the original is left exactly as it was — a failed validation can no longer destroy your document. The saved file keeps the original's permissions, and a symlinked destination is followed to the file it points at.

    Because the temp file is created next to the destination, saving needs write permission on the containing directory, not just on the document itself. If the directory is read-only, save() raises PermissionError.

    A write-protected document is refused, not silently replaced: save() raises PermissionError if the destination is read-only, even though the rename itself would have been permitted by the directory.

    An atomic rename replaces the file's inode, so state bound to the old inode does not survive it: the saved document keeps its permissions, but its ownership, POSIX ACLs, extended attributes, and any hardlinks to it do not carry over. This is inherent to atomic saving (every editor that writes this way behaves the same). If a document depends on an ACL or a hardlink, save to a new path.

  • Open-in-Word guard. Before writing, save() checks for the ~$ owner (lock) file Word places next to any open document. If the destination looks open, it raises DocumentOpenError rather than racing Word's writes:

    from docx_editor import Document, DocumentOpenError
    
    try:
        doc.save()
    except DocumentOpenError:
        # Someone has this document open in Word — close it and retry.
        ...
    

    If you are certain the ~$ file is a stale lock left by a crashed session, pass force=True to save anyway: doc.save(force=True).

  • Limitation — remote co-authoring is undetectable. The guard only sees a local ~$ file. A document being edited remotely (OneDrive/SharePoint co-authoring, or Word for the web) leaves no local lock file, so it cannot be detected from the filesystem. In that case, rely on the cloud provider's version history to recover if edits collide.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

docx_editor-0.6.0.tar.gz (653.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

docx_editor-0.6.0-py3-none-any.whl (107.4 kB view details)

Uploaded Python 3

File details

Details for the file docx_editor-0.6.0.tar.gz.

File metadata

  • Download URL: docx_editor-0.6.0.tar.gz
  • Upload date:
  • Size: 653.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for docx_editor-0.6.0.tar.gz
Algorithm Hash digest
SHA256 07c2abde9dd88e70753009eefa058ce47b562ba4c5ec02cb3295301e4ad714f8
MD5 bfa1ef8162aa6aa02062fa34b19f812a
BLAKE2b-256 c76928721fbc11f9d6f7fde9f3099fde5b7d35661e370ca527e17e8767d6f03c

See more details on using hashes here.

File details

Details for the file docx_editor-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: docx_editor-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 107.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for docx_editor-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ca6f6a6d5aadbf6364f9b0861a2c68999a0a6bf85c9d5f75b1990e4237e3125
MD5 dd043bdc5681f9343df30ac1390f252b
BLAKE2b-256 b7a40d947818ba85fc3cc0365ea8d80ad2e529acbd7e38e66bc16e7eb574c019

See more details on using hashes here.

Release history Release notifications | RSS feed

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.1

2 files

This release

0.6.0 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page