Changing macOS modifier keys… VMs edition

If you’re anything like me and spend a lot of time tinkering with apps and your home lab, you’re probably switching constantly between macOS, Linux, and Windows (and others!). And when macOS is your main system but you also run several virtual machines, keyboard shortcuts and modifier keys can quickly become a source of friction. Specially regarding modifier keys (most OSes use Control the same way macOS usses Command. Fortunately, you can modify that for macOS and keep our VMs behave with the shortcuts you’re used to —-without interfering, using Karabiner Elements… and a trick.

The best app I’ve found, in general, to alter keystrokes on macOS is Karabiner Elements. It requires minimal initial work to get it up and running, but you will save a lot of time if you make all your shortcuts the same (the main point of this). If you don’t use it already, you can download it from here:

https://github.com/pqrs-org/Karabiner-Elements/releases

With Karabiner-Elements, you can make the left and right Control keys behave like Command. The problem appears when you use a virtual machine: inside VirtualBox, you usually want Control to remain Control.

So let’s see how I fixed this, hoping it could be useful for you

The Karabiner-Elements fix: creating a rule

The solution is simple: remap Control globally, then add an exception for VirtualBox.

Here is the complete configuration:

{
  "description": "Control → Command (except in VirtualBox)",
  "manipulators": [
    {
      "type": "basic",
      "from": {
        "key_code": "left_control"
      },
      "to": [
        {
          "key_code": "left_command"
        }
      ],
      "conditions": [
        {
          "type": "frontmost_application_unless",
          "bundle_identifiers": [
            "^org\\.virtualbox\\.app\\.(VirtualBoxVM|VirtualBox)$"
          ]
        }
      ]
    },
    {
      "type": "basic",
      "from": {
        "key_code": "right_control"
      },
      "to": [
        {
          "key_code": "right_command"
        }
      ],
      "conditions": [
        {
          "type": "frontmost_application_unless",
          "bundle_identifiers": [
            "^org\\.virtualbox\\.app\\.(VirtualBoxVM|VirtualBox)$"
          ]
        }
      ]
    }
  ]
}
How to setup the rule
  1. Open Karabiner-Elements.
  2. Go to Complex Modifications.
  3. Click Add your own rule.
  4. Replace the example content with the JSON above.
  5. Save the rule.
  6. Make sure it is enabled in your current profile.

From that point on, outside VirtualBox:

  • Left ControlLeft Command
  • Right ControlRight Command

For example, pressing Ctrl+C will behave like ⌘C.

The same applies to copy and paste, new tabs, and other common shortcuts used with Command on macOS.

Additionally, we aim to change command behavior to act as windows on macos but keep it working for Windows VMs.

What happens inside VirtualBox?

This is the important part of the rule:

{
  "type": "frontmost_application_unless",
  "bundle_identifiers": [
    "^org\\.virtualbox\\.app\\.(VirtualBoxVM|VirtualBox)$"
  ]
}

frontmost_application_unless tells Karabiner to apply the remapping unless one of those applications is currently in the foreground.

The regular expression covers the two VirtualBox bundle identifiers used here:

org.virtualbox.app.VirtualBox
org.virtualbox.app.VirtualBoxVM

That means that when you switch to a VirtualBox virtual machine, the Control keys behave like normal Control keys again. As soon as you switch back to another macOS application, they automatically behave like Command.

No profile switching, manual toggles, or extra steps are required.

How to find an application’s bundle identifier

If the exception ever stops working after a VirtualBox update, or if you want to do the same thing with VMware, Parallels, a game, or any other application, Karabiner includes an easy way to find its bundle identifier.

  1. Open Karabiner-EventViewer.
  2. Go to Frontmost Application.
  3. Switch to the application you want to identify.
  4. EventViewer will display its bundle identifier.

You can then add that identifier to bundle_identifiers and create additional exceptions.

One small caveat

This configuration turns both Control keys into Command outside VirtualBox. That also means you lose the macOS shortcuts that genuinely rely on Control.

In my case, that is intentional. If you want to keep one real Control key, simply remove one of the two manipulator blocks from the JSON. For example, you could remap only left_control to left_command and leave the right Control key untouched.

It is a tiny modification, but if you constantly switch between macOS and other operating systems, it removes a surprising number of wrong key presses. As a side note and if you have issues, make sure the app has the proper permissions regarding keyboard control.

Leave a Reply