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.

```sh
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](https://karabiner-elements.pqrs.org/) 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 — <kbd>⌥⇧2</kbd>. If a window manager like [AeroSpace](https://github.com/nikitabobko/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

```sh
brew install blaueeiner/tap/typechar
```

### Cargo

```sh
cargo install typechar
```

### From source

```sh
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:

```sh
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 <kbd>⌥E</kbd> to `€` (add to a rule in `~/.config/karabiner/karabiner.json`):

```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 <kbd>⌥⇧2</kbd>,
  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 <kbd></kbd>-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](https://docs.rs/typechar)):

```sh
cargo add typechar
```

```rust
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](LICENSE)