What actually happens between dropping a manuscript into Bethaniel and getting a marked-up one back — the passes, the order they run in, and why each one is there.
Six paragraphs, then the detail.
Stages run in order, and the order carries information: chunking cannot happen before chapter detection, and the reviewer cannot score a correction that has not been proposed yet.
DOCX, EPUB, PDF, Markdown or plain text. DOCX comes in through mammoth; EPUB and PDF have their own readers. The PDF reader reconstructs paragraphs, emphasis and headings from where the glyphs physically sit on the page — and refuses scanned documents outright rather than pretending to read them.
Everything becomes Markdown internally. That single internal format is what lets a correction found in chapter 12 be written back into the original DOCX with its formatting intact.
Headings are detected and the manuscript is split into editable units. Sections under fifty words — title pages, a stray heading, a dedication — are folded into the chapter they belong to rather than becoming their own one-line "chapter", which is what makes a job's progress list read like a book's contents rather than like a parser's output.
Scene-break markers are recognised and normalised at the same time, so a manuscript that uses *** in one place and # in another comes out consistent.
Each chapter is split into chunks of roughly 2,500 words, breaking only at paragraph boundaries, with the last paragraph of one chunk repeated at the head of the next. The overlap is what stops a correction at a chunk seam from being made without context. Chapter boundaries reset the overlap to zero — the end of chapter 4 is not context for the start of chapter 5.
Before the model sees anything, the rule-based checkers run over the chunk. They are fast, they are the same every time, and they never invent a word. What they find goes into the correction set and into the model's prompt as hints — because a spell checker knows a word is wrong far more reliably than it knows what the word should have been, and the model reading the sentence is better at the second part.
The chunk, the deterministic hints, your style guide if you supplied one, and the settings you chose are assembled into a prompt. The model returns proposed corrections as original/corrected pairs, not as a rewritten chunk — so a change can always be located, shown and refused individually.
A second prompt sends each proposed correction back to the model in the role of a skeptical second reader: is this actually an error, and is this actually the fix? Each gets a 1–5 confidence score. Anything under the threshold is flagged rather than dropped, so a correct suggestion the reviewer disliked is marked for your attention instead of gone. A finding from the dictionary or the grammar server is never overruled this way at all — a dictionary is not an opinion a model gets to out-vote.
The reviewer runs in parallel with the next chunk's editor, so the extra pass costs far less wall-clock than it looks like it should.
Every surviving correction has to get past a set of mechanical guards before it can touch the text. These are described below; the shortest way to put it is that a correction is not allowed to make the manuscript worse in a way a human proofreader would never do.
You get a word-level inline diff, correction by correction, with the reason attached and the confidence score visible. Accept, dismiss, or accept all. Export to Markdown, DOCX or EPUB — and for a DOCX import, back into the original document with its own styles, rather than into a freshly generated one.
The core design decision is that the rule-based and the model-based checkers are kept as separate sources, run over the same text, and merged afterwards. Neither can do the other's job.
a/an, doubled words, missing apostrophes, "PIN number"They never hallucinate. They also cannot tell that their should have been there, because both are real words.
It reads the sentence. It will also occasionally propose something confidently wrong, which is why nothing it says is applied unreviewed.
Cross-source pre-approval. When a deterministic checker and the model independently produce the same correction, it is auto-applied without needing the reviewer's blessing. A rule and a language model are wrong in completely different ways, so their agreeing is a much stronger signal than either one being confident on its own.
Real Hunspell, compiled to WebAssembly, reading the standard .aff/.dic dictionary pairs unmodified. It flags every out-of-dictionary word in the chunk with no per-chunk cap, while protecting names from your style sheet and words that behave like proper nouns.
Using the actual engine rather than a reimplementation is what makes the compounding languages work. Danish and German build new words by joining old ones — rådhusarkivet, Werkstattfenster — and a novel in either is full of compounds that appear in no dictionary. Hunspell composes them from their parts. A checker without that machinery reads every one of them as a misspelling, which in practice means the author turns the spell checker off.
Words the dictionary can never catch, because both spellings are real: their/there, Danish nogen/nogle, German das/dass, Spanish si/sí. Bethaniel carries a curated set per language and injects the relevant ones into the model's prompt — but only when both members of a pair actually appear near each other in the chunk. A rule that fired on every occurrence of their would flood the manuscript; a hint that fires only where confusion is possible costs almost nothing.
A local LanguageTool server, running offline on your machine, at its stricter picky rule level. Released installers bundle both LanguageTool and a matching Java runtime, so there is nothing to install; if it is missing it degrades to doing nothing rather than failing the job.
A short list of LanguageTool rules is switched off permanently, each with the measurement that put it there. The bar is deliberately harsh — zero real errors found, at least one invented — because a LanguageTool correction skips the reviewer, so nothing downstream restrains a rule that misfires. One Spanish rule, which rewrote every straight quotation mark to an angled one, was firing 248 times across the test corpus and had never once landed on a real error.
English-only deterministic checks for a versus an, missing contraction apostrophes, doubled words, redundant acronyms and sentence spacing. The other languages skip this pass entirely rather than have English rules applied to them.
Quotation-mark repair is deterministic, because the difference between an opening and a closing mark is something a model reads past and a rule never does. It owns quotation marks outright, which is why the grammar server is not allowed to touch them. Dialect normalisation — British to American spelling or back — runs the same way, once you have stated which one the manuscript is in.
Some things that look like errors are choices. Bethaniel's rule is that where a convention is genuinely contested, the author states it and only then is it enforced — because a checker that guesses is wrong about half the time and loud about it either way.
| Language | The choice | Default |
|---|---|---|
| English | Oxford comma | On |
| English | Comma after an introductory phrase | Off — "Finally she turned" is left as written |
| English | British or American spelling | American |
| Danish | Grammatisk komma or nyt komma | Grammatisk |
| Spanish | RAE comma conventions | Applied |
The Danish one is the clearest case. Danish has two competing comma systems, both sanctioned by Retskrivningsordbogen and mutually contradictory: grammatisk komma puts a comma before every subordinate clause, nyt komma mostly does not. Enforcing either without asking is wrong for half of all Danish manuscripts. Danish comma detection was deliberately left weak until this toggle existed.
Between the reviewer and your screen sits a set of mechanical guards. They exist because each one describes something that actually happened during development, and each one is now a test that fails if it happens again.
.,, no doubled full stop. And when the model rewrites a paragraph's last sentence and drops its final period — which it does — the period is put back without discarding the legitimate fix that came with it.The guards apply to every source, including the deterministic ones. A rule-based correction is not privileged just because a rule produced it.
Copy editing is one of four passes. They share the whole pipeline above — chunking, review, the guards, the export path — and differ in the prompt and in what they produce.
| Pass | What it does |
|---|---|
| Copy edit | Spelling, punctuation, grammar, capitalisation, duplicated words. The mechanical layer. |
| Line edit | Style, rhythm, phrasing, redundancy. Suggestions rather than corrections — there is no such thing as an objectively missing comma here. |
| Translation | Full text into any target language, then a target-language polish pass, then a paragraph-by-paragraph fluency review that re-polishes anything scored as garbled. Cloud-only — see below. |
| Analysis | Character catalogue, location catalogue and timeline, merged across every chapter, plus an auto-generated prose summary and a marketing blurb. |
Selecting copy edit and line edit together merges them into a single pass over each chapter rather than running the manuscript twice. Selecting several analysis passes does the same.
The pipeline is identical in all four cases. The only thing that changes is where the inference happens, and whether the text leaves your machine.
| Model | Runs on | Text stays local |
|---|---|---|
| Local Betty — Qwen3.5 4B | Your machine · ~3 GB, 8 GB RAM | Yes |
| Custom Betty | Your machine · any GGUF you supply | Yes |
| External Betty | Your own API key, your chosen provider | No |
| Betty in the Cloud — hosted, EU | Bethaniel's hosted service, paid per job | No |
Local Betty is the default, and the app is fully usable having never touched the network. Before it is downloaded, the Run button says how long a novel should take on the machine in front of it. The cloud options exist for machines that cannot run a 4B model at a useful speed — they are opt-in per job, and the terms say plainly what happens to the text.
The one exception is translation. The local model was measured at it and was not good enough — a weak translation is fluent, confident and wrong, and an author who does not read both languages cannot see it — so the app refuses a translate job on a local model. Translation runs only on Betty in the Cloud, on a much larger model than the editing passes use, or through your own key.
It used to offer two to four editor agents per chunk, and several reviewers, on the theory that independent opinions could be pooled. They were measured, and there were no independent opinions to pool.
Corrections are decoded greedily — the model is asked for the single most likely answer rather than a sample, because finding an error is a question with a right answer and not a creative one. Ask the same question that way twice and you get the same answer twice. Every extra agent was re-reading the same chunk with the same prompt and returning a byte-identical list, which the merge step then collapsed back into one.
Measured across four languages and three models: one editor and two produced identical output in every case — the same corrections, the same misses, the same flags on clean text — and one was 15–20% faster. So the options were removed rather than left as a setting that costs you time and energy for nothing. The one exception is kept: when you supply a style sheet, a second agent runs with a genuinely different prompt, and that one can disagree.
Every claim on this page that has a number attached comes from a benchmark that anyone with the repository can re-run. Paired fixtures — a clean text and the same text with roughly a hundred errors planted at known character offsets — are run through the real pipeline, and what comes back is scored against what was planted.
The errored fixtures are constructed, not annotated: a generator plants each error from a per-language plan and refuses any edit that does not produce exactly one span of the intended kind, so the ground truth cannot drift from the text. The passes are scored differently because they fail differently — recall and precision against the planted errors for copy edit, and chrF against human reference translations, plus length-ratio and untranslated-word checks, for translation.
The results, per language, with the misses broken down by what kind of error was missed, are on the performance page.