Fixing keyboard layouts on macOS over remote desktop

Get the ~ key back when you're remoting into a Mac using NoMachine, and the Mac has an ISO keyboard layout.
June Rhodes posted on Nov 21, 2020

I was supporting a customer recently where their Mac laptop had a physical ISO keyboard layout, and because of this the essential ~ key on my ANSI keyboard didn’t map correctly. None of the built-in keyboard layouts in macOS fixed the issue, so I put together a custom keyboard layout to resolve the issue.

Things that didn’t work

Since it’s the physical keyboard in the Mac that has an ISO layout, and no external keyboard is attached, macOS tries to be helpful and prevents you from reconfiguring the keyboard layout (because it already knows what the keyboard layout is). None of the following solutions work:

  • The Settings app does not permit you to reconfigure the keyboard layout.
  • Attempting to delete the file at /Library/Preferences/ and rebooting does not start the Keyboard Assistant.
  • Manually running the Keyboard Assistant with sudo open /System/Library/CoreServices/ does not work, because it errors saying the keyboard is already configured.
  • Using Karabiner Elements to remap the keys doesn’t work, presumably because the point at which Karabiner hooks keypresses occurs before the point that NoMachine injects them into the remote session.

Making a custom layout

Eventually I found a tool called Ukelele which can be used to build custom keyboard layouts for macOS. It took a bit of wrangling, but eventually I was able to load a U.S. keyboard layout with ISO coding and then copy the ISO ~ key (which doesn’t exist on an ANSI keyboard) over the ยง key (where the ~ character exists on an ANSI keyboard). Once I had that saved and configured it as the keyboard layout, I could type paths normally in the Terminal again ๐Ÿ˜„

To save you the time of going through this process, I’ve exported the keyboard layout and made it available on the Redpoint Games website. You can download the custom keyboard layout here.

All code examples are MIT licensed unless otherwise specified.