Я разработал самопишущую клавиатуру. Неоконченная пьеса для механического пианино

от автора

Есть у меня товарищ. Работает в банке. Не в том банке, где три бухгалтера, директор и сервер под столом, который нельзя выключать, потому что никто не помнит пароль. А в большом, серьёзном банке, где есть закрытые контуры, службы информационной безопасности, согласования, регламенты, сертификаты, ещё согласования и, подозреваю, специальные люди, согласовывающие согласования.

И мы с ним периодически спорим об AI.

Я утверждаю довольно неприятную для программистов вещь: через два года практически весь прикладной код в мире, кроме действительно секретных областей, будет писать AI.

Не обязательно самостоятельно. Не обязательно без человека. Но писать руками очередной CRUD, форму авторизации, API-клиент, миграцию базы или сотый обработчик JSON будет примерно так же естественно, как сегодня вручную считать CRC32 на бумажке.

Он со мной категорически не согласен.

— У нас закрытый контур.

— Хорошо.

— Ты вообще представляешь себе требования безопасности банка?

— Представляю.

— У нас человек сядет, если свою флешку в рабочий ноутбук воткнёт.

— Весомый аргумент.

Потом начинается рассказ про сертификацию, костную систему безопасности, сегментацию сети, государственные требования, внутренние положения, страшных людей из ИБ и главное:

ИМПОРТОЗАМЕЩЕЕЕЕЕЕНИЕ!!!!!

Здесь обычно разговор должен закончиться. Но есть одна маленькая проблема. Будучи тимлидом в таком вот страшном банке, мой товарищ периодически замечает довольно занятную картину.

Нет-нет, да какой-нибудь разработчик достанет телефон. Что-то сфотографирует с экрана. Что-то куда-то отправит. Потом долго смотрит в телефон. А потом начинает что-то впечатывать обратно.

Медленно. Руками. В 2026 году.

И вот тут у меня возник вопрос.

А что, собственно, мы защищаем: код или отсутствие нормального инструмента для работы с кодом?

У вас в компании как? AI официально встроен в процесс разработки или программисты уже организовали подполье с телефонами, фотографиями мониторов и ручным переносом ответов?

Деды наши перфокарты дырявили

Я совершенно понимаю аргументы информационной безопасности.

Исходники нельзя отправлять неизвестно куда. API-ключи нельзя отправлять неизвестно кому. Данные клиентов вообще лучше никуда не отправлять. Исходный код банка — не тот материал, на котором стоит бесплатно тренировать очередную американскую, китайскую или какую угодно модель.

Но дальше возникает странная развилка.

Первый вариант:

сделать внутри контура нормальную локальную LLM.

Посадить туда хороший coding model. Дать ему RAG по внутренней документации. Проиндексировать репозитории, документацию, API, архитектурные решения. Добавить память проектов. ACL. Логи. DLP. Аудит.

Чтобы разработчик мог спросить:

Почему здесь десять лет назад сделали именно так?

И модель полезла не в Интернет, а в историю коммитов, внутреннюю Wiki, ADR, документацию и соседние сервисы.

По-моему, прекрасная система. Но зачем? Нет, не нужно нам этого иностранного. Мы уж по старинке. Деды наши перфокарты дырявили — нам-то уже грех жаловаться.

Поэтому остаётся второй вариант: человек фотографирует код телефоном, получает ответ и перепечатывает его обратно. И в какой-то момент я подумал: ладно, если мы уже дошли до перепечатывания, давайте хотя бы автоматизируем перепечатывание.

Так появился CodeKey.

Неоконченная пьеса для механического пианино

Я давно люблю устройства, которые делают что-то немного не так, как было задумано создателями интерфейса. У компьютера есть прекрасный древний интерфейс ввода — клавиатура. Хотя, все понимают, что это узкое горлышко между нашим мозгом и компьютером.

Она появилась задолго до LLM, Zero Trust, облаков и половины людей, которые сейчас пишут требования по информационной безопасности. Причём USB-клавиатура очень тупая.

Она не отправляет компьютеру:

Здравствуйте. Я AI-агент из облака. Сейчас я внесу изменения в ваш production-код.

Она говорит примерно следующее:

Нажата клавиша f.

Потом:

Нажата клавиша o.

Потом ещё одна o. И компьютер совершенно спокойно получает foo. Получается смешная конструкция. LLM пишет код. Телефон играет роль дирижёра. ESP32 нажимает клавиши. А компьютер наблюдает за этим представлением и думает, что кто-то очень быстро печатает.

