Get Claude's proofreading as a table of changes only
Asking Claude to fix a document rewrites all of it. Get only the changed spans as a table, then check by script that every Original cell is in the document.
Ask for a table of the changed spans instead of a corrected document, then check that each Original cell really appears in your text. The same check is used in Verify summary quotes.
[1] Save the text to proofread. This business paragraph has deliberate spelling, agreement and duplicate-word errors.
Please find attached the sales report for this quarter. Revenue increased by 12% compared to the last quarter, and new customers were the the biggest factor. However, payments from several clients were delayed, so unpaid balances has grown and need to be addressed. The meeting will be held on Thursday at 2 pm in the main conference room, please let us know in advance if you are able to to attend. Further details is in the attached file. Thank you for you cooperation.[2] Write the prompt. Wrap the document in <document> tags to separate it from the instructions, and fix the scope, the table format and the "nothing to fix" answer as rules.
Proofread the text inside <document>. Fix only spelling, spacing, grammar and duplicated words. Rules:- Do not rewrite the document. Do not change its meaning, tone or numbers.- Output only the places you changed, as a Markdown table with exactly these columns: Original | Revised | Reason.- Original must be copied character for character from the document, as short as possible but long enough to be unique. Revised is the same span after the fix.- Write the Reason in the language of the document, in a few words.- If nothing needs fixing, output exactly: None- No other text. <document>[3] Append the document and the closing tag, then run it. --tools "" turns tools off.
$ (cat head.txt doc.en.txt; echo "</document>") > prompt.en.txt$ claude -p --model claude-sonnet-5-5 --max-turns 1 --tools "" < prompt.en.txt > out.en.1.txt$ cat out.en.1.txt| Original | Revised | Reason ||---|---|---|| the the biggest | the biggest | Duplicated word || balances has grown and need to be | balances have grown and need to be | Subject-verb agreement || room, please let | room; please let | Comma splice || able to to attend | able to attend | Duplicated word || details is in | details are in | Subject-verb agreement || for you cooperation | for your cooperation | Wrong possessive |Only the six changed spans come back, not the whole document. A second run (out.en.2.txt) returned five of the same spans and skipped the comma-splice fix (room, please let), so the set of changes differs between runs.
[4] Write the check script. It collapses whitespace in the document, then counts how often column 1 of each table row occurs in it. A count other than 1 exits with code 1, and an answer of None passes.
#!/usr/bin/env python3"""usage: check.py doc.txt out.txt — check that column 1 of the table appears in the document exactly once"""import sysdoc = " ".join(open(sys.argv[1], encoding="utf-8").read().split())out = open(sys.argv[2], encoding="utf-8").read().strip()if out in ("없음", "None"): print("no changes reported"); sys.exit(0)rows = [l for l in out.splitlines() if l.strip().startswith("|")]rows = [[c.strip().strip("`") for c in l.strip().strip("|").split("|")] for l in rows]rows = [r for r in rows if len(r) >= 3 and not set("".join(r[:2])) <= set("-: ")][1:] # skip header rowmiss = 0for i, (orig, rev, *_ ) in enumerate(rows, 1): n = doc.count(orig) flag = "OK " if n == 1 else ("MISS" if n == 0 else "DUP ") if n != 1: miss += 1 print(f"{flag} {i}: {orig!r} -> {rev!r} (found {n}x)")print(f"{len(rows)} rows, {miss} not found or not unique")sys.exit(1 if miss else 0)[5] Run it on the second result. All five rows occur exactly once, so it exits 0. Only the last line is shown.
$ python3 -I check.py doc.en.txt out.en.2.txt | tail -1; echo "exit ${PIPESTATUS[0]}"5 rows, 0 not found or not uniqueexit 0The failing output below uses out-bad.txt: the Korean example result with row 5 edited by hand (not a model error).
$ python3 -I check.py doc.ko.txt out-bad.txt | grep -v '^OK'; echo "exit ${PIPESTATUS[0]}"MISS 5: '미리 알려' -> '미리' (found 0x)6 rows, 1 not found or not uniqueexit 1[6] Apply the changes yourself. Drop rows you do not need or that alter the meaning. The script only proves the Original cell exists; it cannot tell whether a Revised cell is right or changes the meaning.