What SyntaxGym is, and what it measures
SyntaxGym is a code typing trainer that runs entirely in your browser. It records every keystroke with its timing, works out which syntax tokens cost you accuracy and which cost you hesitation, and schedules practice against those specific weaknesses. No account, no server, no telemetry.
The problem it addresses
Most typing tools report a single speed number. That number is nearly useless for code, because it averages over the parts you find easy and the parts you find hard. A developer who types identifiers at 90 WPM and stalls for half a second before every &mut self gets the same headline figure as one who is genuinely fluent.
The interesting question is not how fast but where exactly do you stop. Answering it requires per-keystroke timing, and answering it for code requires knowing which characters belong to which syntax token — which in turn requires a lexer, not a substring search.
What each number means
| Token | Reads as | Why it is awkward |
|---|---|---|
Accuracy | correct keystrokes ÷ total keystrokes | Counts every attempt. Five stabs at the same character cost five, not one. |
Raw WPM | all attempts ÷ 5 ÷ minutes | Includes keystrokes you later corrected. This is your gross output. |
Adjusted WPM | correct attempts ÷ 5 ÷ minutes | Only the keystrokes that landed. The gap between the two is your correction cost. |
Consistency | 1 − (stddev ÷ mean) of key gaps | Rhythm evenness, 0 to 100. High means steady; low means bursts separated by stalls. |
Weak tokens | token instances you mistyped | Counted per occurrence, so `2 of 5 missed` is a rate rather than a raw tally. |
Hesitation | median pause before a token ÷ baseline | Catches tokens typed correctly but slowly. Gaps over five seconds are discarded as breaks, not thought. |
Mastery | 1 − miss rate, across all sessions | The long-run version of weak tokens, on the Progress page. |
Why hesitation is tracked separately
A mistake list can only report characters you got wrong. But the strongest evidence that a piece of syntax is not yet automatic is a pause in front of it — and a pause leaves no trace in a mistake list, because nothing went wrong.
SyntaxGym stores the gap before every keystroke, takes the median gap for the session as your personal baseline, and then reports tokens whose entry latency runs well above it. The baseline is per session and per person: it is not comparing you to anyone else, only to your own steady state a few seconds earlier.
Two deliberate limits. Fewer than eight timed keystrokes and no baseline is computed at all — a median of three numbers is noise. And any gap over five seconds is dropped entirely, because someone answering a message is not hesitating over =>.
Token detection is a lexer, not a search
Before any token is counted, the source is scanned into code, comment and string regions. Only the code regions are eligible, and identifier-like tokens additionally require word boundaries.
// rematch this later
let label = "match arm";
fn rematch() {}
let x: NoneType = value;
if matches!(x, Some(_)) {}Rust adds one more trap: 'a in &'a str is a lifetime, not an opening character literal. Scanners that miss this treat the rest of the line as string content and quietly drop the whole signature from analysis. The rule is that a quote opens a character literal only when the third character closes it, or when an escape follows immediately.
The same rules exist twice: in TypeScript for the browser, and in Rust as a dependency-free reference implementation with its own test suite. It is a lexer, not a compiler — SyntaxGym does not typecheck or execute anything.
Where your data lives
In localStorage, in your browser, on your machine. Session history, custom snippets, daily drill progress and settings — all four. There is no account to create, no request that carries your keystrokes anywhere, and no analytics on what you type.
The practical consequences are worth stating plainly, because “local-first” is often marketed as pure upside. Clearing your browser data deletes your history. Your progress does not follow you to another device or another browser. There is an export and import on the History page for exactly this reason, and it is a manual file — nothing syncs by itself.
The one feature that produces a shareable URL, the challenge link, encodes the snippet in the URL fragment. Fragments are never sent to a server, so even a shared challenge stays between you and whoever you send the link to.
What it deliberately is not
Not a Rust compiler, linter or type checker. Not a LeetCode clone: it does not scrape or mirror problem statements, editorial solutions or submissions from any judge, and the intended workflow for algorithm practice is to paste your own accepted solution. Not a general typing test — words per minute is explicitly not the headline metric, and the interface says so.
It also will not make you a better programmer in any broad sense. Typing has never been the bottleneck in software. What it removes is narrower and real: the small repeated stalls where your hands stop to work out what character comes next.
Frequently asked questions
- Is SyntaxGym free?
- Yes, and there is no paid tier, no account and no usage limit. It is open source under the MIT licence. There is nothing to sign up for, because there is no server holding anything to sign in to.
- Does SyntaxGym send my keystrokes anywhere?
- No. Everything is written to your browser's localStorage and stays on your machine. There is no analytics on typing content, no account system and no server-side storage of sessions. The trade-off is that clearing browser data erases your history, so the History page offers a manual export.
- How is this different from Monkeytype or Keybr?
- Those are excellent general typing trainers built around prose and per-character letter drills. SyntaxGym is built around syntax tokens: it knows that &mut self is one unit, reports mastery per token rather than per letter, and separates hesitation from mistakes. It also lexes the code so a token inside a comment or a string is not counted.
- Which languages does SyntaxGym support?
- The built-in snippet library is Rust and Rust-based DSA. The analysis engine ships token rules and lexing for Go, TypeScript, JavaScript, Python and C++ as well, so pasted snippets in those languages are analysed correctly — but there is no built-in library for them yet.
- Can I practise my own code?
- Yes. Paste any snippet into the Snippets page and it is saved locally alongside the built-in library. Custom snippets get the same token analysis, weak-token reporting and hesitation tracking as anything else.
Keep reading
- Rust typing practice: the full method
Why Rust is structurally slow to type, and the ten-step order for drilling it.
- Option and Result practice
A worked example of the approach on the two most-typed constructs in Rust.
- Borrowing and ownership practice
Where hesitation shows up most clearly, and why accuracy alone misses it.
Try it on a real snippet
No account, nothing uploaded. Your results stay in this browser.