Why track changes matters
Track changes records every insertion, deletion, and formatting change — attributed to an author with a timestamp. Legal teams use it for redlining. Compliance teams use it for audit trails. Editorial teams use it for review.
Suggesting mode
Set mode="suggesting" and the editor tracks every edit automatically:
import { DocxEditor } from "@eigenpal/docx-js-editor";
function ContractEditor({ buffer }: { buffer: ArrayBuffer }) {
return (
<DocxEditor
documentBuffer={buffer}
mode="suggesting"
author="Current User"
/>
);
}- Insertions get a green underline
- Deletions get a red strikethrough
- Consecutive edits by the same author are grouped into a single revision
Switch between "editing" (direct edits), "suggesting" (tracked changes), and "viewing" (read-only) at any time.
Accepting and rejecting
The editor exposes acceptChange(from, to) and rejectChange(from, to) commands:
- Accept — insertion stays, deletion is removed
- Reject — insertion is removed, deletion stays
The sidebar shows accept/reject buttons on each tracked change card.
Round-trip fidelity
Documents redlined in Word open in the editor with all revisions intact, and vice versa. All revision metadata (author, date, IDs) is preserved on save.
Try it
Automating track changes with AI agents
Manual redlining doesn't scale. @eigenpal/docx-editor-agents provides DocxReviewer — a headless API for programmatic document review. No DOM, runs anywhere.
npm install @eigenpal/docx-editor-agentsBasic usage
import { DocxReviewer } from "@eigenpal/docx-editor-agents";
const reviewer = await DocxReviewer.fromBuffer(buffer, "AI Reviewer");
// Read as plain text (LLM-friendly format)
const text = reviewer.getContentAsText();
// [0] (h1) Service Agreement
// [1] The liability cap is $50k per incident.
// Comment
reviewer.addComment(1, "This cap seems too low.");
// Replace (creates a tracked change)
reviewer.replace(1, "$50k", "$500k");
// Export
const output = await reviewer.toBuffer();The output is a standard DOCX with tracked changes and comments — opens in Word, Google Docs, or the editor above.
With an LLM
Read the document, send to any model, apply the response as tracked changes:
import { DocxReviewer } from "@eigenpal/docx-editor-agents";
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const reviewer = await DocxReviewer.fromBuffer(buffer, "Claude Reviewer");
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 4096,
messages: [{
role: "user",
content: `Review this contract. Return JSON with "comments" and "replacements":
${reviewer.getContentAsText()}`
}],
});
const actions = JSON.parse(response.content[0].text);
reviewer.applyReview({
comments: actions.comments,
proposals: actions.replacements,
});
const output = await reviewer.toBuffer();applyReview is fault-tolerant — individual failures are collected in result.errors instead of throwing, so one bad paragraph index doesn't break the review.
Why this works for agents
- Headless — no DOM, runs on servers and edge functions
- LLM-native —
getContentAsText()returns[index] textformat, no JSON escaping issues - Robust matching — handles smart quotes, whitespace variations, LLM truncation
- Batch operations — single
applyReview()call for the full review - Word-compatible output — proper revision marks, comments, and metadata
Full DocxReviewer API reference
Next steps
- Document comments for threaded discussions
- DocxReviewer API reference
- React integration tutorial
- Live editor