| title | The smart normalizer |
|---|---|
| description | How normalizing prunes typos, humanizes typing and trims idle time. |
| order | 6 |
Normalizing is where a messy human recording becomes a clean score. It is not a
separate command — it runs automatically at the end of demo capture (skip it
with demo capture --no-normalize). Four algorithms run over the raw event stream.
The raw input is replayed through a tiny line editor. Destructive edits are applied and discarded, so only the intended command survives:
Backspace/Delremove the previous character.Ctrl-Ukills the whole line.Ctrl-Ccancels the line.
typed: g t i ⌫ ⌫ i t ⏎ → recorded: "git"
Blank lines (a bare Enter) are dropped.
Each command becomes a type step with human_salt = true. At export, the
characters are written one at a time with a delay around [typing].base_ms, offset
by a bounded random salt (±salt_ms). The result reads like a fast human, not
an instant paste — and is reproducible when [typing].seed is set.
Pauses between commands are kept (they feel natural) but clamped: too-short gaps are widened to a readable minimum, long "think time" is capped. The trailing idle that triggered the end of the recording is removed entirely, so the demo ends crisply.
Timing is derived from the raw timestamps:
- between commands → the gap until the next command starts typing, clamped;
- after the last command → the time output kept arriving, capped.
When a gap was really "output streaming, then silence" (a build, a download), the
normalizer emits a wait_for_quiet instead of a fixed wait — robust against
timing changes when the demo is re-run.
The pause between typing a command and pressing enter is hesitation, not
content. Every fixed wait that immediately precedes an enter keypress is
normalized to 200 ms, so commands fire with one deliberate rhythm.
The output is a demo.toml (written by capture --score, or in memory otherwise)
that is already valid and ready to record + export — or to hand-edit.