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:

  1. “-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.).
  2. 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

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

Forward reference.

Leave a Reply

Your email address will not be published. Required fields are marked *

*