Glypher buttons on a Stream Deck. Each keycap shows its assigned character(s) and updates dynamically — no static images involved.
Glypher started from two recurring frustrations:
U+2028), which Slack accepts but which has no keyboard shortcut.Both problems are solvable with a Stream Deck button. Glypher was written solely to solve them.
Each button can hold a primary, secondary, and tertiary character reached via tap, double-tap, and long-press gestures.
Pastes into any focused application — browsers, terminals, chat clients, document editors, creative tools.
Characters like the line separator or zero-width space show a short custom label on the keycap so the button isn't blank.
A built-in scrollable character picker organised by category so you don't need to look up code points.
Button images are generated as SVG at runtime, with font sizes that scale automatically to the character count and zone size.
Uses the most reliable paste mechanism on each platform to avoid encoding corruption.
Each Glypher button supports three independent character assignments through gesture timing:
| Gesture | Timing | Slot |
|---|---|---|
| Single tap | Press and release | Primary character |
| Double tap | Two presses within 300 ms | Secondary character |
| Long press | Hold for 600 ms | Tertiary character |
When only a primary character is configured, it fills the entire keycap. As secondary and tertiary slots are populated, the button automatically switches to a split-zone layout:
Buttons automatically adapt their layout to show primary, double-tap, and long-press zones.
Glypher has first-class support for characters that are invisible or have specialised semantics:
U+2028Slack parses this character as a real blank line without collapsing it. It's invisible in the message box but
preserved in the formatted output. Glypher shows the label SLF on the keycap.
U+2028 sneaks through. Press the button, get a blank line.
U+200B — label ZW-SpAn invisible character that hints to text-layout engines that line-wrapping is allowed at this point. Useful for breaking automatic URL linkification in apps that linkify everything they see.
U+00A0 — label NB-SpA visible space that prevents line-wrapping between two words — for example between a title and a name: Mr. Smith.
The Property Inspector (the configuration panel in Stream Deck) includes a scrollable character palette organised by category. Clicking any character pre-fills it into the active slot and automatically sets an appropriate display label for invisible characters.
The Quick Insert palette makes it easy to find and assign characters without needing to know Unicode code points.
Line Separator, Zero-Width Space, Non-Breaking Space — all pre-labelled for keycap display.
Em dash, en dash, ellipsis, bullet, section, pilcrow, quotes, copyright, registered, trademark.
→ ← ↑ ↓ ↔ ⇒ ⇐ ↩ ➜ and more directional arrows.
× ÷ √ ≈ ≠ ∞ ≤ ≥ ± ∑ degree, micro sign.
€ £ ¥ ¢ ₿ ₹ — major world currencies at your fingertips.
π Ω Δ and other Greek letters commonly used in technical writing.
| Platform | Minimum version | Paste mechanism |
|---|---|---|
| macOS | 12 (Monterey) | osascript — AppleScript via stdin |
| Windows | 10 | powershell.exe -EncodedCommand |
The plugin spawns a single osascript process that both sets the clipboard
and fires Cmd+V in one atomic step:
set the clipboard to (character id 181) -- µ
tell application "System Events" to keystroke "v" using command down
Using character id N (where N is the Unicode code point) sidesteps every encoding
conversion in the shell pipeline. An earlier implementation used pbcopy followed
by a separate osascript keystroke; this suffered from a clipboard race condition
where clipboard-monitoring software would re-encode UTF-8 as Mac Roman before the paste could
fire, producing garbled output such as Œº instead of µ. The
single-process atomic approach eliminates that race window entirely.
Glypher uses System Events for keystroke injection, which
requires Accessibility access. Grant it in
System Settings → Privacy & Security → Accessibility.
The plugin spawns powershell.exe with an -EncodedCommand argument
(Base64 of UTF-16LE) that loads System.Windows.Forms and pastes atomically:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Clipboard]::SetText([System.Char]::ConvertFromUtf32(181))
[System.Windows.Forms.SendKeys]::SendWait("^v")
ConvertFromUtf32 correctly handles every Unicode code point, including characters
above U+FFFF that require surrogate pairs in .NET's UTF-16 strings.
Base64 encoding avoids command-line quoting issues with multi-byte characters.
[...char]), which yields full
Unicode code points — not UTF-16 code units — so surrogate pairs are handled correctly on both
platforms.
Glypher ships with a 15-button starter profile (5 columns × 3 rows) pre-configured with the most commonly useful Unicode characters. Each button holds three characters via tap / double-tap / long-press.
| Button | Tap | Double-tap | Long-press |
|---|---|---|---|
| Invisible | LINE SEPARATOR U+2028 — SLF | ZERO-WIDTH SPACE U+200B — ZW-Sp | NO-BREAK SPACE U+00A0 — NB-Sp |
| Dashes | EM DASH — U+2014 | EN DASH – U+2013 | ELLIPSIS … U+2026 |
| IP (marks) | COPYRIGHT © U+00A9 | REGISTERED ® U+00AE | TRADE MARK ™ U+2122 |
| Marks | BULLET • U+2022 | SECTION § U+00A7 | PILCROW ¶ U+00B6 |
| Quotes | LEFT DBL QUOTE " U+201C | RIGHT DBL QUOTE " U+201D | RIGHT SINGLE ' U+2019 |
| Right arrows | → U+2192 | ⇒ U+21D2 | ➜ U+279C |
| Left arrows | ← U+2190 | ⇐ U+21D0 | ↩ U+21A9 |
| Vertical arrows | ↑ U+2191 | ↓ U+2193 | ↔ U+2194 |
| Relations | ≈ U+2248 | ≠ U+2260 | ∞ U+221E |
| Compare | ≤ U+2264 | ≥ U+2265 | ± U+00B1 |
| Arithmetic | × U+00D7 | ÷ U+00F7 | √ U+221A |
| Science | µ U+00B5 | ° U+00B0 | ∑ U+2211 |
| Major currency | € U+20AC | £ U+00A3 | ¥ U+00A5 |
| Minor currency | ¢ U+00A2 | ₿ U+20BF | ₹ U+20B9 |
| Greek | π U+03C0 | Ω U+03A9 | Δ U+0394 |
U+00B5 (Micro Sign),
not U+03BC (Greek small letter mu). They look identical but are distinct code points.
U+00B5 is what Option+M types on macOS.
Glypher uses System Events to fire Cmd+V. Grant access in
System Settings → Privacy & Security → Accessibility and enable the
Stream Deck entry (or the helper process) once prompted.
Download and double-click the .streamDeckPlugin file. Stream Deck will import it automatically.
From the Stream Deck app, drag a Glypher action onto any button. Open its Property Inspector to configure characters.
The starter profile installs 15 pre-configured buttons covering the most useful Unicode
characters. From the glypher/ directory:
node docs/install-profile.mjs
After Stream Deck restarts, select the Glypher profile from the profile picker (top-left in the Stream Deck app).
# Preview without writing anything:
node docs/install-profile.mjs --dry-run