Механическое пианино XXI века. Только вместо «Лунной сонаты» оно исполняет Python.

Проект я поэтому мысленно называю неоконченной пьессой для механического пианино.

Первая версия была очень простой

Мне нужно было устройство, которое:

  1. подключается к компьютеру как обычная USB-клавиатура;

  2. получает текст по беспроводному каналу;

  3. превращает его в реальные HID-нажатия.

Для железа я взял ESP32-S3. У неё есть нативный USB-OTG, поэтому отдельный USB-контроллер городить не пришлось. Со стороны рабочей станции устройство определяется как USB HID Keyboard. С другой стороны — Bluetooth Low Energy.

Архитектура первоначально выглядела почти неприлично просто:

Телефон   │   │ BLE   ▼ESP32-S3   │   │ USB HID   ▼Рабочий компьютер

Esp32-S3-supermini, просто такая была.

Ее, конечно, можно и просто так оставить, но антуражнее будет разместить ее в корпус реальной клавиатуры.

Телефон отправляет текст. ESP32 нажимает клавиши. Готово. Можно было на этом остановиться, выложить на GitHub очередной проект «ESP32 Bluetooth Keyboard» и пойти заниматься чем-нибудь полезным.

Но тут, как обычно, выяснилось, что между «отправить строку» и «нормально вставить кусок кода» находится примерно половина разработки.

В настройках можно менять как определяется в системе клавиатура. Название производителя, VID, PID.

Код — это очень капризный текст

Обычному человеку всё равно, каким способом в документе появилась буква. IDE — не всё равно.

Нужно правильно обработать:

  • Enter;

  • Tab;

  • Backspace;

  • Delete;

  • сочетания клавиш;

  • разные раскладки;

  • Windows/Linux/macOS;

  • особенности редактора;

  • скорость ввода;

  • паузы;

  • большие задания;

  • остановку посреди печати.

Поэтому простую передачу строки я довольно быстро превратил в задание.

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

Появились состояния:

readyrunningpauseddone

И команды:

startpauseresumecancelrelease_all

Плюс я разделил обычный текст и управляющие операции.

Например, есть семантическая команда:

SAVE

А уже приложение понимает, что конкретно она означает.

Для Windows/Linux:

Ctrl + S

Для macOS:

Command + S

Зачем такое усложнение? Потому что я не хотел давать LLM непосредственное управление клавиатурой. Модель может написать код. Модель может сказать, что его желательно заменить.

Но она не должна сама решить:

А теперь нажмём Win+R, запустим что-нибудь интересное и посмотрим, что получится.

Код и управляющий канал разделены. Мне кажется, это вообще важный принцип для AI-агентов: модель должна предлагать намерение, а исполняющая система — решать, допустимо ли действие.

И вот тут интересно мнение читателей.

Вы бы дали coding-agent прямой доступ к shell/IDE, если он работает внутри компании? Или между моделью и компьютером обязательно должен оставаться жёсткий детерминированный слой?

Потом понадобился телефон

Следующая проблема очевидна. Хорошо, AI умеет печатать код обратно. Но как показать AI код, который уже находится на изолированной рабочей станции? Фотография. Я написал мобильное приложение на Flutter — сразу с расчётом на Android и iOS.

Сценарий получился такой:

Экран рабочего компьютера          │          │ камера          ▼      Смартфон          │          ├── OCR          ├── DLP          ├── запрос пользователя          ├── LLM          └── компилятор задания                    │                    │ BLE                    ▼                 ESP32                    │                    │ USB HID                    ▼             рабочий компьютер

Главный момент: сама фотография экрана в LLM не отправляется. OCR выполняется локально на телефоне. Для этого сейчас используется Google ML Kit Text Recognition v2.

Сделал фотографию — она сразу появляется на основном экране. Распознавание идёт асинхронно. На карточке видно состояние:

В очередиOCR 37%ГотовоОшибка

Фотографий можно сделать несколько. На одной — функция. На второй — место вызова. На третьей — traceback. После распознавания текст можно открыть и вручную исправить. Это оказалось принципиально важным, потому что OCR обычного текста и OCR исходного кода — немного разные виды спорта.

Если из художественного текста исчез один пробел, Толстой переживёт. Если из Python исчез один пробел, Python начнёт рассказывать вам о структуре мироздания через IndentationError.

Интерфейс я специально сделал максимально коротким

Мне не хотелось делать ещё одну мобильную IDE. Телефон здесь — не место, где человек программирует. Это пульт.

На главном экране сверху показывается состояние CodeKey. Видно, подключена ли ESP32 по BLE. Рядом находится текущая раскладка клавиатуры, которую можно быстро переключить.

Ниже появляются фотографии кода. Ещё ниже — обычное поле запроса. Можно написать:

Исправь эту функцию, здесь иногда возникает race condition.

И отправить. Можно вообще ничего не фотографировать:

Напиши функцию на Python, которая принимает список VIN и удаляет дубли.

То есть CodeKey может работать просто как AI-клавиатура.

После ответа приложение не показывает огромную простыню markdown, которой современные AI-сервисы почему-то очень любят доказывать свою полезность. Я заставляю модель вернуть строгий JSON:

{  "schema_version": 1,  "explanation": "Что исправлено и почему",  "placement": "Куда установить курсор или какой участок выделить",  "operation": "replace_selection",  "code": "код для вставки",  "warnings": []}

Приложение сначала валидирует этот ответ. Только после этого что-либо превращается в задание для клавиатуры. На экране отдельно показывается:

Что изменилось

Нормальным человеческим языком.

Потом:

Код для вставки

Отдельным блоком. Если есть технические предупреждения — они тоже отдельно. А внизу большая кнопка:

Печать

Мне до сих пор нравится это название. Не Apply. Не Deploy. Не AI Magic. Печать.

Потому что именно это устройство и делает.

Нажимаем «Печать»

После нажатия приложение сначала говорит человеку, что сделать:

Установите курсор в начало функции.

или:

Выделите существующий метод целиком.

Человек подтверждает, что готов. После этого телефон передаёт задание ESP32. И начинается представление. На экране IDE появляется код. Строчка. Ещё строчка. Ещё. Можно нажать Pause. Можно продолжить. Можно полностью остановить задание. Можно настроить количество символов в секунду.

А ещё есть режим естественной печати. Чисто технически он совершенно не нужен. Но наблюдать, как компьютер самостоятельно пишет код с почти человеческими небольшими задержками, очень приятно. Как механическое пианино. Только немного пугающее.

А если LLM напечатает rm -rf?

Именно поэтому между моделью и клавиатурой я постарался оставить как можно больше скучных, детерминированных проверок. LLM не получает прямой доступ к HID. Она возвращает структурированный ответ. Ответ валидируется. Пользователь видит код. Пользователь видит, куда он будет помещён. Пользователь сам запускает печать.

По BLE устройство тоже не принимает всё подряд от первого встречного телефона. Есть challenge-response аутентификация с HMAC.

Само задание передаётся частями и проверяется по CRC перед выполнением.

То есть архитектурно это не:

AI → компьютер

А скорее:

AI ↓структурированный ответ ↓проверка ↓человек ↓компилятор задания ↓ESP32 ↓HID

Конечно, это не делает систему магически безопасной.

Но мне вообще кажется странной современная вера в то, что безопасность возникает от слова «запрещено» в корпоративном регламенте.

Запретили ChatGPT.

Отлично.

Человек достал телефон.

И безопасность закончилась.

Может быть, правильный вопрос должен звучать не «как запретить разработчику использовать AI?», а «как дать ему AI так, чтобы компания контролировала, какие данные куда уходят?»

Что думаете?

Поэтому в CodeKey появилась DLP

Перед отправкой текста во внешний API приложение локально ищет потенциально чувствительные данные.

Сейчас проверяются, в частности:

  • API keys;

  • access tokens;

  • JWT;

  • пароли;

  • private keys;

  • connection strings;

  • внутренние IP;

  • внутренние домены;

  • email;

  • телефонные номера;

  • платёжные данные;

  • строки с подозрительно высокой энтропией;

  • пользовательский список корпоративных слов.

И перед отправкой можно посмотреть точно тот текст, который уйдёт в API. Не фотографию. Не содержимое телефона. Не весь проект. Конкретный распознанный текст плюс запрос пользователя. Конечно, regex — это не корпоративная DLP за несколько миллионов рублей. Но здесь для меня важнее сам принцип.

Фильтрация должна происходить до выхода данных наружу, а не после того, как SIEM торжественно сообщил, что секрет уже улетел.

Какую LLM использовать — мне всё равно

Я специально не стал привязывать систему к одному поставщику.

