Edit and redline Word documents with AI agents
Word .docx command line built for AI agents: read as annotated Markdown, edit by stable locators, leave comments and tracked-change redlines.
0.28.0Add to Favorites
Why it matters
Enable AI agents to programmatically fill, redline, comment on, and edit .docx files while preserving all formatting, styles, and embedded objects-producing tracked-change documents that humans can review and accept/reject in Microsoft Word.
Outcomes
What it gets done
Fill bracketed placeholders in contract templates and forms with structured data
Suggest redline edits with tracked changes that appear in Word's review pane
Add comments to specific text spans for human reviewers to address
Extract and read document content using stable locators without breaking XML structure
Source
Get it from source
Spark does not host a copy of it.
Open sourceReports
Agent outcome reports
No reports yet
Overview
docx-cli is a .docx command line tool built for AI agents. Agents leave comments, suggest redlines and edit Word documents without breaking the formatting or losing content, and a human accepts or rejects the changes in Word afterward. Custom styles, theme colors and embedded objects survive, and it mutates the XML in place instead of re-emitting a lossy model. Use it when an agent has to work on a Word document: fill in template placeholders, redline with tracked changes, leave comments, restyle or author a document. There is no undo, so copy the file first. Agents should run the command's --help before composing a call.
What it does
The default way for agents to edit Word documents is to unzip the .docx and hand-write OOXML, which needs a strong model, burns tokens and routinely produces a file Word will not open. docx-cli gives the agent plain commands and an annotated-Markdown read view, so it never has to reason about the XML. Agents address text by stable locators with character offsets, such as p3:5-20, while humans see normal Word formatting on the file. Custom styles, theme colors and embedded objects survive. The CLI mutates the XML in place rather than re-emitting from a lossy model. A human then accepts or rejects the redlines in Word.
Commands come in two groups. Read and query commands print to stdout and never write the file: docx read (with --from and --to ranges, --accepted, --baseline or --current views, --comments, and --ast for a JSON AST), find (by text, regex or formatting such as highlight, color, bold, italic or underline, with --batch to run many queries against one read), wc, outline, diff, validate (an ECMA-376 schema check per part), raw get, styles (including styles --catalog for built-in styles such as Title and Heading1-9), render (pages to png or jpg through Word or LibreOffice, with --engine, --dpi and --pages) and list verbs for comments, footnotes, endnotes, headers, footers, images, hyperlinks and tracked changes.
Mutate commands change the file in place and accept --dry-run and -v, plus -o for an output path on every mutator except create, whose positional file is already the output. They cover create, insert, edit, delete, replace, sections, comments (add, reply, resolve, delete), footnotes and endnotes, headers and footers (set, clear), images (add, extract, replace, delete), hyperlinks, tables (create, rows, columns, widths, merge, borders, format), lists set, tasks (add, check, uncheck), track-changes, styles set, styles create and styles set-default-font. Insert takes text, markdown, code, equations, lists and page, column or section breaks; edit can also set run formatting such as bold, color, highlight and font on existing text. On edit, run-formatting flags and --clear are applied directly and are not recorded as a tracked change. In a single call with no content (or one --batch entry), run-formatting flags cannot be combined with paragraph properties such as --style and --alignment; use separate calls or entries, or add --text to set both. insert, edit, delete and replace all accept --track to record one invocation as a tracked change even when the document's track-changes toggle is off.
Reading annotates structure that Markdown cannot show as deviation-only HTML comments: paragraph style, alignment, spacing and indent, section breaks, page geometry, tables and cells, content controls, images, headers and footers, and the tracked-changes state, which always appears on a head line as on or off. For constructs no modeled verb covers, such as drop caps, TOC field codes or embedded objects, the docx raw commands edit OOXML directly. Every raw mutation runs a gate pipeline of well-formedness, addressable roots, ECMA-376 child order, reference and id integrity and a schema check against the bundled transitional XSDs, and nothing is written when any gate fails. Raw changes are never tracked.
When to use - and when NOT to
Use it when an agent has to work on a Word document: hand a .docx to Claude or Codex and get back a redlined copy with comments, then open it in Word and accept or reject as usual. The commands cover reading, finding, replacing, inserting and editing text, tracked changes, comments, styles, tables, images and page setup.
Watch the workflow. There is no undo or history, because the CLI overwrites in place and git is the history. Make a copy first, or snapshot the file and run docx diff report.docx --against report.orig.docx. The --against value can also be a saved docx read output, or - to read the baseline from stdin, as in git show main:report.docx | docx diff report.docx --against -. The diff is a read-only report, not a patch to apply. Positional block ids (pN, tN, sN) shift after structural edits, so re-read between non-trivial mutations. docx replace keeps the run's formatting and tabs by default, matches tab, non-breaking-space and bullet-glyph variants as their plain equivalents unless --exact, and can be confined to one paragraph with --at pN, which helps when the same placeholder repeats across the document. A multi-line pattern with \n works only untracked; it refuses under tracking, and block ids shift afterward.
Inputs and outputs
Input is a .docx file. The CLI is built for non-interactive agents, and the exit code is the success signal: 0 is success, 2 is a usage error or bad locator (USAGE, INVALID_LOCATOR, INVALID_XML), 3 means the addressed thing was not found (for example FILE_NOT_FOUND, BLOCK_NOT_FOUND, MATCH_NOT_FOUND) and 1 is a general failure (for example NOT_A_ZIP, TRACKED_CHANGE_CONFLICT, VALIDATION_FAILED, RENDER_FAILED). Errors print {code, error, hint?} JSON to stdout with a nonzero exit and no ok field; ok appears only in the -v success acknowledgement. Without -v, a mutator that creates a new handle prints the bare locators one per line, other mutators print a one-line confirmation, find prints matched span locators one per line (no match prints nothing and exits 0), and each list verb prints a bare JSON array whose item ids feed straight back into --at. --dry-run prints a preview object and writes nothing.
A fill-and-redline flow: copy the file, read the cover-page table with docx read FILE --from t1 --to t1, replace the highlighted bracketed placeholders, verify none remain with a regex find --regex --all, turn on tracked changes with docx track-changes FILE on, tighten a clause with another replace, and add a comment on a span with docx comments add FILE --at p7:0-30 --text "...". Opening the result in Word shows tracked changes and comments in the review pane, or docx track-changes accept FILE --all bakes them in. To finalize a review, track-changes apply takes accept and reject lists in one call, resolved against the original ids, so nothing renumbers mid-operation and the file is never left half-finalized.
Locators are pN for a paragraph, pN:S-E for a character range (0-based, start-inclusive, end-exclusive, counting the visible text of the selected view, accepted by default), pN-pM for a paragraph range, sN for a section, tN for a table, tN:rRcC for a cell (chainable to tN:rRcC:pK and to nested tables), tbxN and tbxN:pK for a text box, and entity ids cN, imgN, linkN, fnN, enN, tcN, eqN, hdrN and ftrN. Text boxes are counted by find, replace --all and wc; Word discards comments and footnotes inside a box, so those are refused up front. edit --at on a bare cell locator requires exactly one direct paragraph, and merged or grid-shifted bare cells are rejected; a cell-paragraph locator (tN:rRcC:pK) targets a paragraph precisely. --text-file on insert and create takes literal multi-paragraph text: it is not parsed, every character stays verbatim, and each newline starts a new paragraph.
Batch mutation takes JSONL, and every batch surface accepts --batch - to read stdin. A form fill is one sweep: fill the cells with values, then drop the leftover placeholder lines with {"at":"pN","text":""} or {"at":"pN","delete":true}. Page setup (orientation, size, margins) lives under docx sections: with no --at it applies to every section, with --at sN to one, and under tracking it records one sectPrChange per section. Changing margins or size also converts left tab columns to right tabs flush at the new margin, so a resume's dates do not wrap. edit --tabs right does the same for one line or a range.
Integrations
It ships as an Agent Skill, one SKILL.md that works across Claude Code, Codex, Pi and other harnesses reading the open skill format. The skill teaches the locator model and the redline, comment and fill workflows, then defers to each command's --help at runtime. docx info skill prints the canonical SKILL.md for the installed version.
Install the CLI from npm; it requires Bun 1.3 or newer:
bun add -g bun-docx
# or run without installing:
bunx bun-docx read doc.docx
A standalone binary that needs no Bun is published on each release, with prebuilt files for linux/x64, linux/arm64, darwin/x64, darwin/arm64 and windows/x64. Every release publishes the binaries, the installer and a SHA256SUMS manifest covering all of them. To install, download the install.sh release asset from the latest release with curl -fsSLO and run sh install.sh; the installer verifies the binary's SHA-256 before installing and honors PREFIX (default $HOME/.local/bin) and VERSION (default latest). To verify the script before running it, download SHA256SUMS the same way and run shasum -a 256 -c SHA256SUMS --ignore-missing (or sha256sum -c). To skip the script entirely, download the docx binary for your platform plus SHA256SUMS from the latest release, verify it, chmod +x it and put it on PATH. install.sh is a release asset, published from v0.23.0 onward; earlier releases use the npm path. docx upgrade updates a standalone binary in place wherever it already lives (PREFIX does not apply), with --to v0.23.0 to pin a version and --dry-run to preview; on an npm or bun install it tells you to use the package manager.
Skill installs: npx skills add kklimuk/docx-cli for any agent; for Claude Code, /plugin marketplace add kklimuk/docx-cli followed by /plugin install docx-cli@docx-cli; for Codex, codex plugin marketplace add kklimuk/docx-cli; for Pi, pi install git:github.com/kklimuk/docx-cli (global; add -l for a project, team-shared install), then invoke /skill:docx-cli. Any other harness can drop skills/docx-cli/ into its skills directory, and on first activation the skill's bootstrap script installs the docx binary and self-updates a stale one. Agents should run the command's --help before composing a call, plus docx info locators for the locator grammar and docx info schema for the AST types.
Who it's for
docx-cli is built for AI agents, in particular the weakest, cheapest ones.
Source README
docx-cli
Let your AI agent do real work in your Word documents. Fill in contracts and forms, update tables and figures, restyle a résumé, write a report from scratch, or review a draft with tracked changes and comments. When you open the file in Word, it still looks like yours.
- Let your agents cheaply work at a fraction of the cost and time of most skills. Official skills force agents to unpack and self-manage OOXML that composes Word documents, which means that basic operations can be quite expensive on tokens and time. CLIs like OfficeCLi often force them to compose smaller operations with JSON they often struggle to understand in context.
docx-climakes the work familiar by standardizing most operations as creating, updating, deleting, or replacing Markdown. - Use less-capable models. docx-cli is tuned to work even if the model is weak (like Haiku, Luna, or even Qwen 3.5 9B). It decreases context use by using a Markdown that survives multiple rounds of insertions and updates instead of JSON. It also saves on context by avoiding reading images of the documents by including as much visual context as annotations. It self-documents by providing clear help text with examples, but also providing actionable hints when something goes wrong.
- Built from the ground up for review workflows. It's built to handle change tracking, accept/reject changes, and handle interactions from multiple reviewers.
- Works with any harness. Works with Claude Code, Codex, Pi, and anything else that reads the open Agent Skills format.
How it benchmarks
In short: on our six-task benchmark, docx-cli got the same results as Anthropic's docx skill (the skill Claude uses for Word files) in 27% less time, with 22% fewer input tokens and 41% fewer output tokens using Haiku 5.5. Compared to OfficeCLI, it was roughly 2x faster at half of the tokens, while finishing every task that OfficeCLI got wrong.
| Haiku 5.5 | docx-cli 0.27.0 | Anthropic docx skill | OfficeCLI 1.0.156 |
|---|---|---|---|
| Tasks solved (of 6) | 6.0 | 6.0 | 4.7 |
| Every run solved (all 3) | 6/6 | 6/6 | 4/6 |
| Input tokens (cache-weighted) | 902k | 1.15M (+27%) | 1.92M (+113%) |
| Output tokens | 32k | 54k (+70%) | 63k (+97%) |
| Wall-clock, all 6 tasks | 914 s | 1,254 s (+37%) | 1,834 s (+101%) |
| Tool calls | 98 | 124 (+26%) | 165 (+69%) |
- Editing existing documents is where docx-cli saves. On the five editing tasks it used about 30% fewer input tokens and 35% less time than Anthropic's skill.
- On the two contract tasks, all three tools passed every run. There the difference is cost and speed, not correctness.
- OfficeCLI's four misses were the résumé every time (after the margin change, every date line wrapped, some mid-word, e.g. "Cambrid / ge, MA") and one invoice (the old notes line was left in place). That résumé wrap is a trap docx-cli specifically repairs, so read "fewer misses" with that in mind.
- Every output from every tool opened in Word.
What to know about this benchmark. We wrote docx-cli, the six tasks, and the grading rubrics, and these tasks are also the regression suite docx-cli is developed against. It's three runs per tool on one model. The judge knew which tool produced each result; competitor runs carried an instruction to grade the rendered pages and not penalize a different internal approach. Competitors were pinned (Anthropic skill at anthropics/skills@dbd4588, OfficeCLI 1.0.156 by SHA-256). On older models the correctness gap was large (Haiku 4.5, July 2026: 5.0/6 vs 0.7/6 for the default skill); on current models it has closed. Per-task numbers, every caveat, and how to reproduce: benchmarks/2026-10-10.
Agent Setup
Paste this messages into your agent of choice:
Set up docx-cli (https://github.com/kklimuk/docx-cli) so you can edit Word documents for me.
1. Install the skill for the agent you are:
- Claude Code: claude plugin marketplace add kklimuk/docx-cli && claude plugin install docx-cli@docx-cli
- Codex: codex plugin marketplace add kklimuk/docx-cli (the skill loads automatically; nothing else to install)
- Any other agent: npx skills add kklimuk/docx-cli -g -y
2. Install the `docx` program:
- If Bun is installed: bun add -g bun-docx
- Otherwise, from an empty temporary directory:
curl -fsSLO https://github.com/kklimuk/docx-cli/releases/latest/download/install.sh
curl -fsSLO https://github.com/kklimuk/docx-cli/releases/latest/download/SHA256SUMS
shasum -a 256 -c SHA256SUMS --ignore-missing (or: sha256sum -c SHA256SUMS --ignore-missing)
Only if that prints "install.sh: OK", run: REQUIRE_CHECKSUM=1 sh install.sh
- Windows: download docx-windows-x64.exe from https://github.com/kklimuk/docx-cli/releases/latest,
compare `Get-FileHash docx-windows-x64.exe` with its line in SHA256SUMS, rename it to docx.exe,
and put it on PATH.
3. Run `docx --version`. If it isn't found, add ~/.local/bin to PATH and try again.
4. Tell me it's ready. (In Claude Code, the skill is available from the next session.)
Note: the npm package is `bun-docx`. The npm packages named `docx` and `docx-cli` are unrelated.
Or install the skill yourself
Any agent (skills.sh):
npx skills add kklimuk/docx-cli
Claude Code:
/plugin marketplace add kklimuk/docx-cli
/plugin install docx-cli@docx-cli
Codex (the plugin's skills auto-discover):
codex plugin marketplace add kklimuk/docx-cli
Pi (the pi manifest in package.json pulls in the skill), then invoke /skill:docx-cli:
pi install git:github.com/kklimuk/docx-cli # global; add -l for a project (team-shared) install
Manual: copy skills/docx-cli/ into your agent's skills directory (e.g. ~/.claude/skills/ or the cross-tool ~/.agents/skills/). If docx isn't installed, the skill tells the agent to run scripts/bootstrap.sh, which installs a pinned, checksum-verified binary (and, run again later, updates one that's behind).
The skill is thin on purpose: it teaches the workflows, then defers to docx <command> --help, which ships with the program, so it can't go stale. docx info skill prints the canonical SKILL.md for the installed version.
Why docx-cli instead of something else?
On our benchmark docx-cli solved every task and was the cheapest and fastest of the three tools above. Here's how it compares with each alternative.
- Anthropic's docx skill: docx-cli has the same accuracy, with less spend. docx-cli took 27% less time, 22% fewer input tokens, 41% fewer output tokens, and 98 tool calls against 124. On finalizing a redline it used about half: 94k tokens and 86 s against 179k and 159 s. The skill has the agent hand-edit Word's XML with helper scripts; docx-cli gives it commands such as
track-changes apply --accept rev1 --reject rev0. It's one program instead of Python, Node, pandoc, and LibreOffice, and it's MIT-licensed, while the skill's license limits it to Anthropic's services; docx-cli runs under Codex or any other agent. The skill was cheaper on our one from-scratch document, so if you mostly write new documents with Claude, it's a reasonable choice. - OfficeCLI: docx-cli solves more tasks, at half the cost. On our Word tasks docx-cli solved 6 of 6 against 4.7, with about half the tokens and time (most of OfficeCLI's misses were a résumé layout trap docx-cli was built to repair).
- Claude for Word and Copilot: docx-cli needs no Word to make progress. In-Word assistants work on one open document while a person drives. docx-cli lets the agent work on the files directly: a folder of contracts, a scheduled job, an agent like Claude Code or Codex. If you'd rather sit in Word and steer, Claude for Word does tracked changes too.
- python-docx, Open XML SDK, or generate-and-compare: docx-cli doesn't write throwaway code. With a library the agent writes new code for every document, handles text Word splits across runs, and, with python-docx, gets no API for tracked changes. Generating a new copy and running Word's Compare gives a redline shaped by the diff, and the regenerated copy's formatting can drift. docx-cli tracks each change as it's made, scoped to the phrase.
- pandoc: docx-cli can edit instead of regenerating. pandoc is excellent at Markdown to Word (docx-cli's
create --from draft.mddoes that too), but editing an existing file means regenerating it from Markdown, which drops what Markdown can't hold. On our test fixtures (tests/fixtures/text-boxes.docxandsections.docx),pandoc in.docx -o in.md && pandoc in.md --reference-doc=in.docx -o out.docxlost a text box along with its text and merged eight sections, with their columns, into one.
What docx-cli doesn't do: MCP.
Is it safe to use on real documents?
Yes.
- Your document stays on your machine. No command sends content anywhere. The only network access is installing or upgrading the program, plus
images addwhen you give it a web address. See SECURITY.md. - Every edit can be reviewed. Ask the agent to turn tracking on, so each change is a Word tracked change you can reject one by one.
- Edits are surgical. docx-cli changes only what it was asked to change; everything else in the file, including parts of Word's format it doesn't understand, passes through untouched. It never deletes something the document still points to.
- Work on a copy. docx-cli saves changes into the file it's given, so ask the agent to save to a new file (
-o) or keep the original.--dry-runpreviews a change without saving it, anddocx diff FILE --against ORIGINAL.docxlists what changed as text (it isn't a Word compare).
For developers
Install the program yourself
npm. The package is bun-docx, and it runs under Bun ≥ 1.3 even when installed with npm. If you're embedding docx-cli in a Node or Python service, use the standalone binary instead.
bun add -g bun-docx # or: npm install -g bun-docx
bunx bun-docx read doc.docx # run without installing
Every command works directly on the .docx file. Only docx render (page images, for checking layout) needs Word (macOS/Windows) or LibreOffice installed.
Upgrading: docx upgrade replaces a standalone binary in place, using the installer embedded in the binary at build time (never fetched), pinned to a release tag and SHA-256-verified. docx upgrade --to v0.27.0 pins a version; --dry-run reports what would change. It won't touch an npm install (use your package manager) or a renamed binary. On Windows it needs Git Bash (for sh); a running .exe can be renamed but not overwritten, so the verified binary is swapped in and the old one is left as docx.exe.old until the next upgrade.
Use it from your own code
docx-cli is a command-line program with a machine-friendly contract, so any language can call it as a subprocess:
- The exit code is the success signal:
0ok,1general failure,2usage error,3not found. Areplaceorcomments add --anchorthat matches nothing exits3instead of reporting success.replacechanges the first match unless you pass--all; any further matches are reported, not treated as an error. - Errors are JSON on stdout:
{"code":"MATCH_NOT_FOUND","error":"…","hint":"…"}, so capture stdout on failure too (in Python,json.loads(error.stdout)["code"]on aCalledProcessErrorwithcapture_output=True). - Structured output:
docx read FILEprints annotated Markdown with locator comments;--astprints the lossless JSON tree; mostlistverbs print JSON (track-changes listprints a table unless you add--json);--verbosegives a JSON acknowledgement on every change. - Stable addresses: paragraphs, tables, cells, comments, and tracked changes all have locators (
p3,p3:5-20,t0:r1c2,c0,rev1).docx find FILE "phrase"returns the exact span. - Batches:
edit,insert,replace,delete, and thecommentsverbs take--batch FILE.jsonl(-for stdin). Every locator in a batch addresses the document as you read it. - No MCP server. Agents call
docxthrough their shell tool with the bundled skill, which is the setup benchmarked above. - Pre-1.0. Flags can still change between minor versions. Pin a version in production.
import json, os, subprocess
env = {**os.environ, "DOCX_AUTHOR": "Acme Legal"} # the name on every tracked change
subprocess.run(["docx", "track-changes", "on", "contract.docx"], check=True, env=env)
subprocess.run(["docx", "replace", "contract.docx", "Net 90", "Net 30", "--all"], check=True, env=env)
changes = json.loads(subprocess.run(
["docx", "track-changes", "list", "contract.docx", "--json"],
check=True, capture_output=True, text=True).stdout)
Tested on every commit: about 1,900 unit tests, a LibreOffice round-trip of every fixture, and schema checks against the ECMA-376 XSDs (docx validate runs the same check on any file).
For IT administrators
- Data: fully local, no telemetry. Network access happens only when someone installs or upgrades the program, or passes a web address to
images add. - Nothing updates in the background. The binary changes only when someone runs
docx upgrade, the installer, or the skill'sbootstrap.sh(which installsdocxwhen it's missing and updates one that's behind). Pin a fleet withDOCX_CLI_VERSION=v0.27.0in the agent's environment, plusVERSION=/docx upgrade --tofor the install itself. - Air-gapped installs, the network endpoints to allow, Windows and macOS signing, and maintainer risk: see SECURITY.md → Deploying in an organization.
Learn more
docx --helpanddocx <command> --help: the authoritative, versioned contract. Agents should start here.- REFERENCE.md: every command, the output contract, the locator grammar, common workflows, and how it works under the hood.
- SECURITY.md: install integrity, data handling, deployment, and reporting vulnerabilities.
- CONTRIBUTING.md: development setup, architecture, the stack, and CI.
FAQ
Common questions
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.