to.send_user_command

send_user_command sends a command to an external program prepared by the user.

This mechanism is designed to let an external program process input with even lower latency than shell_command.

To use send_user_command, you need to prepare an external program separately. There are mainly two approaches.

  1. One approach is to build a Swift program that integrates the Karabiner-Elements-user-command-receiver Swift package.

    A sample program built with this approach is Karabiner-Elements-user-command-server. It receives commands such as set_window_frames and show_window_frames and changes window positions.

  2. The other approach is to implement your own UNIX domain datagram server in any programming language you prefer, since send_user_command uses UNIX domain socket datagram communication.

Example

This example is a configuration for Karabiner-Elements-user-command-server.

{
    "description": "Set window frames by right_shift+d",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "d",
                "modifiers": {
                    "mandatory": ["right_shift"],
                    "optional": ["caps_lock"]
                }
            },
            "to": [
                {
                    "send_user_command": {
                        "payload": {
                            "command": "set_window_frames",
                            "frames": [
                                {
                                    "bundle_identifier": "com.apple.Terminal",
                                    "x": 100,
                                    "y": 80,
                                    "width": 1200,
                                    "height": 800
                                },
                                {
                                    "bundle_identifier": "com.apple.Safari",
                                    "x": "center",
                                    "y": 60,
                                    "width": 1400,
                                    "height": 900
                                }
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

Socket file used for communication

Because send_user_command communicates over UNIX domain sockets, it uses a socket file. You can specify the socket path with endpoint. If omitted, the following path is used.

/Library/Application Support/org.pqrs/tmp/user/{UID}/user_command_receiver.sock

Tips for implementing your own program

First, it is helpful to verify that your server can receive messages. For example, you can start a server with socat like this.

socat -u UNIX-RECVFROM:/tmp/karabiner-elements-user-command-server.sock,fork STDOUT

Then, with the following configuration, you can send a command by pressing right_shift+a and confirm it is received by socat. The receiver gets the payload as JSON-serialized data.

{
    "description": "send_user_command by right_shift+a",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "a",
                "modifiers": {
                    "mandatory": ["right_shift"],
                    "optional": ["caps_lock"]
                }
            },
            "to": [
                {
                    "send_user_command": {
                        "endpoint": "/tmp/karabiner-elements-user-command-server.sock",
                        "payload": "hello"
                    }
                }
            ]
        }
    ]
}