Сейчас есть:

  • DeepSeek;

  • OpenAI-compatible API;

  • Anthropic.

В настройках выбирается провайдер, Base URL, модель и ключ. Поэтому никто не мешает направить приложение вообще на собственный совместимый endpoint. И вот здесь мы красиво возвращаемся к началу статьи. Потому что самый разумный вариант CodeKey для серьёзной организации — это, возможно, вообще не внешний AI.

Представьте:

Телефон   │   │ корпоративный Wi-Fi   ▼LLM внутри контура   │   ├── RAG документации   ├── репозитории   ├── Wiki   ├── история проектов   └── корпоративные политики

А CodeKey остаётся только способом взаимодействия с рабочей станцией, на которую нельзя ставить дополнительный софт.

Хотя в этот момент возникает закономерный вопрос: если мы уже развернули нормальную LLM внутри контура, может быть, пора просто официально интегрировать её в IDE?

Да. И это, пожалуй, главный недостаток моего проекта.

Если CodeKey становится действительно необходим компании — возможно, у компании сломана не клавиатура. У неё сломан процесс внедрения AI.

Самое смешное — CodeKey частично написан AI

Здесь получается довольно красивая рекурсия. Я спорю с человеком, что AI скоро будет писать практически весь код. Чтобы доказать свою мысль, делаю устройство, которое позволяет AI физически писать код на компьютере. И значительную часть программной работы при создании этого устройства я сам делаю с AI.

Наверное, следующий логичный шаг — подключить CodeKey к компьютеру, на котором открыт исходный код CodeKey, и попросить его дописать самого себя. После этого останется только поставить рядом камеру и проверить, не появится ли в комнате Сэм Альтман из будущего с просьбой немедленно всё выключить.

Что я хочу сделать дальше

Сейчас CodeKey — активный MVP. Мне хочется дальше улучшить распознавание именно исходного кода, сделать больше профилей IDE, нормальный редактор HID-профилей, расширить DLP и историю задач. Есть очевидная идея с локальной LLM прямо на смартфоне. Вот она мне особенно нравится. Тогда конструкция станет совсем забавной:

Код ↓камера телефона ↓локальный OCR ↓локальная LLM ↓ESP32 ↓клавиатура ↓код

Вообще никакого облака. Маленький автономный программист размером с телефон и ESP32. Но куда интереснее корпоративное направление. MDM. Политики. Белые списки моделей. Запрет определённых типов данных. Корпоративный LLM endpoint. Аудит запросов.

Возможно, даже централизованные профили, в которых служба безопасности заранее определяет, что CodeKey вообще имеет право делать.

И тогда устройство из странного костыля превращается в довольно интересный интерфейс между AI и закрытой инфраструктурой.

Но вообще статья не про клавиатуру

Сам CodeKey здесь скорее доведение ситуации до абсурда.

Мы уже научились делать LLM, которые способны читать проект, искать ошибки, писать тесты, рефакторить код, объяснять незнакомые репозитории и выполнять многошаговые задачи.

А потом берём разработчика, закрываем ему доступ к этим инструментам и говорим:

Так безопаснее.

После чего он фотографирует монитор телефоном. Мне кажется, ближайшие годы будут не столько борьбой AI с программистами, сколько борьбой скорости развития AI с корпоративной инерцией. Технологически AI уже способен забирать всё большую долю программирования. Организационно огромная часть компаний к этому совершенно не готова.

И поэтому какое-то время мы будем наблюдать удивительные гибриды. AI пишет код. Человек проверяет его на телефоне. ESP32 изображает клавиатуру. Система безопасности видит клавиатуру. Все довольны. Кроме, возможно, здравого смысла.

Проект выложил здесь:

https://github.com/webzuweb/CodeKey/

Он open source, сейчас это MVP, поэтому особенно интересно услышать людей из банков, крупных корпораций, ИБ и разработки.

Первый вопрос: разрешили бы вы подобное устройство внутри своей инфраструктуры, если AI работает на корпоративном endpoint и наружу вообще ничего не уходит?

Второй: если нет — какое решение вы считаете правильным для разработчика в полностью закрытом контуре?

И третий, ради которого, собственно, мы с товарищем всё ещё спорим:

Какую долю кода через два года программисты всё ещё будут писать руками?

Моя ставка — очень небольшую.

Товарищ из банка пока держится.

Посмотрим.

ссылка на оригинал статьи https://habr.com/ru/articles/1079800/