-
-
Save morkev/3f08cf45f38610565455bf48190b1b7e to your computer and use it in GitHub Desktop.
| #!/bin/bash | |
| # ============================================================================== | |
| # KEYCHRON LINUX FIX FOR HID DEVICE C0NNECTED [K] | |
| # Author: morkev | |
| # | |
| # Contributors: | |
| # - SIMULATAN: Fixed dongle interference by filtering out "Link" devices. | |
| # - karoltheguy: Added SELinux context reset (restorecon) to prevent silent blocks. | |
| # - wanjas: Verified 'input' group addition is required for distros like Pop_OS. | |
| # - Veliion: simplifying the script for multiple devices (mice, dongles) at once. | |
| # | |
| # INSTRUCTIONS | |
| # | |
| # Step 1: Open your terminal and create the file: | |
| # nano fix-keychron.sh | |
| # | |
| # Step 2: Paste this entire script into the nano editor. | |
| # | |
| # Step 3: Save and Exit nano | |
| # Press Ctrl + O to save. | |
| # Press Enter to confirm. | |
| # Press Ctrl + X to exit. | |
| # | |
| # Step 4: Make executable and run | |
| # chmod +x fix-keychron.sh | |
| # sudo ./fix-keychron.sh | |
| # ============================================================================== | |
| # --- 1. QUICK CHECK --- | |
| if [ "$EUID" -ne 0 ]; then | |
| echo "Please run this script with sudo: sudo ./fix-keychron.sh" | |
| exit 1 | |
| fi | |
| # --- 2. SETUP VARIABLES --- | |
| REAL_USER=${SUDO_USER:-$USER} | |
| USER_GROUP=$(id -gn "$REAL_USER") | |
| RULE_FILE="/etc/udev/rules.d/99-keychron.rules" | |
| # --- 3. FIND KEYCHRON VENDOR ID --- | |
| echo "Looking for Keychron devices..." | |
| # Grab the first Keychron device found to extract the Vendor ID. | |
| # Since we now ignore $PRODUCT_ID, it doesn't matter if it grabs the keyboard or the dongle first. | |
| KEYCHRON_INFO=$(lsusb | grep -i "Keychron" | head -n 1) | |
| if [ -z "$KEYCHRON_INFO" ]; then | |
| echo "No Keychron device detected. Please ensure it is plugged in via USB." | |
| exit 1 | |
| fi | |
| echo "Found: $KEYCHRON_INFO" | |
| # Extract the Vendor ID | |
| VENDOR_ID=$(echo "$KEYCHRON_INFO" | awk '{print $6}' | cut -d':' -f1) | |
| echo "Authorizing Keychron Vendor ID: $VENDOR_ID" | |
| # --- 4. APPLY UDEV RULES --- | |
| echo "Creating udev rule at $RULE_FILE..." | |
| # Write the rule dynamically based ONLY on Vendor ID. | |
| # This ensures mice, keyboards, and dongles all work with one rule. | |
| cat <<EOF > "$RULE_FILE" | |
| # Keychron Keyboard/Mouse udev rule for VIA / Keychron Launcher | |
| KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="$VENDOR_ID", MODE="0660", GROUP="$USER_GROUP", TAG+="uaccess", TAG+="udev-acl" | |
| EOF | |
| # Reset SELinux context (if applicable) | |
| if command -v restorecon &> /dev/null; then | |
| echo "Resetting SELinux context for the udev rule..." | |
| restorecon -v "$RULE_FILE" | |
| fi | |
| echo "Reloading udev rules..." | |
| udevadm control --reload-rules | |
| udevadm trigger | |
| # --- 5. PERMISSIONS --- | |
| echo "Adding $REAL_USER to the 'input' group..." | |
| usermod -aG input "$REAL_USER" | |
| # --- 6. WRAP UP --- | |
| echo "Done! ALL your Keychron devices should now be accessible." | |
| echo "IMPORTANT: Please unplug your device(s) and plug them back in for the changes to take full effect." |
Hey, @SIMULATAN! Glad it was a bit helpful, I added your thinking process to the Revision#3 of the script, so it can help future users. Thanks for sharing :)
I can't fully explain why for after trying multiple things and got to your script, it only worked once I did
sudo restorecon -v /etc/udev/rules.d/99-keychron.rules
to reset SELinux so it doesn't silently block it.
Interesting! I will go ahead and add some exception handling for this tomorrow @karoltheguy
Thank you! Worked for me on Pop_OS 22.04.
The following part of the script made a difference for me. Just having /etc/udev/rules.d/99-keychron.rules wasn't working in my case.
echo "Adding $REAL_USER to the 'input' group..."
usermod -aG input "$REAL_USER"
Hey @SIMULATAN @karoltheguy @wanjas, thanks so much for the feedback! I've just updated the script based on all your suggestions. I've also added you all to the contributor credits at the top of the script.
Thanks for your work. I can confirm that this worked for me on CachyOS.
So, I changed
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="$VENDOR_ID", ATTRS{idProduct}=="$PRODUCT_ID", MODE="0660", GROUP="$USER_GROUP", TAG+="uaccess", TAG+="udev-acl"
to
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="$VENDOR_ID", MODE="0660", GROUP="$USER_GROUP", TAG+="uaccess", TAG+="udev-acl"
since I also have a Keychron M6 mouse, which can connect via a dongle (one of the "Ultra-Link" devices). This also allows all my Keychron devices to work with this one udev rule. I am not sure if this is the most secure thing as my knowledge is limited.
Worked!
thank you so much!
thank you, it fixed my K1 version 6 on cachyos
So, I changed
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="$VENDOR_ID", ATTRS{idProduct}=="$PRODUCT_ID", MODE="0660", GROUP="$USER_GROUP", TAG+="uaccess", TAG+="udev-acl"to
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="$VENDOR_ID", MODE="0660", GROUP="$USER_GROUP", TAG+="uaccess", TAG+="udev-acl"since I also have a Keychron M6 mouse, which can connect via a dongle (one of the "Ultra-Link" devices). This also allows all my Keychron devices to work with this one udev rule. I am not sure if this is the most secure thing as my knowledge is limited.
![]()
@Veliion that is actually a pretty good point, yeah instead of just giving permissions to the keyboard you’re giving permissions to any Keychron device. I will remove that rule for users with more Keychron devices, will make sure to give you credit. Revision #5 reflects this change to the $PRODUCT_ID rule
Happy to read your comments, guys! Glad the script was useful :) Have a nice Friday everyone
Thank you so much for this!
worke for me on Cachyos using Helium browser. thanks!

Thank you! One major problem I encountered is that my system also had some weird Keychron Link device:
Due to the
head -1call, the udev rule used that link device's product id, which did not fix the Launcher connection error.To address this bug, I added a
grep -vi "Link"into the pipeline before thehead -n 1.After doing that, I successfully got the Launcher to work.
EDIT: the "Keychron Link" device is actually the 2.4 GHz Dongle