{"id":6606,"date":"2026-07-13T15:40:35","date_gmt":"2026-07-13T14:40:35","guid":{"rendered":"https:\/\/pmortensen.eu\/world2\/?p=6606"},"modified":"2026-10-27T01:42:34","modified_gmt":"2026-10-27T00:42:34","slug":"the-zmk-based-keychron-keyboards-for-example-v6-ultra-8k-work-with-via","status":"publish","type":"post","link":"https:\/\/pmortensen.eu\/world2\/2026\/07\/13\/the-zmk-based-keychron-keyboards-for-example-v6-ultra-8k-work-with-via\/","title":{"rendered":"The ZMK-based Keychron keyboards, for example, V6 Ultra 8K, work with Via!"},"content":{"rendered":"<p><!-- T H E   B E G I N N I N G . . .   Marker for editing in WordPress: qqqq --><\/p>\n<p>The short version: By changing the <a href=\"https:\/\/www.oshwa.org\/2013\/11\/19\/new-faq-on-usb-vendor-id-and-product-id\/\">USB product ID<\/a> in a <a href=\"https:\/\/en.wikipedia.org\/wiki\/JSON\">JSON<\/a> file for a similar keyboard, to that, for example, of a Keychron <a href=\"https:\/\/www.keychron.com\/products\/keychron-v6-ultra-8k-wireless-custom-mechanical-keyboard\">V6&nbsp;Ultra&nbsp;8K<\/a> &#8216;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Keyboard_layout#Physical_layouts\">ISO<\/a>&#8216;, it is possible to change keymappings, record macros, and execute macros from <a href=\"https:\/\/docs.keeb.io\/via\">Via<\/a> for a <a href=\"https:\/\/github.com\/zmkfirmware\/zmk\">ZMK<\/a>-based Keychron keyboard, including using the so-called <a href=\"https:\/\/pmortensen.eu\/world2\/2023\/06\/12\/via-a-mechanical-qmk-keyboard-configuration-works-just-fine-without-google-chrome\/\">standalone version of Via<\/a>!<\/p>\n<p>The underlying reason is that Keychron has implemented the Via protocol for their <a href=\"https:\/\/github.com\/zmkfirmware\/zmk\">ZMK<\/a>-based keyboards.<\/p>\n<h2>Base change: USB identity<\/h2>\n<p>Example: Start JSON file: For <a href=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0059\/0630\/1017\/files\/v6_max_iso_encoder_v1.0.0_2404091021.json.zip\">V6 Max &#8216;ISO&#8217; knob<\/a> (from <a href=\"https:\/\/www.keychron.com\/pages\/firmware-and-json-files-of-the-keychron-qmk-v-and-v-max-series-keyboards\">this page<\/a>). It has the exact same physical key layout as the V6&nbsp;Ultra&nbsp;8K&nbsp;&#8216;ISO&#8217;.<\/p>\n<p>The first three lines:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n    &quot;name&quot;: &quot;Keychron V6 Max ISO Knob&quot;,\r\n    &quot;vendorId&quot;: &quot;0x3434&quot;,\r\n    &quot;productId&quot;: &quot;0x0961&quot;,\r\n<\/pre>\n<p>The USB product ID for V6&nbsp;Ultra&nbsp;8K &#8216;ISO&#8217; is 0x0C61 (it can, for example, <a href=\"https:\/\/www.reddit.com\/r\/Keychron\/comments\/1qsx84d\/comment\/o2zfi5z\/\">be found in<\/a> the operating system somewhere). Thus, change it and the name, to:<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n    &quot;name&quot;: &quot;Keychron V6 Ultra 8K ISO&quot;,\r\n    &quot;vendorId&quot;: &quot;0x3434&quot;,\r\n    &quot;productId&quot;: &quot;0x0C61&quot;,\r\n<\/pre>\n<h2>JSON files blues<\/h2>\n<p>But it isn&#8217;t sufficient. Even for a keyboard with the exact same physical key layout, there are differences, which must be expressed in the JSON file.<\/p>\n<h2 id=\"Shifted_keys\">ZMK blues<\/h2>\n<p>Compared to a QMK-based keyboard, there is a shift in some key positions, e.g., for the four extra keys above the numeric keypad.<\/p>\n<p>Example 1: If a key is mapped (in Via) to the first in that group of four (according to the V6 JSON file\/QMK keymap), activation requires to use the key two to the right, the third key in that group of four&#8230;<\/p>\n<p>Example 2: If a key is mapped to the fourth (last) in that group of four (according to the V6 JSON file\/QMK keymap), activation requires to use <strong><em>key 6 on the numpad<\/em><\/strong>(!) It is far away from anything that could be explained by a simple shift in the key order (the two keys are swapped).<\/p>\n<p>In fact, <strong><em>all<\/em><\/strong> of the four extra keys above the numeric keypad are in different positions. For the 1st, 2nd, and 4th, they are mapped (using that JSON file) to keys on the numeric keypad, &#8220;*&#8221;, &#8220;-&#8220;, and &#8220;6&#8221;, respectively.<\/p>\n<p>Also, some of the keys on the numeric keypad are also shuffled around.<\/p>\n<p>Perhaps it is due to a keyboard firmware bug? That was tested with <a href=\"https:\/\/launcher.keychron.com\/vapi\/v2\/firmware\/875826273\">version 1.0.1<\/a>\/2025-11-28 (other notations are &#8220;1.01&#8221; and &#8220;1.1&#8221;) of the V6 Ultra 8K &#8216;ISO&#8217; keyboard firmware. There is currently a version 1.0.2, but I haven&#8217;t tested it yet.<\/p>\n<p><Is there the same problem in the Via clone? Does the firmware update for the V6 Ultra 8K fix it?><\/p>\n<h2 id=\"Keychron_is_inconsistent\">JSON files blues<\/h2>\n<p>Order of keys: Vertical keys:<\/p>\n<ol>\n<li><strong><em>Enter<\/em><\/strong> key (&#8216;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Keyboard_layout#Physical_layouts\">ISO<\/a>&#8216; only)<\/li>\n<li><strong><em>+<\/em><\/strong> key (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Numeric_keypad\">numeric keypad<\/a>)<\/li>\n<li><strong><em>Enter<\/em><\/strong> key (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Numeric_keypad\">numeric keypad<\/a>)<\/li>\n<\/ol>\n<p>There isn&#8217;t <strong><em>any<\/em><\/strong> consistency between Keychron keyboards if a vertical key belongs to the upper or lower row when it comes to the <strong><em>key order<\/em><\/strong>. Thus, the original JSON file may not reflect the actual key order for the &#8216;Ultra&#8217; keyboard. Or in other words, it is easiest to choose a JSON file to clone and change that has the same key order.<\/p>\n<style>\n    #someTable .rightAlign {text-align: right;}\n<\/style>\n<table id=\"someTable\">\n<tr>\n<th>Keyboard<\/th>\n<th>Key <strong><em>Enter<\/em><\/strong><\/br>(main)<\/th>\n<th>Key <strong><em>+<\/em><\/strong><\/br>(numeric<\/br>keypad)<\/th>\n<th>Key <strong><em>Enter<\/em><\/strong><\/br>(numeric<\/br>keypad)<\/th>\n<\/tr>\n<p>    <!-- Template\n    \n\n<tr> \n\n<td>XXX<\/td>\n\n \n\n<td>111<\/td>\n\n \n\n<td>222<\/td>\n\n \n\n<td>333<\/td>\n\n <\/tr>\n\n\n    --><\/p>\n<tr>\n<td>V6 &#8216;ISO&#8217;<\/td>\n<td>Lower<\/td>\n<td>Upper<\/td>\n<td>Upper<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/Keychron\/qmk_firmware\/blob\/wls_2025q1\/keyboards\/keychron\/v6_max\/iso_encoder\/keymaps\/via\/keymap.c#L45\">V6 Max &#8216;ISO&#8217;<\/a><\/td>\n<td>Lower<\/td>\n<td>Lower<\/td>\n<td>Lower<\/td>\n<\/tr>\n<tr>\n<td>V6 Ultra 8K &#8216;ANSI&#8217;<\/td>\n<td>&#8211;<\/td>\n<td>Lower<\/td>\n<td>Lower<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/Keychron\/zmk\/blob\/rtl8762g\/app\/boards\/shields\/keychron_v6_ultra_iso\/keychron_v6_ultra_iso.keymap#L251\">V6 Ultra 8K &#8216;ISO&#8217;<\/a><\/td>\n<td>Upper<\/td>\n<td>Lower<\/td>\n<td>Lower<\/td>\n<\/tr>\n<\/table>\n<p>Thus, if using the V6 Max &#8216;ISO&#8217; JSON file as the basis and not corrected for, some keys would be shifted by one, starting with keys after the Enter key (on the main keyboard). This problem would <strong><em>show itself when changing keymappings<\/em><\/strong>; the keymapping (for some keys) would change for another key than the intended.<\/p>\n<p>Note that this discrepancy will not show up in the Via key tester, as it uses key codes, not the key order.<\/p>\n<h2 id=\"knob_blues\">Rotary knob blues<\/h2>\n<p>The rotary knob does not seem to be supported, at least with the tested firmware version 1.0.1 of the V6 Ultra 8K &#8216;ISO&#8217;.<\/p>\n<p>Another selection criterion for the starting JSON file is a rotary knob for the keyboard (and variant), but the V6 Max does have a rotary knob (and is thus represented in the JSON file).<\/p>\n<p><!--\nFuture:\n\n\n<h2>Does it work for the B Pro series?<\/h2>\n\n\n\n--><\/p>\n<h2>References<\/h2>\n<ol>\n<li><a href=\"https:\/\/www.keychron.com\/pages\/firmware-and-json-files-of-the-keychron-qmk-v-and-v-max-series-keyboards\">V6 JSON files<\/a> for <a href=\"https:\/\/docs.keeb.io\/via\">Via<\/a>. Near <em>&#8220;V6 knob version ISO keymap&#8221;<\/em>. E.g., <a href=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0059\/0630\/1017\/files\/v6_max_iso_encoder_v1.0.0_2404091021.json.zip\">v6_max_iso_encoder_v1.0.0_2404091021.json<\/a> and <a href=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0059\/0630\/1017\/files\/v6_us_knob_v1.3.json.zip\">v6_us_knob_v1.3.json.zip<\/a>. Note: The JSON section should not be confused with the firmware section. As of 2026-07-13, it does not include the JSON files for V6 V2 (which is <a href=\"https:\/\/www.reddit.com\/r\/Keychron\/comments\/1sxl3v0\/comment\/oiny32m\/\">based on another microcontroller<\/a>).<\/li>\n<li><a href=\"https:\/\/github.com\/Keychron\/zmk\/blob\/rtl8762g\/app\/boards\/shields\/keychron_v6_ultra_ansi\/keychron_v6_ultra_ansi.keymap#L238\">V6 Ultra 8K default keymap<\/a> (&#8216;ANSI&#8217;)<\/li>\n<li><a href=\"https:\/\/github.com\/Keychron\/qmk_firmware\/blob\/wireless_playground\/keyboards\/keychron\/v6_max\/iso_encoder\/keymaps\/via\/keymap.c#L43\">V6 Max default keymap<\/a> (&#8216;ISO&#8217;)<\/li>\n<li><a href=\"https:\/\/github.com\/the-via\/app\/issues\/57\">Via integration with ZMK #57<\/a>. 2022-10-28. Mostly about licensing issues related to an implementation.<\/li>\n<\/ol>\n<p><!-- T H E   E N D . . .   Marker for editing in WordPress: pppp --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The short version: By changing the USB product ID in a JSON file for a similar keyboard, to that, for example, of a Keychron V6&nbsp;Ultra&nbsp;8K &#8216;ISO&#8216;, it is possible to change keymappings, record macros, and execute macros from Via for &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"more-link\" href=\"https:\/\/pmortensen.eu\/world2\/2026\/07\/13\/the-zmk-based-keychron-keyboards-for-example-v6-ultra-8k-work-with-via\/\"> <span class=\"screen-reader-text\">The ZMK-based Keychron keyboards, for example, V6 Ultra 8K, work with Via!<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,28,26,35,29,38,41,40],"tags":[],"_links":{"self":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts\/6606"}],"collection":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/comments?post=6606"}],"version-history":[{"count":72,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts\/6606\/revisions"}],"predecessor-version":[{"id":7234,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/posts\/6606\/revisions\/7234"}],"wp:attachment":[{"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/media?parent=6606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/categories?post=6606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pmortensen.eu\/world2\/wp-json\/wp\/v2\/tags?post=6606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}