From word-agent
Content editing module for academic paper Word documents. Handles text replacement, paragraph rewriting, section block replacement, insertion, deletion, and tracked changes mode. Auto-selects the most efficient tool path for each operation. Triggers: 修改内容, 改写, 替换, 把XX改成YY, change, rewrite, modify, replace, 添加段落, 删除段落, tracked changes, 修订模式.
How this skill is triggered — by the user, by Claude, or both
Slash command
/word-agent:word-editThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Word Content Editor modifies text content in Word documents while preserving formatting. It auto-selects the most efficient editing tool for each operation. For tracked changes, it falls back to XML manipulation via the docx skill.
Word Content Editor modifies text content in Word documents while preserving formatting. It auto-selects the most efficient editing tool for each operation. For tracked changes, it falls back to XML manipulation via the docx skill.
unpack.py, pack.py)find_text_in_document to find the target执行任何非修订模式编辑前,先检查文档是否已含修订(来源:word-read Document Map 的
"Tracked Changes" 节 / .word-agent/{name}.map.md sidecar / mcp__docx-mcp__get_tracked_changes):
IF 文档已含 N 处修订 (N > 0) AND 用户请求的不是修订模式:
→ 必须先警告用户并等待确认:
"文档已含 {N} 处修订,直接修改会混入修订流(后续无法区分原有修订与本次改动),
是否改用修订模式?(A) 改用修订模式 (B) 仍然直接修改 (C) 取消"
→ 仅在用户明确选择 B 后才执行非修订编辑
IF user says "从零写" or "新建文档" or "create document" or "write from scratch"
→ New Document Mode (create_document + add_heading + add_paragraph)
ELIF user says "修订模式" or "tracked changes" or "保留修改痕迹"
→ Native Tracked Changes Mode (word-mcp-live, preferred)
→ IF word-mcp-live unavailable → Legacy Tracked Changes Mode (XML fallback)
ELIF change is word/phrase replacement ("把X改成Y")
→ Precise Replace Mode (search_and_replace)
ELIF change is rewriting a paragraph under a specific heading
→ Block Replace Mode (replace_paragraph_block_below_header)
ELIF change is replacing content between two known anchors
→ Anchor Replace Mode (replace_block_between_manual_anchors)
ELIF change is inserting new content
→ Insert Mode (insert_line_or_paragraph_near_text)
ELIF change is deleting a paragraph
→ Delete Mode (delete_paragraph)
ELIF change is adding a heading
→ Header Insert Mode (insert_header_near_text)
ELIF user says "插入公式" or "insert equation" or "add formula"
→ Equation Insert Mode (word-mcp-live insert_equation)
ELIF user says "插入引用" or "cross-reference" or "引用图/表/式"
→ Cross-Reference Insert Mode (word-mcp-live insert_cross_reference)
1. Call search_and_replace(file_path, old_text, new_text)
2. If fails → try python-docx-replace via Bash:
python3 -c "
from docx import Document
from docx_replace import docx_replace
doc = Document('{file_path}')
docx_replace(doc, '{old_text}', '{new_text}')
doc.save('{file_path}')
"
3. If still fails → fall back to XML edit
1. Identify target heading from Document Map
2. Call replace_paragraph_block_below_header(file_path, header_text, new_content)
1. Identify anchor text (existing text near insertion point)
2. Call insert_line_or_paragraph_near_text(file_path, anchor_text, new_text, position="after")
1. Identify paragraph index from Document Map
2. Call delete_paragraph(file_path, paragraph_index)
Uses word-mcp-live with track_changes: true for native revision marks. No XML manipulation needed.
1. For replacement:
mcp__word-mcp-live__replace_text(file_path, old_text, new_text, track_changes=true)
2. For insertion:
mcp__word-mcp-live__insert_text(file_path, anchor_text, new_text, position="after", track_changes=true)
3. For deletion:
mcp__word-mcp-live__delete_text(file_path, target_text, track_changes=true)
4. For paragraph rewrite:
mcp__word-mcp-live__edit_text(file_path, old_text, new_text, track_changes=true)
Advantages over XML mode:
MCP_AUTHOR environment variable (default: "Claude")When to fall back to Legacy mode:
See ../../references/tracked_changes.md for full parameter reference.
For edits that must show revision marks when word-mcp-live is unavailable:
1. Unpack document:
python3 scripts/office/unpack.py document.docx unpacked/
2. Read target location in unpacked/word/document.xml
3. Apply tracked change XML:
- For replacement: wrap old text in <w:del>, add new text in <w:ins>
- For insertion: add <w:ins> block
- For deletion: wrap text in <w:del>, change <w:t> to <w:delText>
- Author: "Claude", Date: current ISO timestamp
4. Repack:
python3 scripts/office/pack.py unpacked/ output.docx --original document.docx
Tracked Changes XML patterns:
Replacement ("30 days" → "60 days"):
<w:del w:id="1" w:author="Claude" w:date="2026-04-26T00:00:00Z">
<w:r><w:rPr>{copy original rPr}</w:rPr><w:delText>30</w:delText></w:r>
</w:del>
<w:ins w:id="2" w:author="Claude" w:date="2026-04-26T00:00:00Z">
<w:r><w:rPr>{copy original rPr}</w:rPr><w:t>60</w:t></w:r>
</w:ins>
Critical rules for tracked changes:
<w:r> elements, never inject tags inside a run<w:rPr> formatting block into tracked change runs<w:delText> inside <w:del>, never <w:t>w:id must be unique across the documentRequires word-mcp-live. Accepts LaTeX input, converts to OMML (Word-native equation format).
1. Collect from user:
- LaTeX expression (e.g., "E = mc^2")
- Display mode (display=centered on own line, inline=within text)
- Equation number (e.g., "(1)" — optional, for display equations)
- Position (after which text to insert)
2. Insert equation:
mcp__word-mcp-live__insert_equation(
file_path, latex="{expression}",
display=true/false, equation_number="(1)",
position="after", anchor_text="{anchor}"
)
3. If word-mcp-live unavailable:
→ Warn: "公式插入需要 word-mcp-live。请安装后重试。"
→ Manual OMML XML insertion is possible but not recommended.
See ../../references/equation_crossref.md for LaTeX patterns and OMML details.
Creates live cross-references that update when the document changes.
1. Collect from user:
- Reference type: heading / figure / table / equation / bookmark
- Target: which heading/figure/table to reference
- Display format: label_number ("图1") / number_only ("1") / page / text
2. Insert cross-reference:
mcp__word-mcp-live__insert_cross_reference(
file_path, ref_type="{type}", ref_target="{target}",
ref_format="label_number",
position="after", anchor_text="{anchor}"
)
3. If word-mcp-live unavailable:
→ Fall back to plain text reference (e.g., manually type "图1")
→ Warn: "已插入纯文本引用。建议安装 word-mcp-live 以使用自动更新的交叉引用。"
See ../../references/equation_crossref.md for reference types and format options.
After executing edits:
Before returning the document to the user, ALWAYS run:
python3 scripts/normalize_fonts.py "{file_path}" --unify
This fixes theme font references, bare runs, and missing eastAsia attributes introduced by MCP operations. This step is non-optional — see ../../references/font_normalization.md.
Rule 1: 样式先行,禁止直接格式化
format_text 设字体字号style_nameRule 2: 使用 Word 内置标题样式(Heading 1/2/3)
Heading 1, Heading 2, Heading 3 样式Rule 3: 中英文字体必须配对设置
eastAsia(中文字体)和 ascii/hAnsi(英文字体)Rule 4: 一段一次写入
add_paragraph 写完,NEVER 分多次追加文本到同一段落<w:r> run,每个 run 可能携带不同的 <w:rPr> 格式Rule 5: TOC 必须用 field code 插入
Two paths depending on whether user provides a template or a format spec:
Path A: Template-based (preferred, 最可靠)
1. User provides template.docx
→ copy_document(template_path, output_path)
→ All styles, page setup, headers/footers, TOC field are inherited
2. word-reader analyzes template:
→ Identify existing heading styles and their formatting
→ Identify placeholder text / sections to replace
3. Write content section by section:
→ For each section heading already in template:
replace_paragraph_block_below_header(output_path, heading, content)
→ For missing sections:
insert_line_or_paragraph_near_text(output_path, anchor, content, "after")
→ Each paragraph written in ONE call with style_name matching template styles
4. Route to word-table-figure for tables/figures
5. Route to word-reference for reference list
6. Run word-checker as final gate
Path B: Format spec-based (from blank)
1. create_document(output_path)
2. Parse format spec into style rules (ask user confirm):
- Page: A4, margins
- Heading 1: 黑体/Arial, 16pt, bold, center
- Heading 2: 黑体/Arial, 14pt, bold, left
- Heading 3: 黑体/Arial, 13pt, left
- Body: 宋体/Times New Roman, 12pt, first-line indent 2字符, 1.5倍行距
- Caption (表/图): 宋体/Times New Roman, 10.5pt, center
3. Modify built-in heading styles via python-docx (NOT create_custom_style):
python3 << 'PYEOF'
from docx import Document
from docx.shared import Pt, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
doc = Document(output_path)
# Modify built-in Heading 1
h1 = doc.styles['Heading 1']
h1.font.name = 'Arial' # English font
h1.font.size = Pt(16)
h1.font.bold = True
h1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Set Chinese font via XML
from docx.oxml.ns import qn
h1.font.element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
# Modify built-in Heading 2
h2 = doc.styles['Heading 2']
h2.font.name = 'Arial'
h2.font.size = Pt(14)
h2.font.bold = True
h2.font.element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
# Modify built-in Heading 3
h3 = doc.styles['Heading 3']
h3.font.name = 'Arial'
h3.font.size = Pt(13)
h3.font.element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
# Modify Normal (body text base)
body = doc.styles['Normal']
body.font.name = 'Times New Roman'
body.font.size = Pt(12)
body.font.element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
body.paragraph_format.first_line_indent = Cm(0.74) # 2字符
body.paragraph_format.line_spacing = 1.5
# Page setup
for section in doc.sections:
section.page_width = Cm(21.0)
section.page_height = Cm(29.7)
section.top_margin = Cm(2.54)
section.bottom_margin = Cm(2.54)
section.left_margin = Cm(3.17)
section.right_margin = Cm(3.17)
doc.save(output_path)
PYEOF
4. Build document structure top-down:
→ add_heading(output_path, "摘 要", level=1)
→ add_paragraph(output_path, abstract_text) # inherits Normal style
→ add_heading(output_path, "第1章 绪论", level=1)
→ add_heading(output_path, "1.1 研究背景", level=2)
→ add_paragraph(output_path, section_text)
→ ... continue for all sections
→ Each add_paragraph inherits Normal style automatically (fonts correct)
→ Each add_heading inherits modified Heading N style (fonts correct)
5. Insert TOC field via word-format module (XML field code, NOT plain text)
6. Route to word-table-figure for tables/figures
7. Route to word-reference for reference list
8. Run word-checker as final gate
User Confirmation Points:
Common Anti-Patterns (NEVER DO):
format_text(p_idx, font="宋体") — 只设中文字体,英文变 Calibricreate_custom_style("MyHeading1", ...) — 自定义标题样式,TOC 找不到add_paragraph(text); format_text(p_idx, ...) — 先写后格式化,应该用样式When user requests multiple changes:
When the orchestrator detects that Word has the target document open (via get_active_document), all edits go through word-mcp-live's live automation. Each operation appears instantly in the Word UI.
| Aspect | File Mode | Live Mode |
|---|---|---|
| Write tool | word-document-server | word-mcp-live |
| Changes visible | After reopening file | Immediately in Word |
| Font normalization | Runs immediately | Deferred (file locked) |
| Undo support | No (use document copy) | Yes (undo_last_operation) |
| Tracked changes | Native or Legacy XML | Native only (track_changes=true) |
normalize_fonts.py --check-lock to detect. Warn user to close Word before normalizing, or defer to next sessionSee ../../references/live_editing.md for platform detection and full reference.
For large-scale edits (10+ changes simultaneously), use adeu to convert the document to Markdown, apply CriticMarkup edits, and write back. This is significantly more token-efficient than making 10+ individual MCP calls.
IF number of planned changes >= 10
OR user says "批量修改" / "bulk edit"
OR word-reviewer Phase 3 has >= 10 revision items
THEN → suggest Bulk Edit via Markdown Mode
Step 1: Extract document to Markdown
python3 -c "
from adeu import RedlineEngine
engine = RedlineEngine('{file_path}')
md_text = engine.to_markdown()
print(md_text)
"
Step 2: Generate CriticMarkup edits
Apply all planned changes as CriticMarkup syntax:
- Insertion: {++new text++}
- Deletion: {--old text--}
- Replacement: {~~old text~>new text~~}
Step 3: Validate changes
python3 -c "
from adeu import ModifyText
mt = ModifyText('{file_path}')
result = mt.validate(critic_markup_text)
print(result)
"
→ If validation fails (ambiguous matches) → fall back to individual MCP calls
Step 4: Apply changes atomically
python3 -c "
from adeu import ModifyText
mt = ModifyText('{file_path}')
mt.apply(critic_markup_text, track_changes=True, output='{output_path}')
"
Step 5: Font normalization gate
python3 scripts/normalize_fonts.py "{output_path}" --unify
If adeu is not installed or validation fails on any edit, fall back to individual MCP calls (standard word-edit modes). Never apply partially validated CriticMarkup.
See ../../references/adeu_integration.md for CriticMarkup syntax and SDK reference.
When operating in live editing mode, each word-mcp-live operation can be undone individually:
User: "撤销" / "undo" / "回退上一步"
→ mcp__word-mcp-live__undo_last_operation()
→ Equivalent to Ctrl+Z in Word
→ Can be called multiple times for multi-step undo
User: "撤销最近3步"
→ Call undo_last_operation() 3 times sequentially
Undo is NOT available in file mode. For file-mode safety, word-edit always works on a copy (via copy_document) for destructive operations, and the original remains as backup.
../../references/tool_routing.md — Tool selection priority and fallback rules../../references/token_budget.md — Token efficiency rules../../references/document_creation_rules.md — New document anti-pattern rules (字体配对、内置样式、TOC)../../references/tracked_changes.md — Native vs Legacy tracked changes reference../../references/live_editing.md — Live editing platform detection and mode rules../../references/adeu_integration.md — adeu Markdown bulk editing pipeline../../references/equation_crossref.md — Equation (LaTeX→OMML) and cross-reference insertionCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub qingfuliu071313-arch/word-agent --plugin word-agent