Fully automated setup of multiple QMK projects from scratch, incl. forks and Vial
The short version: … at scale: Multiple types (QMK, ZMK, ), different forks, different branches, different versions
Convenient development
… And yes, it takes up more disk space and initial bandwidth cost, but XXXX.
Original vs. own custom changes
Original without custom changes: Easy to change version, without being disrupted by uncommitted custom changes
Easier to compare different branches and forks. (
A naming convention
The general idea is to make it possible to XXX without having to invoke Git commands. By never having to change Git branch, this also makes it possible to avoid the confusion caused by the forced commits after making own changes.
Incl. a prefix for all QMK and ZMK clones. To be sorted near each other / easier filtering.
Original vs. own custom changes
Forks vs. original. Different branches.
Incl. naming convention for the .bin files. Date/revision. USB-side version.
Incl. naming convention for Python virtual environments.
Optional: Information about the base version, version, date, and commit ID (applies to forks in most cases, e.g, Keychron’s fork, as the forks are in general not updated to track the main project)
How it works
The “XX” parameter is used to make run unattended, with. The main QMK is last to overrides setting the default QMK (temporarily) set by the previous clones.
Python virtual environments vs. ‘uv’
TBD
The command lines
Note the branch confusion in Keychron’s fork of QMK. For example, the “2025” in “wls_2025q1” and “2025q3” represent two different things…
For:
- Keychron’s QMK fork, Git branch “wireless_playground”. Note: We roll back the version to B507EA (2025-03-25), because the 2025-05 release was incomplete (and the compiled result has never really been proven. And it broke compilation for the K Pro series and Q Pro series). But note that there were some later keyboard-only releases in the branch (‘ISO‘ and ‘JIS‘ keyboard variants): Lemokey L1 ISO, Q2 Max JIS, Q3 Max JIS, and Q6 Max JIS.
- Keychron’s QMK fork, Git branch “wls_2025q1”
- Keychron’s QMK fork, Git branch “2025q3”
- Main Vial project. It isn’t clear what the (effective release) version is, but for now we assume both the firmware part and the GUI use the same version number (currently version 0.7.5 (2025-08))
- Main QMK project, Git branch master (it is the default branch, so it is not necessary to specify, unlike for Keychron). It isn’t necessary to specify the GitHub user (“qmk”) and repository name (“qmk_firmware”) either.
Other notes:
- “-y” (or “–yes” (two ASCII dashes, not as rendered here)) to ‘qmk setup’ (e.g., from qmk setup –help (two ASCII dashes, not as rendered here)) is suppressing the two prompts. As the main QMK project is the last in the sequence, the QMK home will end up being set to the main QMK project (not that it is that important; the current directory can just first be changed to the used repository before performing compiling, etc.).
- We also encode the (effective) QMK version, so alphabetic sorting will sort by date/QMK version. That version is effectively fixed for the various branches in Keychron’s fork, but it will become out of date over time for the main QMK project (though the folder can just be renamed; it will break the QMK home, but it doesn’t really matter).
cd $HOME # Not strictly necessary; the command lines
# are independent of the current directory
# ================== Keychron: "bluetooth_playground" ==================
echo ; echo "Start QMK setup for Keychron's fork, Git branch bluetooth_playground: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/Keychron/qmk_firmware/tree/bluetooth_playground/keyboards/keychron/>
#
qmk setup --yes -H $HOME/Keyboard_firmware_QMK_2022-11_0.19_Keychron_fork_bluetooth_playground -b bluetooth_playground Keychron/qmk_firmware
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_QMK_2022-11_0.19_Keychron_fork_bluetooth_playground status
git -C $HOME/Keyboard_firmware_QMK_2022-11_0.19_Keychron_fork_bluetooth_playground log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_QMK_2022-11_0.19_Keychron_fork_bluetooth_playground -type f | wc -l
find $HOME/Keyboard_firmware_QMK_2022-11_0.19_Keychron_fork_bluetooth_playground -type d | wc -l
find $HOME/Keyboard_firmware_QMK_2022-11_0.19_Keychron_fork_bluetooth_playground | wc -l
echo ; echo "End QMK setup for Keychron's fork, Git branch bluetooth_playground: $(date +%FT%T_%N_ns)" ; echo
# ================== Keychron: "wireless_playground" ==================
echo ; echo "Start QMK setup for Keychron's fork, Git branch wireless_playground: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/Keychron/qmk_firmware/tree/wireless_playground/keyboards/keychron/>
#
qmk setup --yes -H $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground -b wireless_playground Keychron/qmk_firmware
# Roll back to the 2025-03-25 version (before the partial source code release, that also broke compilation, at least for some K Pro series keyboards):
cd $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground
git checkout B507EA # 2025-03-25 (the latest before the two 2025-05-30 commits)
git submodule update --init --recursive
cd $HOME
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground status
git -C $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground -type f | wc -l
find $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground -type d | wc -l
find $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_wireless_playground | wc -l
echo ; echo "End QMK setup for Keychron's fork, Git branch wireless_playground: $(date +%FT%T_%N_ns)" ; echo
# ================== Keychron: "wls_2025q1" ==================
echo ; echo "Start QMK setup for Keychron's fork, Git branch wls_2025q1: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/Keychron/qmk_firmware/tree/wls_2025q1/keyboards/keychron/>
#
qmk setup --yes -H $HOME/Keyboard_firmware_QMK_2025-02_0.28_Keychron_fork_wls_2025q1 -b wls_2025q1 Keychron/qmk_firmware
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_QMK_2025-02_0.28_Keychron_fork_wls_2025q1 status
git -C $HOME/Keyboard_firmware_QMK_2025-02_0.28_Keychron_fork_wls_2025q1 log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_QMK_2025-02_0.28_Keychron_fork_wls_2025q1 -type f | wc -l
find $HOME/Keyboard_firmware_QMK_2025-02_0.28_Keychron_fork_wls_2025q1 -type d | wc -l
find $HOME/Keyboard_firmware_QMK_2025-02_0.28_Keychron_fork_wls_2025q1 | wc -l
echo ; echo "End QMK setup for Keychron's fork, Git branch wls_2025q1: $(date +%FT%T_%N_ns)" ; echo
# ================== Keychron: "hall_effect_playground" ==================
echo ; echo "Start QMK setup for Keychron's fork, Git branch hall_effect_playground: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/Keychron/qmk_firmware/tree/hall_effect_playground/keyboards/keychron/>
#
qmk setup --yes -H $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_hall_effect_playground -b hall_effect_playground Keychron/qmk_firmware
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_hall_effect_playground status
git -C $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_hall_effect_playground log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_hall_effect_playground -type f | wc -l
find $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_hall_effect_playground -type d | wc -l
find $HOME/Keyboard_firmware_QMK_2023-11_0.23_Keychron_fork_hall_effect_playground | wc -l
echo ; echo "End QMK setup for Keychron's fork, Git branch hall_effect_playground: $(date +%FT%T_%N_ns)" ; echo
# ================== Keychron: "2025q3" ==================
echo ; echo "Start QMK setup for Keychron's fork, Git branch 2025q3: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/Keychron/qmk_firmware/tree/2025q3/keyboards/keychron/>
#
qmk setup --yes -H $HOME/Keyboard_firmware_QMK_2025-08_0.30_Keychron_fork_2025q3 -b 2025q3 Keychron/qmk_firmware
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_QMK_2025-08_0.30_Keychron_fork_2025q3 status
git -C $HOME/Keyboard_firmware_QMK_2025-08_0.30_Keychron_fork_2025q3 log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_QMK_2025-08_0.30_Keychron_fork_2025q3 -type f | wc -l
find $HOME/Keyboard_firmware_QMK_2025-08_0.30_Keychron_fork_2025q3 -type d | wc -l
find $HOME/Keyboard_firmware_QMK_2025-08_0.30_Keychron_fork_2025q3 | wc -l
echo ; echo "End QMK setup for Keychron's fork, Git branch 2025q3: $(date +%FT%T_%N_ns)" ; echo
# ================== Main Vial project ==================
echo ; echo "Start QMK setup for the main Vial project: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/vial-kb/vial-qmk/tree/vial/keyboards/keychron>
#
# We are treating Vial as just another QMK fork:
#
# * Git branch = "vial"
# * GitHub user = "vial-kb"
# * GitHub repository (for that user) = "vial-qmk"
#
qmk setup --yes -H $HOME/Keyboard_firmware_Vial_2025-08_0.7.5_main -b vial vial-kb/vial-qmk
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_Vial_2025-08_0.7.5_main status
git -C $HOME/Keyboard_firmware_Vial_2025-08_0.7.5_main log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_Vial_2025-08_0.7.5_main -type f | wc -l
find $HOME/Keyboard_firmware_Vial_2025-08_0.7.5_main -type d | wc -l
find $HOME/Keyboard_firmware_Vial_2025-08_0.7.5_main | wc -l
echo ; echo "End QMK setup for the main Vial project: $(date +%FT%T_%N_ns)" ; echo
# ================== Main QMK project ==================
echo ; echo "Start QMK setup for the main QMK project: $(date +%FT%T_%N_ns)" ; echo
#
# <https://github.com/qmk/qmk_firmware/tree/master/keyboards/keychron>
#
# We do ***not*** need to specify these (all defaults):
#
# * Git branch
# * GitHub user
# * GitHub repository (for that user)
#
qmk setup --yes -H $HOME/Keyboard_firmware_QMK_2026-05_0.33_main
# Confirm (current Git branch and current version):
git -C $HOME/Keyboard_firmware_QMK_2026-05_0.33_main status
git -C $HOME/Keyboard_firmware_QMK_2026-05_0.33_main log -3
# Statistics (number of files, number of folders, and
# the sum of the two, respectively)
find $HOME/Keyboard_firmware_QMK_2026-05_0.33_main -type f | wc -l
find $HOME/Keyboard_firmware_QMK_2026-05_0.33_main -type d | wc -l
find $HOME/Keyboard_firmware_QMK_2026-05_0.33_main | wc -l
echo ; echo "End QMK setup for the main QMK project: $(date +%FT%T_%N_ns)" ; echo
ls -lsa $HOME | grep Keyboard_firmware
# The end...
For example, for “wls_2025q1”, on my system it took about 5 minutes. The result is about 1.8 GB (old unit) disk space for about 24,000 files in about 6,500 folders. The download size is about 0.9 GB.
References
- Sample instructions for setting up for Git branch ‘wls_2025q1’ in Keychron’s fork
Appendix A: ‘qmk setup’ information
There isn’t a man page for the command line qmk setup, but there is a help option (slightly edited and formatted for clarity):
qmk setup --help
Output:
Usage: qmk setup [-h] [-H HOME] [-b BRANCH] [--baseurl BASEURL] [-y] [-n] [fork]
Positional arguments:
fork The QMK firmware fork to clone.
Default: qmk/qmk_firmware
Options:
-h, --help Show this help message and exit
-H, --home HOME The location for QMK Firmware.
Default: /home/embo/qmk_firmware
-b, --branch BRANCH The branch to clone. Default: master
--baseurl BASEURL The URL all Git operations start from.
Default: https://github.com
-y, --yes Answer yes to all questions
-n, --no Answer no to all questions
Keychron B6 Pro Ultra-Slim Wireless Keyboard ISO Layout Collection
Leave a Reply