--- type: tech topic: keyboard tags: - karabiner - keyboard - macos - input-sources - russian-layout - caps-lock created: 2026-09-15T00:00:00.000Z updated: 2026-09-15T00:00:00.000Z --- # Karabiner-Elements — конфиг, раскладки, символы Конфиг клавиатуры Mac (Karabiner-Elements). Правила подмены символов в русской раскладке (RussianWin), переключение раскладок, горячие клавиши. ## Файлы конфига | Путь | Назначение | |---|---| | `~/Documents/karabiner.json` | **Рабочая копия** (канон, редактируется) | | `~/.config/karabiner/karabiner.json` | **Живой** конфиг — его читает Karabiner | | `~/Documents/karabiner.json.bak` | Бэкап рабочей копии | | `~/Documents/karabiner.json.bak.20260915` | Бэкап перед первой правкой Caps-фикса (md5 `2ad1f7e1c8c8807739b636cc0650a527`) | | `~/.config/karabiner/assets/complex_modifications/*.json` | Импортированные наборы правил (не редактируются вручную) | ### ⚠️ Расхождение канона и живого файла (обнаружено 2026-09-15) На 2026-09-15 при первом осмотре **рабочая копия и живой конфиг РАЗЛИЧАЛИСЬ**: | Файл | md5 (при осмотре) | Права | |---|---|---| | `~/Documents/karabiner.json` | `2ad1f7e1c8c8807739b636cc0650a527` | — | | `~/.config/karabiner/karabiner.json` | `3d12713ff32ad49cb4d20a5f7b284746` | **`-rw-------` (600)** | **Два вывода, требующих внимания:** 1. Живой конфиг имел права **600** вместо нужных **644**. По известному поведению Karabiner это прямой риск: при restrictive-правах Karabiner **молча сбрасывает конфиг на дефолт** (спрашивает про тип виртуальной клавиатуры, все complex_modifications пропадают). Обязательно `chmod 644` после каждого `cp`. **Статус: исправлено** — после правок живой файл приведён к `644`. 2. md5 не совпадали → расхождение канона и живого. Причина не установлена; `~/.config/karabiner/karabiner.json` меньшего размера (111 KB) чем канон (156 KB), в нём присутствуют лишние файлы-артефакты (`karabiner new.json`, `karabiner.json.06072026.bak`). После правок канон и живой были синхронизированы (`cp` канон→живой). **Перед любой правкой сверять содержимое, не заливать канон поверх живого слепо.** ### Состояние файлов на конец сессии 2026-09-15 Откат выполнен: живой конфиг = `~/Documents/karabiner.json.bak.20260915`, md5 `2ad1f7e1c8c8807739b636cc0650a527`, права `644`. Правило `#13` группы `#7` — в исходном виде (`to` = `7`+`right_shift`, `from.mandatory` = `["option","shift"]`). **Задача Caps-фикса НЕ решена.** ## Структура профиля (на 2026-09-15) Один профиль: `Default profile`, `selected=true`. `simple_modifications` — пустой (0). Все правила — в `complex_modifications.rules[]`. Группы правил (индекс → название → число манипуляторов): | # | Правило | Манипуляторов | |---|---|---| | 0 | Launch Apps HotKeys | 43 | | 1 | Russian @ from opt+cmd+2 | 1 | | 2 | Xcode Keyboard helpers | 7 | | 3 | F Keys | 8 | | 4 | Media Keys, F Keys | 11 | | 5 | Smart Quotes | 8 | | 6 | EN/ABC symbol keys | 4 | | 7 | **Russian symbol keys** | **27** | | 8 | Cmd+Space to switch language in RDP | 1 | | 9 | Remap Keys in Microsoft Remote Desktop | 1 | | 10 | Disable Cmd+H Hide (rev 2) | 1 | | 11 | Sleep | 1 | | 12 | Window Resize Mode | 4 | Все RU-символьные ремапы живут в группе **#7 `Russian symbol keys`**. ## Ключевой паттерн группы «Russian symbol keys» Каждый манипулятор: - `from` — клавиша + `modifiers.mandatory` - `to` — key_code + `modifiers` (обычно `right_shift` / `right_option` — правые модификаторы, чтобы не конфликтовать с левыми) - `conditions`: `[{ "input_sources": [{"language": "ru"}], "type": "input_source_if" }]` — срабатывает **только в русской раскладке** ### Таблица ремапов (27 манипуляторов) | RU-нажатие | Символ | Как реализовано | |---|---|---| | opt+4 ($) | ₽ | `8` + right_option | | ₽ (opt+8) | € | opt+shift+4 | | opt+shift+4 (€) | $ | `4` + right_option | | opt+е (†) | € | opt+shift+4 | | opt+9 («) | [ | grave + left_option | | opt+0 (») | ] | grave + left_option+left_shift | | ё | [ | grave + left_option | | shift+ё | ] | grave + left_option+left_shift | | opt+[ | [ | grave + left_option | | opt+] | ] | grave + left_option+left_shift | | opt+shift+[ | { | shift+9 | | opt+shift+] | } | shift+0 | | **opt+slash** | **/** | `backslash` + right_shift | | **opt+shift+slash** | **?** | **`7` + right_shift** ← см. раздел про Caps Lock | | opt+; (ж) | ; | `4` + right_shift | | opt+shift+; (Ж) | : | `6` + right_shift | | opt+' (э) | ' | `o` + right_option | | opt+2 (") | « | close_bracket + right_option | | opt+shift+2 (") | » | close_bracket + right_option+right_shift | | backslash | ё | grave_accent_and_tilde | | backslash | Ë | grave + right_shift | | § | § | non_us_backslash + left_option | | shift+§ (±) | ± | `f` + left_shift+left_option | | opt+, (<) | < | comma + right_shift+right_option | | opt+. (>) | > | period + right_shift+right_option | | opt+shift+, (≤) | ≤ | comma + right_option | | opt+shift+. (≥) | ≥ | period + right_option | ### Особый случай: `@` (в отдельной группе #1) `@` нет ни в одной русской раскладке → используется `select_input_source` (временно переключиться на ABC, набрать, вернуться): ```json { "description": "Russian @ from opt+cmd+2", "from": { "key_code": "2", "modifiers": { "mandatory": ["left_command", "option"] } }, "to": [ { "select_input_source": { "input_source_id": "com.apple.keylayout.ABC", "language": "en" } }, { "key_code": "2", "modifiers": ["right_shift"] }, { "select_input_source": { "input_source_id": "com.apple.keylayout.RussianWin", "language": "ru" } } ], "type": "basic", "conditions": [ { "input_sources": [{ "language": "ru" }], "type": "input_source_if" } ] } ``` **Это рабочий образец для символов, которых нет в RU-раскладке.** Основной минус — короткий визуальный фликер раскладки. ## 🔴 Проблема: Caps Lock ломает подстановку `?` **Запрос (2026-09-15):** в русской раскладке `opt+shift+/` без Caps вводит `?`, **при активном Caps Lock вводит `Ї`**. ### ✅ Диагноз (ПОДТВЕРЖДЁН Alex, 2026-09-15) **Правило не срабатывает при активном Caps Lock.** Подтверждено Alex напрямую. Следствие: нажатие не перехватывается манипулятором, уходит в систему напрямую, и RussianWin отдаёт свой **стандартный символ** на позиции `opt+shift+/` — это и есть `Ї`. `Ї` — не результат инверсии выхода `to`, а именно «сырой» системный символ, который возникает, когда Karabiner пропускает нажатие. Это подтверждается и косвенно: если бы правило срабатывало, на выход пошёл бы `7`+shift, и Caps инвертировал бы его в другой символ — но не в `Ї`. ### ⚠️ Что НЕ является причиной - **Смена модификатора `option` → `command` в `from`** — не имеет отношения к делу, комбинация-триггер тут не при чём. - **Инверсия выхода `to` под Caps** — этой гипотезы придерживался агент в первой части сессии, она **неверна**. Лечить надо входную часть (`from`), а не выходную (`to`). ### Правка (подготовлена, ждёт подтверждения Alex) Добавить `caps_lock` в **`optional`** модификаторы `from`, оставив `mandatory` нетронутым: ```json "from": { "key_code": "slash", "modifiers": { "mandatory": ["option", "shift"], "optional": ["caps_lock"] } } ``` **Почему именно так (важно, не повторить ошибку):** - **`shift` НЕЛЬЗЯ переводить из `mandatory` в `optional`.** Shift — часть combo `opt+shift+/`. Если сделать его опциональным, правило начнёт срабатывать и на `opt+/`, что сломает соседнее правило `opt+slash -> /`. Это предложение агента было ошибочным, Alex его отклонил. - `mandatory: ["option","shift"]` остаётся как есть — оба обязательны. - Активный Caps перестаёт блокировать матч за счёт его явного указания в `optional`. - `to` (`7`+`right_shift`), `conditions`, `description` — не трогать. **Незакрытый риск:** Alex поставил вопрос — не инвертирует ли Caps и выход `to` (`7`+`right_shift`)? Если при Caps правило сработает, но на выходе снова получится не `?` — потребуется дополнительно сбрасывать Caps в `to`. Определяется только проверкой фактом после применения. ### Ошибки агента в этой сессии — НЕ повторять | Что было сделано | Результат | Вывод | |---|---|---| | Замена `to.modifiers`: `right_shift` → `right_option` | Вместо `?` пошёл `&` | В RussianWin `opt+7` = `&`. Менять модификатор в `to` вслепую нельзя — раскладка не является аналогом US | | Замена `from.modifiers.mandatory`: `["option","shift"]` → `["option"]` + `optional:["shift"]` | Не применено (черновик) | Сломало бы `opt+/` — shift обязателен, он часть combo | | Гипотеза «Caps инвертирует выход `to`» | Неверна | Реальная причина — матч `from` не проходит | **Корневая ошибка:** агент дважды правил конфиг **без подтверждённого диагноза**, гадая между `from` и `to`. Оба раза мимо; первая правка попала в живой конфиг и сломала Alex раскладку (`&`), пришлось откатывать. **Правило: не править, пока причина не подтверждена фактом (EventViewer / прямой ответ Alex).** ### Процедура правки (когда решение будет принято) 1. Сверить `~/Documents/karabiner.json` и `~/.config/karabiner/karabiner.json` — **сначала понять, где свежие правки** (md5 разные!). 2. Бэкап: `cp ~/Documents/karabiner.json ~/Documents/karabiner.json.bak.20260915` 3. Правка рабочей копии через `jq` (не sed, не in-place). **Проверить diff изменённых путей** — должен измениться ровно один путь: ```bash /usr/bin/jq '.profiles[0].complex_modifications.rules[7].manipulators[13].from.modifiers = {"mandatory":["option","shift"],"optional":["caps_lock"]}' \ ~/Documents/karabiner.json > /tmp/k.json \ && /usr/bin/jq -e . /tmp/k.json > /dev/null \ && diff <(/usr/bin/jq -r 'paths(scalars) as $p | "\($p|join("."))=\(getpath($p))"' ~/Documents/karabiner.json) \ <(/usr/bin/jq -r 'paths(scalars) as $p | "\($p|join("."))=\(getpath($p))"' /tmp/k.json) ``` Индексы: группа `"Russian symbol keys"` = **7**, правило `alt+shift+slash -> ? (shift+7)` = **13**. 4. Заливка в живой конфиг + права: ```bash cp /tmp/k.json ~/Documents/karabiner.json cp ~/Documents/karabiner.json ~/.config/karabiner/karabiner.json chmod 644 ~/.config/karabiner/karabiner.json # ОБЯЗАТЕЛЬНО ``` 5. Проверка: Karabiner подхватывает изменения немедленно, рестарт не нужен. Набрать `opt+shift+/` при **включённом Caps** → должно быть `?`; при выключенном → тоже `?` (регрессии быть не должно). 6. **Откат:** ```bash cp ~/Documents/karabiner.json.bak.20260915 ~/.config/karabiner/karabiner.json chmod 644 ~/.config/karabiner/karabiner.json ``` ### Альтернатива, если фикс через `optional: caps_lock` не сработает Заменить `to` на трёхшаговую цепочку через ABC-раскладку (как в правиле `@`): переключиться на ABC → `slash` + `right_shift` (Shift+/ = `?` на US, Caps на пунктуацию не влияет) → вернуться в RussianWin: ```json "to": [ { "select_input_source": { "input_source_id": "com.apple.keylayout.ABC", "language": "en" } }, { "key_code": "slash", "modifiers": ["right_shift"] }, { "select_input_source": { "input_source_id": "com.apple.keylayout.RussianWin", "language": "ru" } } ] ``` Минус — короткий фликер раскладки. Применять только если `optional: caps_lock` не даёт результата. ### Черновик правки `to` (собран, НЕ применён) Файл `/tmp/k3.json` — версия с `to` через ABC. В живой конфиг и канон **не заливался**. `diff` показал изменение только путей внутри `manipulators.13.to`. ### Терминологическая поправка Alex в изначальном запросе назвал комбинацию `cmd+shift+/`, но фактическое правило в конфиге — `opt+shift+/` (`alt+shift+slash`). Правила на `cmd+shift+/` в конфиге **нет вообще** (проверено: ни одного манипулятора с `key_code: "slash"` + `command` в `mandatory`). Работаем с существующим правилом `opt+shift+/`. ## Pitfalls - **Права 600 → молчаливый сброс конфига.** `cp` сохраняет режим ИСТОЧНИКА, а не целевого файла. После каждого `cp` в `~/.config/karabiner/karabiner.json` → `chmod 644`. Симптомы сброса: Karabiner спрашивает про тип виртуальной клавиатуры, все complex_modifications исчезли. - **Правила без явного условия Caps Lock.** Каждый манипулятор, чей `from` содержит `shift`, при активном Caps Lock **может перестать матчиться вообще** — нажатие уходит в систему и раскладка отдаёт свой стандартный символ (для `opt+shift+/` в RussianWin это `Ї`). Лечится добавлением `"optional": ["caps_lock"]` в `from.modifiers`, не трогая `mandatory`. - **Не переводить `shift` из `mandatory` в `optional`.** Если shift — часть combo (как в `opt+shift+/`), это расширит правило на более короткое сочетание (`opt+/`) и сломает соседнее правило. - **Не менять модификатор в `to` вслепую.** RussianWin **не является** аналогом US-раскладки: `opt+7` там = `&`, а не `?`. Замена `right_shift` → `right_option` в `to` даёт мусорный символ. Сначала проверить, что реально лежит на позиции в раскладке. - **Не править конфиг без подтверждённого диагноза.** Определить, ломается ли матч `from` или инвертируется выход `to` — можно только фактом (EventViewer или прямой ответ пользователя). Гадание между `from` и `to` в этой сессии привело к порче раскладки и откату. - **Именование модификаторов:** `left_command`/`right_command` (не `left_gui`); для левого option достаточно `option`; `right_shift`/`right_option` указывать явно. - **Цепочка `select_input_source` → key → `select_input_source`** выполняется мгновенно, задержки не нужны, но даёт короткий фликер раскладки. - **Живой файл и канон разъезжаются** — проверять md5 перед правкой. - **Перед применением правки проверять diff `jq paths(scalars)`** — должен измениться ровно ожидаемый путь и ничего больше. Это ловит и ошибку индекса, и случайные изменения. ## Input Sources на этой системе | Раскладка | Тип | ID | |---|---|---| | ABC (US) | Keyboard Layout | `com.apple.keylayout.ABC` | | RussianWin | Keyboard Layout | `com.apple.keylayout.RussianWin` | | Unicode Hex Input | Keyboard Layout | — | Список: `defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleEnabledInputSources` ## Связанные правила по флагам Caps (для справки) Проверено на 2026-09-15: ссылок на `caps_lock` ни в `key_code`, ни в `from`/`to` в конфиге **нет** (0 совпадений). Ни один манипулятор не декларирует Caps в `optional` — именно поэтому Caps-состояние ломает матчинг у правил, где `shift` обязателен. ## References - [Karabiner select_input_source](https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/to/select-input-source/) - [KE complex_modifications JSON spec](https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/basic/)