A lightweight desktop typing engine that allows users to press multiple keys simultaneously ("chords") to expand into English words or phrases.
Unlike stenography:
- no special keyboard layout
- no steno theory
- uses normal QWERTY mental model
- user-defined dictionary
Example:
p+r+b -> problem
w+h -> with
t+o -> to
Goal:
- reduce keystrokes
- reduce finger fatigue
- preserve normal typing feel
Current options are poor fits:
| Solution | Problem |
|---|---|
| Steno/Plover | huge learning curve |
| Kanata/QMK | low-level remapping, not language-oriented |
| Text expanders | sequential, not simultaneous |
| AI autocomplete | not deterministic |
- simultaneous key chord detection
- word expansion
- low perceived latency: timing window limits chord eligibility only; commit on last keyup
- normal keyboard compatibility
- custom user dictionary
- phrase expansion
- typo tolerance
- replacing full English typing
- court-reporting speed
- full stenography compatibility
- custom keyboard firmware
Users think:
- abbreviations
- consonants
- mnemonic clusters
NOT:
- phonetics
- steno theory
- hand zones
A chord gesture is one attempt to fire a chord. Rules:
a) Window start: The gesture starts on the first keydown (T₀).
b) Who may join: Additional keydowns count toward this gesture only if they occur within T₀ + timing window (default 70ms, configurable 30–150ms).
c) First keyup closes enrollment: On the first keyup, no further keydowns join this gesture.
d) Chord key set: Dictionary lookup uses the keys that were held down together (simultaneous overlap)—not merely “every key that keydown’d before first keyup.” Normalize key order for lookup (e.g. canonical sorted signature).
e) Commit: Early commit when all keys up—on last keyup, lookup; inject expansion or passthrough originals (no idle timer wait).
If chord not recognized:
- emit original keys normally
Must never “eat” typing unexpectedly.
User presses:
p+r+b
System outputs:
problem
User presses:
w+h
Outputs:
with
Implement Core Principles §2: track keydown/keyup, normalize chord signature, longest-match dictionary lookup; on match suppress gesture keys and emit replacement; on no match passthrough (never drop input).
Example (normalized keys → expansion):
{
"prb": "problem",
"wh": "with"
}How long after T₀ (first keydown) new keydowns may join before first keyup: default 70ms, range 30–150ms. Does not delay output—commit on last keyup.
User-editable:
words:
prb: problem
txn: transaction
wh: withSupports:
- words
- phrases
- punctuation
Longest match wins.
Example:
pr -> process
prb -> problem
If all 3 keys detected:
- choose
prb
Low-level keyboard hook:
- macOS event tap
- Windows raw input
- Linux evdev/xinput
Gesture state, §2 rules, normalization, longest match, commit on last keyup.
Inject replacement text:
- virtual keyboard events
- clipboard fallback
Hot reload dictionary; no restart.
words:
prb: problem- Swift
- CGEventTap
- accessibility API
- Rust
- Tauri UI
- native input hooks
User types:
problem
Must not accidentally trigger:
prb
Prevented by §2: enrollment closes on first keyup, simultaneous-overlap key set, and timing window.
Some keyboards miss arbitrary multi-key combos—MVP includes chord tester UI and guidance on reliable combos.
Detect frequent typed words:
implementation
Suggest:
impl
- context ranking when multiple chords could apply
- local stats: saved keystrokes, chord usage
- simultaneous chord detection
- YAML dictionary
- word expansion
- macOS support
- tray app
- configurable timing
- AI
- cloud sync
- mobile
- predictive language models
- firmware support
Effort reduction, retention, expansion accuracy, low false positives and interruption rate.