This project implements a virtual keyboard and virtual mouse using DriverKit on macOS. These virtual devices are recognized by macOS as same as physical hardware, allowing you to control macOS with keystrokes and mouse inputs from the virtual devices.
The client for controlling the virtual devices is provided as a header-only C++ library. By integrating this library, your software can control the virtual devices.
Note: The ability to send keystrokes and mouse inputs means having full control over macOS. Therefore, to prevent malicious software from manipulating the virtual devices, the virtual devices will only accept commands from processes running with root privileges. This means that the software incorporating the client library must be run with root privileges.
- macOS 14 Sonoma
- Both Intel-based Macs and Apple Silicon Macs
- macOS 13 Ventura
- Both Intel-based Macs and Apple Silicon Macs
-
Open
dist/Karabiner-DriverKit-VirtualHIDDevice-x.x.x.pkg
. -
Install files via installer.
-
Execute the following command in Terminal.
/Applications/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager activate
-
Run Karabiner-VirtualHIDDevice-Daemon:
sudo '/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice/Applications/Karabiner-VirtualHIDDevice-Daemon.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Daemon'
-
Run a client program to test the driver extension.
git clone --depth 1 https://github.com/pqrs-org/Karabiner-DriverKit-VirtualHIDDevice.git cd Karabiner-DriverKit-VirtualHIDDevice/examples/virtual-hid-device-service-client brew install xcodegen make make run
-
Run uninstaller in Terminal.
bash '/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice/scripts/uninstall/deactivate_driver.sh' sudo bash '/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice/scripts/uninstall/remove_files.sh'
/Applications/.Karabiner-VirtualHIDDevice-Manager.app
/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice
/Library/Application Support/org.pqrs/tmp
/var/log/karabiner
To run DriverKit drivers, simply building from the code is not sufficient; proper signing is also necessary. In particular, a general developer account lacks the necessary permissions for DriverKit signing, so you need to apply to Apple for higher privileges. The primary focus of this document is on signing.
- macOS 14+
- Xcode 15+
- Command Line Tools for Xcode
- XcodeGen
To create an App ID that supports the com.apple.developer.driverkit
entitlement required for distributing DriverKit drivers, you need to apply to Apple with your developer account to obtain the necessary permissions.
Specifically, follow the instructions on Requesting Entitlements for DriverKit Development
Note: This process may take some time to be completed on Apple's side.
Create the following App IDs on the Apple Developer site.
Bundle ID | Capabilities | App Services | Additional Capabilities |
---|---|---|---|
org.pqrs.Karabiner-DriverKit-VirtualHIDDevice | --- | --- |
com.apple.developer.driverkit com.apple.developer.driverkit.family.hid.device com.apple.developer.driverkit.family.hid.eventservice com.apple.developer.driverkit.transport.hid com.apple.developer.hid.virtual.device |
org.pqrs.Karabiner-VirtualHIDDevice-Daemon | --- | --- | --- |
org.pqrs.Karabiner-VirtualHIDDevice-Manager |
System Extension |
--- | --- |
The entitlement of com.apple.developer.driverkit.userclient-access
must be applied for from Apple, and unless individually authorized, it cannot be granted to your application.
You can apply through the request form: https://developer.apple.com/contact/request/system-extension/
Profile | App ID | Entitlements |
---|---|---|
Developer ID | org.pqrs.Karabiner-DriverKit-VirtualHIDDevice | DriverKit and System Extension Template for XXXXXXXX (Developer ID) |
Developer ID | org.pqrs.Karabiner-VirtualHIDDevice-Daemon | DriverKit and System Extension Template for XXXXXXXX (Developer ID) |
Developer ID | org.pqrs.Karabiner-VirtualHIDDevice-Manager | Default |
Please ensure that com.apple.developer.driverkit.userclient-access
appears under Extended Entitlements when you select DriverKit and System Extension Template
in Entitlements.
|
- src/Daemon/Developer_ID_KarabinerVirtualHIDDeviceDaemon.provisionprofile
- src/DriverKit/Developer_ID_KarabinerDriverKitVirtualHIDDevice.provisionprofile
- src/Manager/Developer_ID_KarabinerVirtualHIDDeviceManager.provisionprofile
Search G43BCU2T37
and replace them with your team identifier.
git grep G43BCU2T37 src/
The rest of the operations will be performed in the terminal.
Set the following environment variables for application signing and package signing.
PQRS_ORG_CODE_SIGN_IDENTITY
PQRS_ORG_INSTALLER_CODE_SIGN_IDENTITY
You can determine the values using the following methods:
Find the value for PQRS_ORG_CODE_SIGN_IDENTITY
:
security find-identity -p codesigning -v | grep 'Developer ID Application'
2) BD3B995B69EBA8FC153B167F063079D19CCC2834 "Developer ID Application: Fumihiko Takayama (G43BCU2T37)"
Then, set PQRS_ORG_CODE_SIGN_IDENTITY
export PQRS_ORG_CODE_SIGN_IDENTITY=BD3B995B69EBA8FC153B167F063079D19CCC2834
Find the value for PQRS_ORG_INSTALLER_CODE_SIGN_IDENTITY
:
security find-identity -p basic -v | grep 'Developer ID Installer'
1) C3107C61DB3605DA2D4549054B225DAFB1D6FA2D "Developer ID Installer: Fumihiko Takayama (G43BCU2T37)"
Then, set PQRS_ORG_INSTALLER_CODE_SIGN_IDENTITY
export PQRS_ORG_INSTALLER_CODE_SIGN_IDENTITY=C3107C61DB3605DA2D4549054B225DAFB1D6FA2D
make package
dist/Karabiner-DriverKit-VirtualHIDDevice-X.X.X.pkg
will be generated.
Create App-Specific Passwords on https://appleid.apple.com.
- name:
pqrs.org notarization
Execute store-credentials
xcrun notarytool store-credentials --apple-id tekezo@pqrs.org --team-id G43BCU2T37
Profile name:
> pqrs.org notarization
App-specific password for tekezo@pqrs.org:
> The password you created earlier
Then, notarize the package:
make notarize
Karabiner-DriverKit-VirtualHIDDevice consists the following components.
- Extension Manager (including DriverKit driver)
/Applications/.Karabiner-VirtualHIDDevice-Manager.app
- It provides a command line interface to activate or deactivate DriverKit driver.
- Karabiner-VirtualHIDDevice-Daemon
/Library/Application Support/org.pqrs/Karabiner-DriverKit-VirtualHIDDevice/Applications/Karabiner-VirtualHIDDevice-Daemon.app
- It mediates between the client app and the driver.
- It allows apps to communicate with the virtual device even if the app is not signed with pqrs.org's code signing identity. (The client app must be running with root privileges.)
- Client apps
- Client apps are not included in the distributed package.
- For example, you can build the client app from
examples/virtual-hid-device-service-client
in this repository. - Client apps can send input events by communicating with Karabiner-VirtualHIDDevice-Daemon via UNIX domain socket.
(
/Library/Application Support/org.pqrs/tmp/rootonly/vhidd_server/*.sock
)
Version is defined in version.json
.
package_version
:- Karabiner-DriverKit-VirtualHIDDevice package version.
- Increment this when any components are updated.
driver_version
:- DriverKit driver internal version.
- Increment this when the driver source code is updated.
client_protocol_version
:- The version for communication between Karabiner-VirtualHIDDevice-Daemon and the DriverKit driver.
- Increment this when the communication specifications are changed.
Karabiner-VirtualHIDDevice-Daemon requires high responsiveness, so it is recommended to run it via launchd with the ProcessType: Interactive
specified.
There is an example application for registration with launchd in examples/SMAppServiceExample
, which you can refer to for registering with launchd.