Skip to content

gjoob/lapsusfix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LapsusFix

Русский · English

Маленький агент в строке меню macOS, который конвертирует текст, набранный не в той раскладке. Выдели текст (или просто поставь курсор сразу после него) и нажми Control + Fn — набранный кусок переводится в противоположную раскладку: ghbdtn становится привет, Руддщ становится Hello, а системная раскладка переключается на ту, в которую переведён последний фрагмент.

Дополняет штатный переключатель раскладок macOS, а не заменяет его.

Что он чинит

Два частых случая.

  1. Весь кусок не в той раскладке. Набрал фразу не глядя, был уверен, что раскладка правильная, а потом увидел, что индикатор показывал другую. Выдели текст, нажми хоткей — готово.
  2. Перевёрнутый текст. Набирал, переключая раскладки «на автомате», но стартовая раскладка была не та, и всё перевернулось: то, что должно было выйти латиницей, вышло кириллицей, и наоборот. Выдели весь фрагмент: каждый кусок перебьётся в свою правильную сторону.

Без выделения LapsusFix конвертирует последнее слово, после которого стоит курсор — полезно, если быстро заметил, что ошибся.

Дизайн и приватность

LapsusFix построен вокруг одного решения: он не следит за нажатиями клавиш.

  • Слушает только собственный хоткей. Поток ввода он не видит вообще.
  • Раз его нет в пути обычных нажатий, он не может тормозить или морозить ввод — в отличие от переключателей, которые ради автопереключения перехватывают каждое нажатие (отсюда фризы у Punto под нагрузкой на CPU).
  • Текст для конвертации он читает в момент нажатия хоткея — прямо из активного поля (через Accessibility), а где так нельзя — через проход по буферу обмена.
  • Единственное нужное разрешение — Accessibility.
  • Открытый код, без телеметрии, без сети.

Раскладка переводится позиционно, как в Punto: QWERTY ↔ ЙЦУКЕН по физическим клавишам, а не транслитом. Конвертируются и буквы, и знаки препинания, которые смещаются между раскладками.

Требования

  • macOS 10.14 (Mojave) или новее. Universal (Apple Silicon + Intel).
  • Для сборки из исходников — Xcode Command Line Tools (xcode-select --install).

Установка из исходников

Нотаризованного релиза нет (ссылка на ненотаризованную сборку есть ниже) — приложение собирается из исходников:

git clone https://github.com/gjoob/lapsusfix.git
cd lapsusfix
bash scripts/build_app.sh

Скрипт собирает build/LapsusFix.app. После сборки можно перенести его в /Applications. Запускать через Finder или open:

open build/LapsusFix.app

Запуск через LaunchServices важен: иначе macOS может приписать выданное разрешение Accessibility родительскому процессу, и оно не сработает.

При первом запуске приложение попросит доступ к Accessibility и подскажет путь: System Settings → Privacy & Security → Accessibility. Добавь туда LapsusFix.app и включи тумблер. Приложение живёт в строке меню (значок L), без иконки в доке и без главного окна.

Нюанс ad-hoc-подписи (Sequoia). Сборка подписана ad-hoc, и грант Accessibility привязан к хэшу бинарника. После пересборки грант может молча слететь: тумблер визуально включён, но прав нет. Если после пересборки перестало срабатывать — удали запись из списка Accessibility и добавь LapsusFix.app заново.

Юнит-тесты ядра конвертации: bash scripts/test.sh.

Использование

  1. Выбор раскладок в меню: подменю English layout и Russian layout показывают установленные в системе раскладки. По умолчанию — ABC (английская) и Russian (системная Mac-раскладка, не «Русская — ПК»). Пока что поддерживается работа только с кириллическими раскладками в качестве второй, если будут запросы на другие нелатинские варианты (греческий, иврит и т.д.), постараемся реализовать поддержку.
  2. Калибровка, если раскладки отличаются от дефолтных: меню → Calibrate layout…, дальше четыре прохода по клавишам (каждая раскладка, с Shift и без). Калибровка сохраняется в ~/Library/Application Support/lapsusfix/layout.json. При смене раскладки в подменю приложение предложит перекалибровать — таблица конвертации привязана к конкретной паре раскладок.
  3. Конвертация: выдели текст и нажми Control + Fn; либо поставь курсор сразу после ошибочно набранного слова и нажми хоткей — перебьётся слово. Системная раскладка переключится на ту, в которую переведён последний фрагмент.
  4. Настройка хоткеев: меню → Hotkeys…. Рекордер понимает сочетания из модификаторов (как Ctrl+Fn) и различает левые и правые модификаторы.
  5. Автоматический запуск при старте системы: переключатель в меню.

