29 KiB
type, topic, tags, created, updated
| type | topic | tags | created | updated | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| tech | keyboard |
|
2026-09-15T00:00:00.000Z | 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) |
Два вывода, требующих внимания:
- Живой конфиг имел права 600 вместо нужных 644. По известному поведению Karabiner это прямой риск: при restrictive-правах Karabiner молча сбрасывает конфиг на дефолт (спрашивает про тип виртуальной клавиатуры, все complex_modifications пропадают). Обязательно
chmod 644после каждогоcp. Статус: исправлено — после правок живой файл приведён к644. - 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-фикса НЕ решена.
🔴🔴 ГЛАВНАЯ НАХОДКА: right_control ремапнут в devices[].simple_modifications
Дата: 2026-09-15 (вторая сессия). Запрос Alex: «почему сломались комбинации переключения аппов (right_control+…)?»
Симптом
right_control+x вместо запуска Xcode печатает ≈. Аналогично ломаются все остальные app-комбо.
✅ ДИАГНОЗ (подтверждён фактом из конфига)
Физическая правая Control НЕ приходит в систему как right_control. Она ремапится на уровне устройства. В profiles[0].devices[].simple_modifications живого конфига (версия 155 937 байт) прописано:
{ "from": { "key_code": "right_control" }, "to": [{ "key_code": "right_option" }] },
{ "from": { "key_code": "right_option" }, "to": [{ "key_code": "right_command" }] }
Присутствует у всех трёх клавиатур в devices[] (vid 1204/pid 257, vid 1133/pid 49948, vid 1267/pid 259).
Следствие: Karabiner видит нажатие как right_option. Все 43 манипулятора группы #0 Launch Apps HotKeys ждут в from.modifiers.mandatory ровно right_control. Такого нажатия не приходит никогда → правило не матчится → нажатие уходит в систему напрямую → RussianWin отдаёт свой стандартный символ на opt+x, а это ≈.
Механизм идентичен случаю с Ї (см. раздел про Caps Lock): «сырой» символ раскладки = признак того, что Karabiner пропустил нажатие. Не вывод to, а провал матча from.
Почему это вылезло именно после отката
| Версия конфига | Размер | Секция devices[] |
Комбо right_control+… |
|---|---|---|---|
karabiner.json.new (текущая рабочая, md5 4f643933…) |
96 877 | ремапа right_control→right_option НЕТ |
работают |
karabiner.json.bak.20260915 (откат, md5 2ad1f7e1…) |
155 937 | ремап есть | мертвы |
Разница в 59 KB — это в основном старая обвязка в devices[].simple_modifications (включая application→right_control, left_command↔left_option, consumer-keys на F7–F12).
Ошибки агента в этой сессии — НЕ повторять
| Что было сделано | Вывод |
|---|---|
Откат на .bak.20260915 без предварительного diff devices[] |
Снёс рабочую обвязку и убил 43 app-комбо. Откат «на бэкап» ≠ откат к рабочему состоянию: бэкап может быть старше по структуре, а не только по правкам |
Поиск причины в complex_modifications (правила r0 m7/m8, device_if) |
Правила были целы и идентичны. Причина лежала в другой секции конфига — devices[].simple_modifications. При «правило не срабатывает» проверять обе секции |
| Гипотеза «Karabiner потерял Input Monitoring» / «не та клавиатура» | Мимо. Процессы Karabiner живы, конфиг валиден. Причина — ремап внутри самого конфига |
| Просьба к Alex самому нажать комбо для проверки | Алекс это отверг — задачу решать агенту, не перекладывать проверку на пользователя. Скрейпить факты из файлов, а не спрашивать |
🔎 Ключевая диагностическая процедура: «правило есть, но не срабатывает»
- Проверить, что сам
from-модификатор вообще доходит до Karabiner. Искать его вdevices[].simple_modifications:Если нужный модификатор там переназначен — все правила на него мертвы. Это первое, что надо смотреть, а не содержимое/usr/bin/jq -r '.profiles[0].devices[].simple_modifications[] | "\(.from.key_code) -> \(.to[0].key_code)"' ~/.config/karabiner/karabiner.jsoncomplex_modifications. - Сверить число правил на целевой модификатор:
/usr/bin/jq '[.profiles[0].complex_modifications.rules[].manipulators[] | select((.from.modifiers.mandatory // []) | index("right_control"))] | length' - Только после этого смотреть
device_if-условия иto.
⚠️ Что НЕ является причиной
- «
toсодержитshell_command, значит не может печатать символы» — верно технически, но это следствие, не причина.shell_commandпросто не даёт вывода в раскладку;≈приходит из системы, потому что матч провалился. Не путать: сам фактshell_commandне ломает запуск приложения. - Отсутствие
optional: caps_lock— кright_control-комбо отношения не имеет. - Права 644 / md5 канона и живого — были в порядке, конфиг не сбрасывался.
Пути решения (обсуждались, ждут выбора Alex)
Вариант A — вернуть .new (текущее рабочее состояние, ремапа нет):
cp ~/Documents/karabiner.json.new ~/Documents/karabiner.json
cp ~/Documents/karabiner.json ~/.config/karabiner/karabiner.json
chmod 644 ~/.config/karabiner/karabiner.json
Плюс: app-комбо оживают, правило #13 в исходном виде. Минус: теряется старая обвязка application→right_control, left_command↔left_option, consumer-keys на F7–F12 (нужно проверить, пользуется ли Alex ими).
Вариант B — оставить обвязку и переписать комбо: заменить right_control → right_option в from.modifiers.mandatory у 43 манипуляторов группы #0. Риск: right_option уже занят под ремап right_option→right_command, и в той же devices[]-секции может возникнуть конфликт; перед правкой проверить diff по всем 43 путям.
Статус: НЕ применено. Ждёт команды Alex.
Файловое состояние на конец второй сессии
| Файл | md5 | Размер | Роль |
|---|---|---|---|
~/Documents/karabiner.json |
2ad1f7e1c8c8807739b636cc0650a527 |
155 937 | канон (откаченный, app-комбо мертвы) |
~/.config/karabiner/karabiner.json |
2ad1f7e1c8c8807739b636cc0650a527 |
155 937, права 644 | живой = канон |
~/Documents/karabiner.json.new |
4f643933f9565330fd2111973c865563 |
96 877 | рабочая версия, app-комбо живы |
~/Documents/karabiner.json.bak.20260915 |
2ad1f7e1c8c8807739b636cc0650a527 |
155 937 | бэкап, на который откатились |
~/Documents/karabiner.json.bak.20260915.keep |
2ad1f7e1c8c8807739b636cc0650a527 |
155 937 | страховочная копия бэкапа |
~/Documents/karabiner.json.bak |
44ca420798be5ab38ff3c1d54c1c6fb9 |
153 847, Jun 15 | старый бэкап |
Структура профиля (на 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.mandatoryto— 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, набрать, вернуться):
{
"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 нетронутым:
"from": {
"key_code": "slash",
"modifiers": {
"mandatory": ["option", "shift"],
"optional": ["caps_lock"]
}
}
Почему именно так (важно, не повторить ошибку):
shiftНЕЛЬЗЯ переводить изmandatoryвoptional. Shift — часть comboopt+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).
Процедура правки (когда решение будет принято)
- Сверить
~/Documents/karabiner.jsonи~/.config/karabiner/karabiner.json— сначала понять, где свежие правки (md5 разные!). - Бэкап:
cp ~/Documents/karabiner.json ~/Documents/karabiner.json.bak.20260915 - Правка рабочей копии через
jq(не sed, не in-place). Проверить diff изменённых путей — должен измениться ровно один путь:Индексы: группа/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. - Заливка в живой конфиг + права:
cp /tmp/k.json ~/Documents/karabiner.json cp ~/Documents/karabiner.json ~/.config/karabiner/karabiner.json chmod 644 ~/.config/karabiner/karabiner.json # ОБЯЗАТЕЛЬНО - Проверка: Karabiner подхватывает изменения немедленно, рестарт не нужен. Набрать
opt+shift+/при включённом Caps → должно быть?; при выключенном → тоже?(регрессии быть не должно). - Откат:
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:
"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
- 🔴 ПЕРВЫМ ДЕЛОМ ПРОВЕРЯТЬ
devices[].simple_modifications. Если нужныйfrom-модификатор там переназначен (в этой системеright_control → right_option), то все правила на него вcomplex_modificationsмертвы, сколько бы их ни было. Симптом: вместо действия печатается «сырой» символ раскладки (opt+x→≈). Правило «не срабатывает» ≠ ошибка в правиле; проверять обе секции конфига, а не толькоcomplex_modifications. - Откат «на бэкап» ≠ откат к рабочему состоянию. Перед откатом делать
diffпо структуре (devices[], число правил, размер), а не только по целевой правке..bak.20260915(155 937) структурно старше и содержит ремап, которого нет в рабочей версии (96 877) — откат на него убил 43 app-комбо. Хранить рабочие снимки как.newдо подтверждения, что откат вернул работоспособность. - Не перекладывать проверку на Alex. Просьба «нажми комбо и скажи, что произошло» была отвергнута. Задачу решает агент: факты вытаскивать из файлов конфига, логов и процессов, а не спрашивать пользователя.
- Права 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в первой сессии привело к порче раскладки и откату. - Не мешать кириллицу с ASCII в shell-командах. Поиск кириллических
key_codeстрокой вjq(== "х") блокируется tirith какconfusable_text. Использовать регулярку по диапазону:test("[^\\x00-\\x7F]")— без кириллицы в командной строке. - Именование модификаторов:
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 обязателен.