🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Docx Editing

by @stevenobiajulu

Surgically edit existing (brownfield) .docx files with formatting preservation and tracked changes via the Safe-DOCX MCP server. Use when user says "edit thi...

Versionv0.3.0
Downloads1,593
Stars⭐ 2
TERMINAL
clawhub install docx-editing

πŸ“– About This Skill


name: docx-editing description: >- Surgically edit existing (brownfield) .docx files with formatting preservation and tracked changes via the Safe-DOCX MCP server. Use when user says "edit this docx," "change the contract," "redline the document," "compare these Word files," "add a comment to the docx," "read this Word file," or "mark up the agreement." Not for from-scratch document generation. license: MIT compatibility: >- Works with any MCP-compatible agent. Requires Node.js >=18.0.0 and npm (for npx) on the host machine. The MCP server runs locally as a stdio child process. Install-time: npm registry fetch (one-time, cacheable). Runtime: zero network calls, file access limited to ~/ and system temp. requires: binaries: - node (>=18.0.0) - npx (bundled with npm) network: install_time: npm registry (registry.npmjs.org) β€” one-time fetch runtime: none filesystem: - ~/ (home directory) - system temp directories metadata: author: safe-docx version: "0.3.0"

Editing .docx Files with Safe-DOCX

Safe-DOCX is a local MCP server for surgically editing existing .docx files. It preserves formatting, generates tracked-changes redlines, and β€” once installed β€” runs entirely on the local filesystem with zero network activity.

Source Code and Audit

Safe-DOCX is fully open source (MIT license). Review the complete source before installing:

  • GitHub: https://github.com/UseJunior/safe-docx
  • npm registry: https://www.npmjs.com/package/@usejunior/safe-docx
  • Code coverage: Published via Codecov on every release
  • Conformance harness: Automated spec coverage tests run in CI on every commit
  • No postinstall scripts β€” verify: npm view @usejunior/safe-docx scripts shows no postinstall or install hooks
  • All security claims below are verifiable by reading the source.

    Runtime Requirements

    Safe-DOCX requires these binaries to be available on the host:

    | Binary | Minimum version | Why | |--------|-----------------|-----| | node | 18.0.0 | Authoritative version from packages/safe-docx/package.json engines field | | npx | Bundled with npm | Used by the recommended MCP connector to launch the server |

    If you prefer not to use npx, see Offline / Pinned Installation below for alternatives.

    Safety Model

    Safe-DOCX's safety model has two distinct phases: install time (when the package is fetched) and runtime (when the MCP server is running).

    Install-Time Behavior (network required, one-time)

  • npm registry fetch β€” the recommended connector command npx -y @usejunior/safe-docx downloads the package from registry.npmjs.org on first run. Subsequent runs use the cached copy unless the cache is cleared.
  • No postinstall scripts β€” the package declares no postinstall, preinstall, or install hooks. Verify with npm view @usejunior/safe-docx scripts.
  • Provenance β€” releases are published with npm provenance (--provenance), so you can verify the package was built from the public GitHub repo via GitHub Actions.
  • If you need guaranteed offline install β€” pin a specific version and vendor it locally. See the next section.
  • Runtime Behavior (zero network)

  • Local-only stdio runtime β€” the MCP server runs as a child process, never binds a port. Verify: the entry point (src/server.ts) uses StdioServerTransport with no HTTP listener. (source)
  • No outbound network calls β€” at runtime, the package makes zero outbound HTTP requests. Verify: grep -r "fetch\|http\.\|https\.\|net\." packages/safe-docx/src/ returns no matches in application code (test fixtures excluded).
  • Path policy β€” only files under ~/ (home directory) and system temp directories are accessible. Symlinks must resolve to allowed roots.
  • Archive guardrails β€” zip bomb detection and hostile payload rejection protect against malformed .docx inputs.
  • Offline / Pinned Installation

    For high-security environments where npx auto-fetch is unacceptable, install the package manually and pin the version:

    # Option 1: Pin a specific version globally
    npm install -g @usejunior/safe-docx@0.9.0

    Then configure your MCP client to invoke it by path:

    command: "safe-docx"

    args: []

    Option 2: Vendor the package into your project

    npm pack @usejunior/safe-docx@0.9.0

    Inspect the tarball, then install it from disk:

    npm install -g ./usejunior-safe-docx-0.9.0.tgz

    Option 3: Build from source (most auditable)

    git clone https://github.com/UseJunior/safe-docx.git cd safe-docx git checkout npm ci npm run build npm link packages/safe-docx

    After any of these, your MCP client config becomes:

    {
      "mcpServers": {
        "safe-docx": {
          "command": "safe-docx",
          "args": []
        }
      }
    }
    

    Using command: "safe-docx" (the installed binary) instead of command: "npx" eliminates the install-time network fetch on every invocation.

    Always pin the version

    Even with npx, you can pin the version to prevent unexpected updates:

    {
      "mcpServers": {
        "safe-docx": {
          "command": "npx",
          "args": ["-y", "@usejunior/safe-docx@0.9.0"]
        }
      }
    }
    

    Before upgrading, review the changelog: https://github.com/UseJunior/safe-docx/blob/main/CHANGELOG.md

    When to Use This Skill

    Use Safe-DOCX when you need to:

  • Change clauses or paragraphs in an existing .docx
  • Insert or delete content with formatting preservation
  • Add comments or footnotes for reviewers
  • Produce a tracked-changes redline from edits
  • Compare two .docx files into a redline
  • Extract revisions to structured JSON
  • Apply layout formatting (spacing, row heights, cell padding)
  • Not for From-Scratch Generation

    Safe-DOCX edits already-existing .docx files β€” it does not create documents from blank. For new document generation, use a template-filling workflow (e.g. OpenAgreements). Safe-DOCX can refine generated docs downstream.

    Quick Start

    1. read_file(file_path="~/doc.docx")        β†’ see paragraphs + _bk_* IDs
    2. grep(file_path="~/doc.docx", patterns=["target phrase"])  β†’ find paragraph IDs
    3. replace_text(session_id, target_paragraph_id, old_string, new_string, instruction)
    4. save(session_id, save_to_local_path="~/doc-edited.docx")
    

    Core Workflow: Read, Locate, Edit, Save

    Step 1 β€” Read. Call read_file with format: "toon" (token-efficient table) to see paragraphs and their stable _bk_* IDs.

    Step 2 β€” Locate. Use grep with regex patterns to find target paragraphs. It returns paragraph IDs with surrounding context.

    Step 3 β€” Edit. Use replace_text to swap text within a paragraph, or insert_paragraph to add new paragraphs before/after an anchor.

    Step 4 β€” Save. Call save to write output. Default is save_format: "both" which produces a clean copy and a tracked-changes redline.

    Gotchas That Will Bite You

    Unique match required

    replace_text needs old_string to match exactly one location in the target paragraph. If the text appears multiple times, you get MULTIPLE_MATCHES. Fix: include more surrounding context in old_string.

    BAD:  old_string: "the Company"          β†’ 5 matches, fails
    GOOD: old_string: "the Company shall indemnify"  β†’ 1 match, succeeds
    

    Footnote markers are display-only

    read_file shows footnotes as [^1], [^2], etc., but these markers are not part of the editable text. You cannot search for or replace [^1] via replace_text. To modify footnotes, use the dedicated add_footnote, update_footnote, and delete_footnote tools.

    Hyperlinks are read-only

    read_file shows links as text, but you cannot create new hyperlinks via replace_text or insert_paragraph. The tag is stripped from new text. Existing hyperlinks are preserved when surrounding text is edited.

    Paragraph IDs are session-scoped

    The _bk_* bookmark IDs are generated when a document is opened and are tied to that session. Do not store or reuse IDs across sessions. Always re-read the document to get fresh IDs.

    Smart text matching

    replace_text is tolerant of:

  • Quote variants: straight ", curly \u201c\u201d, angle \u00ab\u00bb all match each other
  • Whitespace differences: multiple spaces, tabs, and line breaks are normalized
  • This means you can copy text from read_file output and use it in old_string even if the underlying XML uses different quote characters.

    Formatting Tags

    When writing new_string in replace_text or insert_paragraph, use inline tags to apply formatting:

    | Tag | Effect | |-----|--------| | text | Bold | | text | Italic | | text | Underline | | text | Yellow highlight |

    Tags can be nested: bold italic. Formatting from the original matched text is preserved for untagged replacement text.

    Batch Edits with apply_plan

    For 3+ edits on one document, prefer apply_plan over sequential replace_text calls. It validates all steps before applying any, so you get all-or-nothing transactional semantics.

    1. read_file / grep  β†’ gather paragraph IDs and text
    2. apply_plan(file_path, steps=[
         { step_id: "1", operation: "replace_text", target_paragraph_id, old_string, new_string, instruction },
         { step_id: "2", operation: "insert_paragraph", positional_anchor_node_id, new_string, instruction },
         ...
       ])
    3. save(session_id, save_to_local_path)
    

    Insert Paragraphs

    insert_paragraph adds new content before or after an anchor paragraph.

  • position: "BEFORE" or "AFTER" (default "AFTER")
  • style_source_id: optional _bk_* ID of a paragraph whose formatting you want to clone
  • Multi-paragraph: separate with \n\n in new_string (each becomes its own paragraph)
  • Comments and Footnotes

    Comments: add_comment anchors to a paragraph (optionally to a text span via anchor_text). Use get_comments to list, delete_comment to remove. Supports threaded replies via parent_comment_id.

    Footnotes: add_footnote inserts a footnote marker in a paragraph (optionally after specific text via after_text). Use get_footnotes, update_footnote, delete_footnote to manage.

    Comparing Documents

    Two modes:

  • Two files: compare_documents(original_file_path, revised_file_path, save_to_local_path) β€” produces a redline
  • Session edits: compare_documents(session_id) β€” compares current session state against the original
  • Use extract_revisions on any document with tracked changes to get structured JSON diffs.

    Accepting Tracked Changes

    Call accept_changes(session_id) to flatten all tracked changes into a clean document. This removes all revision markup.

    Session Behavior

  • Sessions auto-create when you first use file_path with any tool
  • Sessions expire after 1 hour of inactivity (each tool call resets the timer)
  • Call clear_session to clean up when done
  • Documents are normalized on open: format-identical runs are merged and proof-error markers removed, which improves text matching reliability
  • Layout Formatting

    format_layout applies paragraph spacing, table row height, and cell padding without touching text content. Units are in twips (1/20 of a point) or DXA (1/635 of an inch).

    Path Restrictions

    By default, only files under ~/ (home directory) and system temp directories are accessible. Symlinks must resolve to allowed roots.

    Related Skills

  • Open Agreements (open-agreements) β€” fill standard legal templates (NDAs, SAFEs, cloud service agreements) and produce signable DOCX files: clawhub install open-agreements/open-agreements
  • Outlook Email Management (outlook-email-management) β€” manage Outlook email with AI agents: clawhub install stevenobiajulu/outlook-email-management
  • Connectors

    For MCP server setup instructions (Claude Desktop, Cursor, Claude Code), see CONNECTORS.md.

    Feedback

    If this skill helped, star us on GitHub: https://github.com/UseJunior/safe-docx On ClawHub: clawhub star usejunior/docx-editing

    πŸ’‘ Examples

    1. read_file(file_path="~/doc.docx")        β†’ see paragraphs + _bk_* IDs
    2. grep(file_path="~/doc.docx", patterns=["target phrase"])  β†’ find paragraph IDs
    3. replace_text(session_id, target_paragraph_id, old_string, new_string, instruction)
    4. save(session_id, save_to_local_path="~/doc-edited.docx")