typechar 1.0.0

Type any Unicode string on macOS, regardless of keyboard layout
docs.rs failed to build typechar-1.0.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: typechar-1.1.0

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

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