A small macOS app that types text into whatever app you have focused, with realistic human-like rhythm.
You paste text into a window, set a typing speed and an error rate, click Start, focus the target app, and Typer types it for you — with natural pauses between words, longer pauses after punctuation, occasional thinking pauses, mouse jitter, and (in chunked mode) sentence-level false starts that get backspaced and rewritten.
Built as a weekend project to learn Python and macOS automation. Useful for:
- Accessibility — slower, paced text input for people who find pasting walls of text overwhelming.
- Screencast / demo recording — clean, paced typing on screen without your hands in shot.
- Automated UI testing of text-input flows.
- Just for fun — watching it type for you is oddly satisfying.
- macOS (tested on Apple Silicon).
- Homebrew.
- Python 3.10 or newer (the system Python 3.9 is too old for current
pynput).
# 1. Install a modern Python (with Tk for the UI)
brew install python-tk
# 2. Install the one Python dependency
/opt/homebrew/bin/python3 -m pip install --break-system-packages pynputDouble-click run.command in Finder, or from a terminal:
/opt/homebrew/bin/python3 typer.pyTyper simulates real keystrokes, so the first time you click Start, macOS will block it and pop up a dialog. Grant it under:
- System Settings → Privacy & Security → Accessibility → enable Terminal (or whatever app launched the script).
- System Settings → Privacy & Security → Automation → allow Terminal to control "System Events" if prompted.
These are the same permissions any keystroke-automation tool (Keyboard Maestro, BetterTouchTool, etc.) needs.
- Speed slider — characters per minute, 60 to 700.
- Error rate slider — 0% to 15%; errors type a neighboring QWERTY key, pause, backspace, and correct.
- Stop button + global Esc key — cancellation is effectively instant.
- 5-second countdown before typing starts, so you can focus the target app.
For longer texts, enable chunked mode to type in bursts with idle gaps in between (configurable, 10–180s). When chunked mode is on, additional humanization kicks in:
- Mouse jitter during pauses (real OS-level mouse events).
- Re-read passes — every 150–300 characters, the cursor briefly moves back a few characters and then forward, like glancing at what you just wrote.
- Sentence-level false starts — occasionally types a chunk of a different sentence from your text (a real "wrong thought"), pauses, backspaces it, and types the correct sentence.
The typing engine uses AppleScript's keystroke command (via osascript) rather than direct Python-level keystroke injection. AppleScript produces real hardware-style key events with proper keycodes, which apps like browsers receive as genuine keydown/keypress/input events.
The app is a single Python file (typer.py) using Tkinter for the UI. No build step, no Xcode, no dependencies beyond pynput for the global Esc listener and mouse jitter.
- macOS only.
- AppleScript keystroke generation caps out around 700 cpm reliably.
- Some special characters (em dashes, certain Unicode) may need a non-default input source.
MIT — see LICENSE.
This was built collaboratively in a single sitting as a learning project. The full transcript of the build (including the back-and-forth debugging Google Docs' paste detection) is in docs/transcript.md.