Логирование

По умолчанию выключено. Тумблер Verbose logging в меню включает запись диагностики (пригодится, если будешь сообщать о проблеме), Reveal log in Finder открывает лог. Лог лежит в ~/Library/Logs/lapsusfix/agent.log и ротируется на 5 МБ.

Приватность: при включённом verbose в лог попадают фрагменты конвертируемого текста (для отладки) — поэтому логирование выключено по умолчанию и включается только вручную. Без verbose пишутся лишь служебные события (старт, ошибки) без содержимого полей.

Как выбирается раскладка и что конвертируется

Исходный алфавит определяется по последней букве фрагмента — латиница (U+0041–007A) против кириллицы (U+0400–04FF). Не-буквы при определении пропускаются, но в конвертацию входят (часть знаков смещена между раскладками). Дальше логика зависит от того, есть ли выделение:

  • Есть выделение. Строка делится на куски по буквенной «окраске», и каждый кусок перебивается в противоположную раскладку — то, что вышло кириллицей, возвращается в латиницу, и наоборот. Так чинится перевёрнутый текст из второго случая: в одном выделении несколько сегментов, каждый инвертируется в свою сторону.
  • Нет выделения. Берётся «забег» — цепочка в конце последнего слова: опорная буква и дальше влево буквы того же алфавита со знаками из таблицы конвертации, до ближайшей чужой буквы или разрыва. Смешанное слово «съедается» кусками: после конвертации последняя буква оказывается из другого алфавита, и повторное нажатие делает новый забег с учётом этого.

После конвертации системная раскладка переключается на ту, в которую переведён последний кусок, — чтобы можно было продолжать печатать с того же места.

Известные ограничения

