typechar 1.1.0

Type any Unicode string on macOS, regardless of keyboard layout
Documentation

typechar

Type any Unicode character — or string — on macOS, regardless of your keyboard layout.

typechar
typechar --unicode 20ac
typechar '¯\_(ツ)_/¯'

Why this exists

macOS keyboard layouts define which characters your keys can produce. If a character isn't on your layout, no key combination will type it. And tools like Karabiner-Elements can't help directly: Karabiner remaps key codes, not characters — whatever key it synthesizes is still interpreted through your active layout.

The concrete story behind this tool: on a US layout, lives on exactly one combination — ⌥⇧2. If a window manager like AeroSpace or any other hotkey daemon claims that combo, the character becomes untypeable. Your options are to sacrifice the hotkey, or to bypass the layout system entirely.

typechar does the latter. It posts the character itself as a keyboard event via CoreGraphics (CGEventKeyboardSetUnicodeString), so the layout never gets a vote. Bind it to any hotkey via Karabiner, skhd, Hammerspoon, or a shell alias, and type , , , °, or any snippet — from any layout.

Install

Homebrew

brew install blaueeiner/tap/typechar

Cargo

cargo install typechar

From source

git clone https://github.com/blaueeiner/typechar
cd typechar
cargo install --path .

Usage

typechar [OPTIONS] <string>
typechar [OPTIONS] --unicode <hex> [--unicode <hex>...]

Options:
  -u, --unicode <hex>  Codepoint to type, e.g. 20ac or U+20AC (repeatable)
  -d, --delay <ms>     Wait before typing (for apps that drop fast events)
  -h, --help           Show this help
  -V, --version        Show version

Examples:

typechar# type a literal character
typechar --unicode 20ac     # same thing, by codepoint (handy inside JSON configs)
typechar -u 2713 -u 2192    # ✓→ — codepoints compose in order
typechar 'Hello — World'    # whole strings work; it's a snippet tool too
typechar --delay 100 €      # some apps drop events that arrive mid-keystroke
typechar -- --help          # everything after -- is typed literally

Permissions

The process that invokes typechar needs Accessibility permission (System Settings → Privacy & Security → Accessibility):

  • run from a terminal → grant it to your terminal app
  • run from a Karabiner shell_command → grant it to karabiner_console_user_server
  • run from skhd / Hammerspoon → grant it to that daemon

If permission is missing, typechar exits with an error telling you so instead of silently typing nothing.

Karabiner-Elements example

Bind ⌥E to (add to a rule in ~/.config/karabiner/karabiner.json):

{
    "description": "Option+E types €",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "e",
                "modifiers": { "mandatory": ["option"] }
            },
            "to": [
                { "shell_command": "/opt/homebrew/bin/typechar --delay 50 --unicode 20ac" }
            ]
        }
    ]
}

--unicode avoids putting non-ASCII literals in JSON; --delay 50 keeps the synthetic event from racing your still-held modifier keys.

skhd example

alt - e : /opt/homebrew/bin/typechar --delay 50 --unicode 20ac

Problems this solves

Situations where people end up here:

  • "How do I type € on a US keyboard on macOS?" — natively it's ⌥⇧2, but if a window manager or hotkey daemon has claimed that combo, the character is untypeable. typechar € on any free hotkey fixes it.
  • "Karabiner types the wrong character / can't type a Unicode character." — Karabiner remaps key codes, which are still interpreted through your keyboard layout. A character that isn't on your layout can't be produced by any key code. Calling typechar from a shell_command sidesteps the layout entirely.
  • "Type em-dash / arrow / checkmark / degree sign from a keyboard shortcut."typechar —, typechar →, typechar ✓, typechar °, or any snippet, without switching layouts or opening the character picker.
  • "AeroSpace / skhd / Rectangle stole the shortcut for a special character." — tiling window managers commonly bind -combos that macOS layouts use for symbols. typechar gives every symbol a home on whatever keys are left.

Use as a library

typechar is also a Rust crate (docs.rs/typechar):

cargo add typechar
if !typechar::has_permission() {
    typechar::request_permission(); // prompts the user via System Settings
}
typechar::type_string("")?;

type_string posts the text to the frontmost app, bypassing the keyboard layout; it returns TypeError::PermissionDenied when the process lacks Accessibility permission instead of silently doing nothing.

How it works

typechar creates a keyboard event with CGEventCreateKeyboardEvent, attaches your string with CGEventKeyboardSetUnicodeString, and posts it to the HID event tap. The frontmost app receives the characters directly — the keyboard layout is never consulted. Long strings are split into 20-code-unit chunks (the API's practical limit), never splitting a surrogate pair.

License

MIT