This project has the “shajra” keyboard mappings for four ergonomic split keyboards:
- Keyboardio’s Model 100, programmed with Kaleidoscope firmware
- Keyboardio’s Model 01 (discontinued), also programmed with Kaleidoscope
- ZSA Technology Labs’ Moonlander, programmed with QMK firmware
- ZSA Technology Labs’ Ergodox EZ, also programmed with QMK.
Beyond the keymap, this project offers some streamlined automation with Nix that you can use for your own keymap. Or you can use this automation to return your keyboard to its factory default.
This automation only works for GNU/Linux (not MacOS or Windows). If you’re new to Nix, this project bundles a few guides to get you started:
- Introduction to Nix and motivations to use it
- Nix installation and configuration guide
- Nix end user guide
- Introduction to the Nix programming language
The rest of this document discusses using this automation. To get the most out of the keymap itself, you may be interested in the design document explaining the motivation behind the mapping.
The “shajra” keymaps for all four keyboards are highly similar, which works out well because the physical layouts of these keyboards are also similar. We can more easily switch from one keyboard to another and retain the design benefits of the mapping.
Note the Moonlander keyboard is an almost identical layout to the EZ and not illustrated here. The Moonlander has only two fewer keys on the thumb cluster. This leads to not having either Home or End on the base layer for the Moonlander (they are still in a function layer). And the “application menu” keycodes are moved to the bottom-outer corners.
This project only supports a GNU/Linux operating system (sorry, not MacOS or Windows) with the Nix package manager installed.
QMK and Kaleidoscope have build complexities and dependencies that can take a moment to work through. Nix can automate this hassle away by downloading and setting up all the necessary third-party dependencies in a way that
- is highly reproducible
- won’t conflict with your current system/configuration.
Using Nix, we won’t have to worry about downloading QMK or Kaleidoscope, ensuring we have the correct versions of build tools like Arduino, without messing with Git submodules or setting up environment variables. Nix does all this for us. The provided scripts simplify using Nix even further.
The following steps will get your keyboard flashed.
If you don’t have Nix installed and configured on your system, follow the instructions provided. As discussed, setting up Cachix and enabling the experimental flakes feature are both recommended.
To program either keyboard with a new mapping, you need to augment your OS configuration with new udev rules.
The following are recommended rules for each keyboard:
# For Ergodox EZ ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1" ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1" SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", TAG+="uaccess" KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", TAG+="uaccess" # For Moonlander SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", \ TAG+="uaccess", SYMLINK+="stm32_dfu" # For Model 100 SUBSYSTEMS=="usb", ATTRS{idVendor}=="3496", ATTRS{idProduct}=="0005", \ SYMLINK+="model100", ENV{ID_MM_DEVICE_IGNORE}:="1", \ ENV{ID_MM_CANDIDATE}:="0", MODE="0666", TAG+="uaccess", TAG+="seat" SUBSYSTEMS=="usb", ATTRS{idVendor}=="3496", ATTRS{idProduct}=="0006", \ SYMLINK+="model100", ENV{ID_MM_DEVICE_IGNORE}:="1", \ ENV{ID_MM_CANDIDATE}:="0", MODE="0666", TAG+="uaccess", TAG+="seat" # For Model 01 SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="2300", \ SYMLINK+="model01", ENV{ID_MM_DEVICE_IGNORE}:="1", \ ENV{ID_MM_CANDIDATE}:="0", MODE="0666", TAG+="uaccess", TAG+="seat" SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="2301", \ SYMLINK+="model01", ENV{ID_MM_DEVICE_IGNORE}:="1", \ ENV{ID_MM_CANDIDATE}:="0", MODE="0666", TAG+="uaccess", TAG+="seat"
These settings should roughly correspond to the official documentation of tools and libraries used by this project:
- QMK documentation for configuring Halfkey bootloader used by the Ergodox EZ
- Teensy CLI documentation, used internally for flashing the Ergodox EZ
- Wally CLI, used internally for flashing the Moonlander
- Kaleidoscope documentation
Note, if the MODE="0666"
settings above are not set, you may require
root-privileges (sudo) to call the flashing scripts.
Each distribution is different, but on many GNU/Linux systems, udev rules are
put in a file in /etc/udev/rules.d
with a “.rules” extension.
On some systems, you can activate these rules with the following commands:
udevadm control --reload-rules udevadm trigger
Or just restart the computer.
/NOTE:/ You don’t need this step if you’re flashing the Ergodox EZ or Moonlander.
Once udev is configured, when you plug in the Keyboardio Model 01, a serial
device should appear under /dev/serial/by-id
with a name matching
“usb-Keyboardio_Model_01_*”. This human-readable symlink pointing to the device
should be something like /dev/ttyACM0
. On many systems, this device is
group-owned by the “dialout” or the “uucp” group:
In the following example, we can see the device is group-owned by the “dialout” group.
ls -lL /dev/serial/by-id/usb-Keyboardio_Model_01_*
crw-rw---- 1 root dialout 166, 0 Dec 28 20:09 /dev/serial/by-id/usb-Keyboardio_Model_01_Ckbio01E-if00
On most distributions, the following commands should work to join a group
(substituting $TTY_GROUP
and $USERNAME
):
sudo usermod -a -G $TTY_GROUP $USERNAME
newgrp $TTY_GROUP
You should see memberships in the new group with the groups
command:
groups | grep dialout
users wheel video dialout docker
Unplug your keyboard and plug it back in to ensure everything’s set to program. Rebooting your computer is probably overkill, but would probably work too.
This project provides four scripts:
flash-ergodoxez
flash-model01
flash-model100
flash-moonlander
Calling these scripts without arguments will flash your respective keyboard with the “shajra” keymap. There is a “–factory” switch to flash your keyboard back to a factory default keymap.
If you enabled flakes in your Nix installation, you can run these scripts
without installing them. Here’s an invocation illustrating doing so with
flash-ergodoxez
:
nix run github:shajra/shajra-keyboards#flash-ergodoxez
Flashing ZSA Technology Lab's Ergodox EZ (custom "shajra" keymap) ================================================================= FLASH SOURCE: /nix/store/6v8v2avkkh72v010z4p2cbnl97zxnr85-qmk-builtin-shajra-src FLASH BINARY: /nix/store/afq0r8v9fir53rayfyd0w7ryy7vqxzmn-ergodoxez-builtin-shajra.hex ⠋ Press the reset button of your keyboard
The same works for the other three flashing scripts. Just replace “flash-ergodoxez” in the invocation above with the script of your choice.
Alternatively, the four flashing scripts are provided at the root of this project. Just clone this repository, and you can call them directly:
cd $SOME_WORKING_DIR
clone https://github.com/shajra/shajra-keyboards.git
cd shajra-keyboards
./flash-ergodoxez
Note that the first time you run the commands described below, you’ll see Nix doing a lot of downloading and compiling. After that, subsequent invocations should be quicker with less output.
When flashing with flash-ergodoxez
, you will be prompted to press a reset
button. Access this button with an unbent paperclip inserted into the small
hole in the top right corner of the right keyboard half.
When flashing with flash-ergodoxez
, you will be prompted to press a reset
button. Access this button with an unbent paperclip inserted into the small
hole in the top left corner of the left keyboard half.
When flashing with flash-model100
or flash-model01
, you will be prompted
with instructions to hold down the Prog
key, and then press Enter
.
The Prog
key is hardwired to be the top-left-most key of the Keyboardio Model
01, but the Enter
key can be remapped. If you forget where the Enter
has
been mapped to on your Keyboard, you can hit Enter
on another connected
keyboard.
This project’s scripts won’t save off your previous keymap from your keyboard. But we can revert to the OEM keymap that your keyboard shipped with.
Reverting to the OEM keymap can be done with the -F
/ --factory
switch,
which all the flashing scripts support. If you forget your options, these
scripts have a -h
/ --help
switch.
The provided code is relatively compact. In the keymaps
directory, you should
find familiar files you would edit in QMK or Kaleidoscope projects,
respectively. These keymaps are compiled into the flashing scripts provided with
this project.
For both keyboards, The “shajra” keymap is in its own directory. You can make your own keymaps and put them in a sibling directory with the name of your choice, and they’ll be compiled in as well.
If you don’t want to use keymaps compiled into the flashing scripts, you can use
another directory of keymaps at runtime with the -K
/ -keymaps
switch.
Then you can use the -k
/ --keymap
switch to load your custom keymap by the
name you chose for the keymap in the “keymaps” directory. The scripts should
pick up changes, rebuild anything necessary, and flash your keyboard.
The used keymap source code is copied into /nix/store
, and the invocation of
the flashing scripts will print out a “FLASH SOURCE:” line indicating the source
used for compiling/flashing for your reference. These are the whole source trees
you’d typically use if following the QMK or Kaleidoscope documentation manually.
This project relies heavily on Nix, primarily to help deal with all the complexity of setting up dependencies. The development of this project also relies on an experimental feature of Nix called flakes, not required to use the project. See the included introduction to Nix if you’re new to Nix or flakes.
If you want to check that everything builds before flashing your keyboard, you can build locally everything built by this project’s continuous integration:
tree $(nix build --no-link --print-out-paths) 2>/dev/null
/nix/store/di223c5xf4py7n4sa7hl6ib26qzk145z-shajra-keyboards-ci ├── build-ergodoxez-builtin-shajra-flash -> /nix/store/9147p0hfcvq4gz6drfrccgqj6j2lccxd-ergodoxez-builtin-shajra-flash ├── build-ergodoxez-builtin-shajra-hex -> /nix/store/afq0r8v9fir53rayfyd0w7ryy7vqxzmn-ergodoxez-builtin-shajra.hex ├── build-ergodoxez-factory-flash -> /nix/store/m8lgz8z3lwkk5g41xcml8pmllmf55v59-ergodoxez-factory-flash ├── build-ergodoxez-factory-hex -> /nix/store/7r8rif4gaz7vmp61l5pwhnkywsvcf21q-ergodoxez-factory.hex ├── build-model01-builtin-shajra-flash -> /nix/store/9pnca6ccdcal0ppqiq98id3z26dbfi6z-model01-builtin-shajra-flash ├── build-model01-builtin-shajra-hex -> /nix/store/k2g0wj51jpwfgnzx2rg72hz0nvys7fn9-model01-builtin-shajra-hex ├── build-model01-factory-flash -> /nix/store/p9cfg2p8l2ci2zf8dqgyykiac6rlgr95-model01-factory-flash ├── build-model01-factory-hex -> /nix/store/pq26cl740hzpj5nijjigzivvsv70fsay-model01-factory-hex ├── build-model100-builtin-shajra-flash -> /nix/store/mhn1vbcldqw3jc9ckip8k7ak1w23gzna-model100-builtin-shajra-flash ├── build-model100-builtin-shajra-hex -> /nix/store/3wd9qha0janvmcl41xps6czdp3l51ass-model100-builtin-shajra-hex ├── build-model100-factory-flash -> /nix/store/5pdiqsdjgdky3xdkyalskbx5vrww6n5y-model100-factory-flash ├── build-model100-factory-hex -> /nix/store/6gcm5vra7vzpxgvslip0wq6d7gmhi2w5-model100-factory-hex ├── build-moonlander-builtin-shajra-flash -> /nix/store/zb3gw7yfvl3zpl4v155rs7jfr3c3lq10-moonlander-builtin-shajra-flash ├── build-moonlander-builtin-shajra-hex -> /nix/store/mda5f1pda5fqlxy84f86i7q1alxc9i0r-moonlander-builtin-shajra.bin ├── build-moonlander-factory-flash -> /nix/store/5kffy3qbf2kh6qzj1jymar2q7778kbk1-moonlander-factory-flash ├── build-moonlander-factory-hex -> /nix/store/h793pznk11dw6wpy723bx741lz8c8z8l-moonlander-factory.bin ├── flash-ergodoxez -> /nix/store/k7vlk0v6ggglh1l67ygssfpzl5li75y1-flash-ergodoxez ├── flash-model01 -> /nix/store/8h4kzy13zir8568lsrqkwyfmfwq2nb57-flash-model01 ├── flash-model100 -> /nix/store/v298nzzcdp381qw4hghs6hnfqkrivg6w-flash-model100 ├── flash-moonlander -> /nix/store/i6i6c68hfyqxamssj5hm9dnq1ynm7mp4-flash-moonlander └── licenses -> /nix/store/v6bnwj40fnxqrssvhjd6v10398bqyw43-shajra-keyboards-licenses 18 directories, 4 files
The “main” branch of the GitHub repository has the latest version of this code. There is currently no commitment to either forward or backward compatibility. However, the scripts for compiling/flashing are considered stable and less likely to change than the “shajra” keymap.
“user/shajra” branches are personal branches that may be force-pushed to. The “main” branch should not experience force-pushes and is recommended for general use.
This project is not a modified work in the traditional sense. It provides scripts the end user runs to make a modified work. Most of the source code modified (QMK, Kaleidoscope, and Model 01) is licensed under either GPLv2 or GPLv3.
If you have Nix installed, then a provided script licenses-thirdparty
can be
run to download all original source used, including license information.
In the spirit of the projects we build upon, all files in this “shajra-keyboards” project are licensed under the terms of GPLv3 or (at your option) any later version.
Please see the COPYING.md file for more details.
Feel free to file issues and submit pull requests with GitHub. Ideas for how to improve automation are welcome. If you have ideas on how to improve the “shajra” keymap, just make a compelling argument considering the factors that have already gone into its design.
There is only one author to date, so the following copyright covers all files in this project:
Copyright © 2019 Sukant Hajra