Большинство приложений работают через Accessibility; многие веб- и Electron-приложения и часть нативных идут через фоллбэк на буфер обмена. Остаются частные особенности:

  • Pages (основной текст): конвертация без выделения вызывает системный «бип» (побочка от проверки, есть ли выделение). Это косметика — текст конвертируется правильно. На комментарии в Pages не влияет.
  • Холодный старт LibreOffice: первые секунды после запуска LibreOffice конвертация может не сработать. Подожди немного и повтори.
  • Обрезка крайних пробелов в некоторых полях: Evernote, поле поиска google.com и похожие JS-инпуты срезают пробелы по краям при вставке. Сама конвертация верна — страдают только крайние пробелы.
  • Markdown-редакторы: символы разметки (*, _, #, …), попавшие в выделение, конвертируются позиционно и могут поломать разметку — LapsusFix не разбирает markdown.
  • Редакторы на Chromium/Slate (Claude Desktop, возможно Slack/Discord): многострочная конвертация использует параграфную эвристику; если дотянуть выделение до самого конца строки, может остаться лишняя пустая строка. Откатывается через ⌘Z.
  • Apple Terminal: иногда хоткей не срабатывает (Accessibility не отдаёт поле — зависит от состояния окна/вкладки) — повтори или выдели мышью. Только что вставленный текст может на какое-то время остаться подсвеченным.
  • Чужой буфер обмена сохраняется только как обычный текст. При фоллбэке на буфер LapsusFix снимает и восстанавливает лишь текстовое содержимое (до 500 КБ). Если в буфере лежало форматирование (RTF/HTML), картинка, файлы или больше 500 КБ — после операции буфер очищается. Форматирование и не-текст конвертацию через буфер не переживают. В плане развития переписать эту часть, чтобы сохранялось любое содержимое до определённого размера.
  • Очень большие выделения не конвертируются. Если захваченный кусок больше 100 КБ, конвертация не делается — защита от случайного ⌘A в огромном документе.
  • Переключение раскладки — системное. В macOS нет API для раскладки на отдельное поле, поэтому после конвертации меняется системная раскладка целиком.

Если попадётся новое приложение, которое ведёт себя странно, включи Verbose logging, воспроизведи и приложи лог к issue.

Обновления

На данный момент программа не поддерживает никакого механизма автоматических апдейтов или нотификации об обновлениях.

Готовая сборка

Если не хочется самостоятельно собирать программу из исходников, можно взять собранный ненотаризованный бандл с инструкцией по обходу Gatekeeper'а по адресу: https://github.com/gjoob/lapsusfix/releases

Лицензия

MIT © 2026 Fedor Malginov.

Благодарности

Собрано с помощью Claude Code (Anthropic). Спасибо за очень интересный и полезный опыт.


LapsusFix

Русский · English

A small macOS menu-bar agent that converts text typed in the wrong keyboard layout. Select the text (or just put the cursor right after it) and press Control + Fn — what you typed is converted to the opposite layout: ghbdtn becomes привет, Руддщ becomes Hello, and the system input source switches to the layout the text now ends in.

It complements the standard macOS layout switcher rather than replacing it.

What it fixes

Two common cases.

  1. The whole chunk is in the wrong layout. You typed a phrase without looking, sure the layout was right, then noticed the indicator was set to the other one. Select the text, press the hotkey — done.
  2. Inverted text. You typed while switching layouts "on autopilot," but the starting layout was wrong, and everything got flipped: what should have been Latin came out as Cyrillic, and vice versa. Select the whole thing: each chunk is converted back to its correct alphabet.

Without a selection, LapsusFix converts the last word before the cursor — handy when you catch the mistake right away.

Design and privacy

LapsusFix is built around one decision: it does not monitor your keystrokes.

  • It listens only for its own hotkey. It never sees what you type.
  • Since it isn't in the path of ordinary keypresses, it can't lag or freeze your typing — unlike switchers that intercept every keystroke for auto-switching, the reason Punto stutters under CPU load.
  • It reads the text to convert at the moment you press the hotkey — straight from the focused field (via Accessibility), or, where that isn't possible, through a clipboard round-trip.
  • The only permission it needs is Accessibility.
  • Open source, no telemetry, no network.

The layout is converted positionally, like Punto: QWERTY ↔ ЙЦУКЕН by physical key, not by transliteration. Both letters and the punctuation that shifts between layouts are converted.

Requirements

  • macOS 10.14 (Mojave) or later. Universal (Apple Silicon + Intel).
  • To build from source — Xcode Command Line Tools (xcode-select --install).

Installing from source

There is no notarized release (a link to an un-notarized build is below) — the app is built from source:

git clone https://github.com/gjoob/lapsusfix.git
cd lapsusfix
bash scripts/build_app.sh

The script produces build/LapsusFix.app. Once built, you can move it to /Applications. Launch it through Finder or open:

open build/LapsusFix.app

Launching via LaunchServices matters: otherwise macOS may attribute the granted Accessibility permission to the parent process, and it won't take effect.

On first launch the app asks for Accessibility access and points you to: System Settings → Privacy & Security → Accessibility. Add LapsusFix.app there and turn on the toggle. The app lives in the menu bar (the L icon), with no Dock icon and no main window.

Ad-hoc signing caveat (Sequoia). The build is ad-hoc signed, and the Accessibility grant is tied to the binary's hash. After a rebuild the grant may silently drop: the toggle still looks enabled, but the permission isn't there. If it stops working after a rebuild — remove the entry from the Accessibility list and add LapsusFix.app again.

Unit tests for the conversion core: bash scripts/test.sh.

Usage

  1. Layout selection in the menu: the English layout and Russian layout submenus list your installed keyboard layouts. The defaults are ABC (English) and Russian (the stock macOS Russian layout, not "Russian – PC"). For now only Cyrillic layouts are supported as the second one; if there are requests for other non-Latin options (Greek, Hebrew, etc.), we'll try to add support.
  2. Calibration, if your layouts differ from the defaults: menu → Calibrate layout…, then four passes over the keys (each layout, with and without Shift). Calibration is saved to ~/Library/Application Support/lapsusfix/layout.json. When you change a layout in the submenu, the app offers to recalibrate — the conversion table is tied to one specific layout pair.
  3. Conversion: select the text and press Control + Fn; or put the cursor right after a mistyped word and press the hotkey — the word is converted. The system input source then switches to the layout the text now ends in.
  4. Hotkey setup: menu → Hotkeys…. The recorder understands modifier-only combinations (like Ctrl+Fn) and distinguishes left and right modifiers.
  5. Launch at login: a toggle in the menu.

Logging

Off by default. The Verbose logging toggle in the menu turns on diagnostic recording (handy when you report a problem), and Reveal log in Finder opens the log. The log lives at ~/Library/Logs/lapsusfix/agent.log and rotates at 5 MB.

Privacy: with verbose on, fragments of the converted text end up in the log (for debugging) — so logging is off by default and is only turned on manually. Without verbose, only basic events (startup, errors) are logged, with no field contents.

How the layout is chosen and what gets converted

The source alphabet is determined by the last letter of the run or selection — Latin (U+0041–007A) versus Cyrillic (U+0400–04FF). Non-letters are skipped for detection but are still converted (some characters are shifted between layouts). What happens next depends on whether there is a selection:

  • There is a selection. The string is split into runs of a single alphabet, and each run is converted to the opposite layout — what came out as Cyrillic goes back to Latin, and vice versa. This is how the inverted text from the second case is fixed: one selection holds several segments, each flipped back to its correct alphabet.
  • There is no selection. LapsusFix takes a "run" at the end of the last word: an anchor letter and, going further left, letters of the same alphabet plus characters from the conversion table, up to the nearest foreign letter or break. A mixed word is converted in pieces: after each conversion the last letter belongs to the other alphabet, so pressing the hotkey again converts the next run.

After a conversion the system input source switches to the last chunk's new layout, so you can keep typing from where you left off.

Known limitations

Most apps work through Accessibility; many web and Electron apps, and some native ones, go through the clipboard fallback. A few specific quirks remain:

  • Pages (main body): a conversion without a selection triggers the system "beep" (a side effect of probing whether there's a selection). It's cosmetic — the text is converted correctly. It doesn't affect comments in Pages.
  • LibreOffice cold start: for the first few seconds after LibreOffice launches, a conversion may not fire. Wait a moment and try again.
  • Edge spaces trimmed in some fields: Evernote, the google.com search box, and similar JS inputs strip leading and trailing spaces on paste. The conversion itself is correct — only the edge spaces are affected.
  • Markdown editors: markup characters (*, _, #, …) caught in a selection are converted positionally and can break the markup — LapsusFix does not parse markdown.
  • Chromium/Slate editors (Claude Desktop, possibly Slack/Discord): multi-line conversion uses a paragraph heuristic; if you drag the selection to the very end of a line, an extra blank line may remain. Undo with ⌘Z.
  • Apple Terminal: sometimes the hotkey does nothing (Accessibility doesn't return the field — it depends on the window/tab state) — try again or select with the mouse. Just-pasted text may stay highlighted for a while.
  • Your existing clipboard contents are preserved only as plain text. During the clipboard fallback, LapsusFix captures and restores only text content (up to 500 KB). If the clipboard held formatting (RTF/HTML), an image, files, or more than 500 KB — the clipboard is cleared after the operation. Formatting and non-text don't survive a conversion through the clipboard. A planned improvement is to rewrite this part so that any content up to a certain size is preserved.
  • Very large selections are not converted. If the captured chunk is larger than 100 KB, nothing is converted — a guard against an accidental ⌘A in a huge document.
  • Layout switching is system-wide. macOS has no API for a per-field layout, so after a conversion the entire system input source changes.

If you hit a new app that behaves oddly, turn on Verbose logging, reproduce it, and attach the log to an issue.

Updates

At the moment the app has no mechanism for automatic updates or update notifications.

Prebuilt bundle

If you'd rather not build the app from source yourself, you can grab a prebuilt (un-notarized) bundle, with Gatekeeper-bypass instructions, from the Releases page: https://github.com/gjoob/lapsusfix/releases

License

MIT © 2026 Fedor Malginov.

Acknowledgments

Built with Claude Code (Anthropic). Thanks for a genuinely interesting and useful experience.

About

Fix text typed in the wrong keyboard layout on macOS — a minimal, fast, privacy-respecting menu-bar agent, hotkey-controlled, with no automatic switching.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors