
По пути на презентацию я в очередной раз просматривал функции приложения и заметил небольшой баг. Ноутбука под рукой не оказалось, а исправить его нужно было срочно. Я вспомнил про тестовый стенд с онлайн-IDE, развернул там нужные инструменты и прямо с планшета оперативно поправил код.
Я мог бы закончить историю на этом, но идея мобильной разработки не давала мне покоя: получается, имея под рукой планшет с большим экраном, вы можете организовать полноценный рабочий процесс. Правда, инструменты для сборки, тестирования и работы с SDK обычно выпускают только для ПК. А можно ли скомпилировать код прямо на смартфоне? Можно — например, в ALT Mobile или «Авроре ОС», если установить дополнительные пакеты. Но удобно ли это? Любителям Vim — вполне.
Среди веб-решений (GigaIDE, GitLab Web IDE и другие) мне больше всего нравится code-server (coder) — полноценная веб-версия Visual Studio Code, которая поддерживает большинство привычных плагинов. В статье я подробно расскажу, как развернуть облачную среду разработки, привязать ее к планшету и написать собственный плагин для автоматизации сборки под «Аврору ОС».
Настройка coder
Среду coder я разворачивал в рамках эксперимента по созданию удаленного рабочего места. Это не стало целевым решением, но виртуальная машина продолжала крутиться для других экспериментов. Серверу coder минимально требуется 1 ГБ ОЗУ и 2 ядра, однако для ускорения сборки приложения стоит увеличить эти параметры, хотя бы 4 ядра и 4 ГБ ОЗУ.
Формально code-server и сборочную среду можно упаковать в Docker, монтируя папки с проектами. Однако Aurora Platform SDK для работы с flutter-aurora штатно рассчитан на запуск вне контейнерной среды. Сценарий с Docker подходит для быстрой проверки гипотез, но для стабильной повседневной разработки лучше разворачивать SDK и IDE нативно на хост-системе.
Перед развертыванием IDE необходимо установить сам Aurora Platform SDK. Сделать это можно двумя способами:
Установить вручную по официальной инструкции (я предпочитаю этот вариант);
Или установить автоматически прямо через плагин для VS Code.
После подготовки SDK переходим к развертыванию code-server. Разработчики подготовили удобный скрипт автоматической установки:
curl -fsSL https://code-server.dev/install.sh | sh
В процессе работы скрипт затребует права sudo. По завершении инсталляции в консоли появится инструкция по добавлению сервера в systemd — это нужно, чтобы coder автоматически запускался после ребута.
Запустим службу от имени нашего пользователя и проверим сгенерированный пароль для входа в веб-интерфейс. При необходимости пароль в файле ~/.config/code-server/config.yaml можно сразу изменить на свой:
sudo systemctl enable --now code-server@$USER cat ~/.config/code-server/config.yaml
По умолчанию code-server запущен и доступен только внутри виртуальной машины (127.0.0.1:8080). Чтобы организовать доступ к Web IDE с других устройств через интернет, необходимо либо пробросить порт по SSH, либо настроить одно из прокси-решений.
Мне понравился вариант с Caddy: он настраивается буквально в пару строк и берет на себя управление SSL-сертификатами.
Установка Caddy
Выполним установку из официального репозитория:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy
Конфигурация прокси
Откроем файл конфигурации /etc/caddy/Caddyfile и добавим в него строки следующего вида:
coder.doman.ru { reverse_proxy 127.0.0.1:8080 tls /etc/caddy/code_ssl/fullchain.cer /etc/caddy/code_ssl/coder.key }
Здесь coder.doman.ru — ваше доменное имя для сервера coder, 127.0.0.1:8080 – адрес и порт из конфигурации, а ~/.config/code-server/config.yaml, /etc/caddy/code_ssl – путь к файлам цепочки сертификатов и приватного ключа.
Если у вас есть публичный домен, сертификат проще всего выпустить с помощью скрипта acme.sh. Достаточно запустить скрипт, получить TXT запись, добавить ее на стороне регистратора доменов и минут через 15 перезапросить ключи.

Перенос домена по 1 ₽
С легкостью переходите в Selectel от любого другого провайдера. Сайт продолжит работать без остановки.
Если домена нет или доступ идет по IP-адресу (например, без управляемого DNS в VPN-сети), можно сгенерировать самоподписанный сертификат. Учитывайте, что браузер будет выдавать предупреждение о недействительном сертификате, но соединение все равно останется зашифрованным. Сгенерировать пару «ключ + сертификат» можно следующей командой:
sudo mkdir -p /etc/caddy/code_ssl sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/caddy/code_ssl/coder.key -out /etc/caddy/code_ssl/fullchain.cer -subj "/CN=10.0.40.203" sudo chown -R caddy:caddy /etc/caddy/code_ssl sudo chmod 600 /etc/caddy/code_ssl/coder.key sudo chmod 644 /etc/caddy/code_ssl/fullchain.cer sudo systemctl restart caddy
На этом настройка сервера завершена. Перейдите в браузере вашего планшета по указанному домену или IP-адресу, введите пароль из config.yaml — и перед вами откроется полноценная облачная среда разработки, готовая к установке плагинов, языковых пакетов и сборке проектов.

Новый плагин
Плагины для VS Code разрабатываются на TypeScript. Это относительно простой язык программирования, с помощью которого можно автоматизировать процессы, вызывать системные команды, работать с файлами, верстать графический интерфейс и многое другое. Остается только определиться с задачами и реализовать их в коде.

Для начала соберем плагин Hello World. В первую очередь необходимо установить yo (генератор шаблонов) и generator-code (расширение для yo, предназначенное для генерации плагинов VS Code):
npm install -g yo generator-code
А также инструментарий для упаковки и сборки пакетов:
npm install -g vsce
Не хотите устанавливать Node.js и другие инструменты для сборки и разработки плагинов на TypeScript? Не беда, если у вас установлен Docker (Docker Desktop на macOS и Windows):
DOCKER_BUILDKIT=1 docker build --tag codegen "https://github.com/Microsoft/vscode-generator-code.git#main" DOCKER_BUILDKIT=1 docker build --tag vsce "https://github.com/microsoft/vscode-vsce.git#main"
Далее вызываем следующие команды для генерации и сборки:
docker run -it -v $(pwd):/usr/src/app codegen docker run --rm -it -v "$(pwd)":/workspace vsce publish
Теперь запускаем генератор. Этот интерактивный мастер задокументирует ответы на несколько вопросов, чтобы создать правильную структуру проекта и обеспечить удобство дальнейшей разработки плагина. Он автоматически сгенерирует директорию проекта в соответствии с указанным вами названием.
✔ What type of extension do you want to create? New Extension (TypeScript) ✔ What's the name of your extension? hello-world-plugin ✔ What's the identifier of your extension? hello-world-plugin ✔ What's the description of your extension? This is an example plugin. ✔ Initialize a git repository? Yes `list` prompt is deprecated. Use `select` prompt instead. ✔ Which bundler to use? unbundled `list` prompt is deprecated. Use `select` prompt instead. ✔ Which package manager to use? npm
Если вы не любите интерактивные формы ввода, можно сгенерировать конфигурацию одной строкой (не работает при использовании Docker):
yo code ./hello-world-plugin -t=ts -q
После генерации откройте созданную папку в VS Code и нажмите F5 — запустится окно отладки с вашим плагином.

Как это работает
Весь основной код описан в файле src/extension.ts:
import * as vscode from 'vscode'; export function activate(context: vscode.ExtensionContext) { console.log('Congratulations, your extension "hello-world-plugin" is now active!'); const disposable = vscode.commands.registerCommand('hello-world-plugin.helloWorld', () => { vscode.window.showInformationMessage('Hello World from hello-world-plugin!'); }); context.subscriptions.push(disposable); } export function deactivate() {}
В первую очередь импортируется API VS Code — именно с ним взаимодействует плагин для регистрации команд, отображения диалоговых окон, кнопок и элементов интерфейса.
При инициализации плагина VS Code вызывает функцию activate(). В рамках процедуры активации срабатывает метод registerCommand(), в котором указываются уникальный идентификатор команды и исполняемая им функция.
Чтобы команду можно было вызвать из палитры вводом команды (Ctrl+Shift+P / Cmd+Shift+P), ее необходимо добавить в файл package.json (здесь же находятся название плагина, его описание, версия и зависимости). В разделе contributes указываются сама команда и ее название для пользователя:
"contributes": { "commands": [ { "command": "hello-world-plugin.helloWorld", "title": "Hello World" } ] },
Архитектура плагина
Теперь перейдем к основной реализации. Функциональность плагина я разделяю на три логических блока:
Управление устройствами: добавление девайса с описанием, вызов консоли конкретного устройства, отправка файлов и установка приложения на него.
Управление проектом: базовые функции Flutter (создание проекта, запуск анализатора и тестов) и сборка приложения под каждую архитектуру. В этом блоке важно учитывать особенности
flutter-aurora, например передачу названия организации.Инструменты: настройки плагина и списка устройств (изменение IP-адресов, комментариев), а также функциональность подписания пакета сертификатами разработчика и организации.
Добавляем интерфейс (боковую панель)
Чтобы не искать команды в палитре и не вводить их вручную, добавим боковую панель (View Container) с несколькими представлениями.
Для этого внесем в раздел contributes файла package.json следующую запись:
"viewsContainers": { "activitybar": [ { "id": "aurora-sidebar", "title": "Flutter for Aurora OS", "icon": "media/sidebar-icon.svg" } ] }, "views": { "aurora-sidebar": [ { "id": "aurora-devices-view", "name": "Устройства" }, { "id": "aurora-project-view", "name": "Проект" }, { "id": "aurora-tools-view", "name": "Инструменты" } ] },

Простые действия с Flutter
Теперь нужно заполнить созданные представления функциями. Самое простое и быстрое — продублировать базовые команды flutter из консоли: создание проекта, добавление платформы, сборку под нужную архитектуру и запуск тестов.
Сначала зарегистрируем команды и настроим их отображение в интерфейсе:
export function registerProjectCommands(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.commands.registerCommand('ffa.create', createProject), vscode.commands.registerCommand('ffa.addPlatform', addAuroraPlatform), vscode.commands.registerCommand('ffa.pubGet', pubGet), vscode.commands.registerCommand('ffa.analyze', analyze), vscode.commands.registerCommand('ffa.test', runTests), vscode.commands.registerCommand('ffa.build', (arch: string) => { if (arch) build(arch); }) ); } … export class ProjectProvider implements vscode.TreeDataProvider<vscode.TreeItem> { getTreeItem(element: vscode.TreeItem) { return element; } getChildren(): vscode.ProviderResult<vscode.TreeItem[]> { const items = [ { label: 'Создать проект', cmd: 'ffa.create', icon: 'new-folder', args:[] }, { label: 'Добавить платформу Аврора', cmd: 'ffa.addPlatform', icon: 'call-incoming', args:[] }, { label: 'Pub Get', cmd: 'ffa.pubGet', icon: 'cloud-download', args:[] }, { label: 'Анализатор', cmd: 'ffa.analyze', icon: 'beaker', args:[] }, { label: 'Запуск тестов', cmd: 'ffa.test', icon: 'pass', args:[] }, ...ARCHITECTURES.map(arch => ({ label: arch.displayName, cmd: 'ffa.build', icon: 'play', args: [arch.label] })) ]; return items.map(i => { const item = new vscode.TreeItem(i.label); item.command = { command: i.cmd, title: i.label, arguments: i.args }; item.iconPath = new vscode.ThemeIcon(i.icon); return item; }); } }
Чтобы не перечислять варианты сборки в виде нескольких однотипных команд, вынесем список архитектур в отдельный массив:
const ARCHITECTURES = [ { label: 'aarch64', displayName: 'Сборка (aarch64)', psdkArch: "aurora-arm64" }, { label: 'armv7', displayName: 'Сборка (armv7)', psdkArch: "aurora-arm" }, { label: 'x86_64', displayName: 'Сборка (x86_64)', psdkArch: "aurora-x64" } ];
Далее опишем сами функции и их аргументы. Так как вызов команд консоли будет выполняться регулярно с разным набором параметров, для него создана небольшая вспомогательная обертка runCommand().
Самая объемная операция в этом блоке — сборка проекта. Из переданного аргумента выбирается целевая архитектура, а ее псевдоним подставляется в параметр --target-platform:
function pubGet() { runCommand(flutterAurora, ['pub', 'get'], "AuroraFlutter"); } function analyze() { runCommand(flutterAurora, ['analyze', '--no-fatal-infos'], "AuroraFlutter"); } function runTests() { runCommand(flutterAurora, ['test'], "AuroraFlutter"); } export function build(arch: string) { const archInfo = ARCHITECTURES.find(a => a.label === arch); if (!archInfo) return; runCommand(flutterAurora, ['build', 'aurora', '--release', `--target-platform=${archInfo.psdkArch}`], "AuroraFlutter"); }
Мастер создания проекта
Чтобы сделать процесс создания нового проекта более удобным, добавим немного «волшебства» — интерактивный мастер (Wizard). Поля, которые необходимо заполнить: название проекта, целевая папка и (опционально) идентификатор организации (по умолчанию для ОС «Аврора» используется ru.aurora).
API VS Code позволяет легко реализовать такие диалоговые окна с помощью vscode.window.showInputBox и vscode.window.showOpenDialog:
async function createProject() { const appName = await vscode.window.showInputBox({ prompt: 'Название проекта', value: 'app_demo', validateInput: (text) => !text?.trim() ? 'Название не может быть пустым' : null }); if (!appName) return; // escape const org = await vscode.window.showInputBox({ prompt: 'Организация', value: readAuroraConfig().developer?.app_prefix || 'ru.aurora', validateInput: (text) => !text?.trim() ? 'Организация не может быть пустой!' : null }); if (!org) return; const parentDirUri = await vscode.window.showOpenDialog({ canSelectFiles: false, canSelectFolders: true, canSelectMany: false, openLabel: 'Выберите папку для создания проекта' }); if (!parentDirUri || parentDirUri.length === 0) return; …
Аналогичным образом реализован класс ToolsProvider — представление для дополнительных инструментов. Он позволяет открывать настройки плагина, редактировать IP-адреса и параметры подключенных устройств, а также подписывать собранный RPM-пакет сертификатом разработчика или организации.

Мобильная ферма Selectel
Запустите тесты на реальных Android‑ или iOS‑устройствах.
Реверс IDE
Примерно по той же логике добавлен и класс DeviceProvider. Он содержит функции, которые выполняются непосредственно в связке с самим устройством:
Обмен SSH-ключами: упрощает подключение и позволяет в дальнейшем не вводить пароль (при использовании ключа без фразы-пароля);
SSH-терминал: для отладки и подключения к устройству;
Отправка файлов и пакетов приложения: загрузка собранных файлов на устройство;
Управление приложением: установка, запуск, просмотр логов и остановка процесса.
Каждая операция должна выполняться на конкретном устройстве по его IP-адресу. Перечень кнопок и устройств формируется из JSON-файла, а для его заполнения предусмотрено простое интерактивное меню:
export async function addDevice() { const host = await vscode.window.showInputBox({ prompt: 'Имя устройства (напр. R570E)' }); if (!host) return; const hostname = await vscode.window.showInputBox({ prompt: 'IP адрес устройства' }); if (!hostname) return; const archPick = await vscode.window.showQuickPick([ { label: 'aarch64', detail: '64-bit ARM' }, { label: 'armv7', detail: '32-bit ARM' }, { label: 'x86_64', detail: 'x86_64' } ], { placeHolder: 'Архитектура' }); if (!archPick) return; const devices = readDevices(); devices.push({ host: host.trim(), hostname: hostname.trim(), user: 'defaultuser', arch: archPick.label }); writeDevices(devices); vscode.window.showInformationMessage(`Устройство "${host}" добавлено.`); }
Компания ОМП уделяет много внимания поддержке сообщества. В частности, они адаптировали популярную open-source IDE Qt Creator под нужды ОС «Аврора», заложив в нее готовые инструменты для сборки, доставки, установки и запуска приложений.
Доставить собранное приложение на устройство проще всего: достаточно передать полученный RPM-пакет по SSH командой scp:
runCommand('scp', ['-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', rpmPath, `${device.user}@${device.hostname}:${remotePath}`], "Deploy");
Далее начинаются нюансы. Установить пакет привычной командой rpm -i без повышения привилегий не так просто. Конечно, можно каждый раз запрашивать у пользователя пароль root, но это неудобно. Другой вариант — использовать утилиту sfdk.
Однако есть более изящное, неочевидное, но простое решение: установка пакета через встроенный системный сервис. Для этого достаточно отправить запрос службе ru.omp.APM через системную шину DBus:
setTimeout(() => { runCommand('ssh', ['-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', `${device.user}@${device.hostname}`, `gdbus call -y -d ru.omp.APM -o /ru/omp/APM -m ru.omp.APM.Install ${remotePath} '{}'`], "Deploy"); }, 2000);
Занимательный факт: один из разработчиков ОМП опубликовал аналогичный подход на платформе CSDN.
Заключительный шаг — запуск приложения в пользовательском или отладочном режиме. Для этого используется системная утилита на устройстве или в эмуляторе (доступная также через DBus):
let sshCommand: string; if (isDebug) { sshCommand = `/usr/bin/runtime-manager-tool Control startDebug ${appId} --output-to-console -e 'AURORA_APP_ID=${appId}' -e 'AURORA_PACKAGE_NAME=${appId}'`; } else { sshCommand = `/usr/bin/runtime-manager-tool Control start ${appId}`; }
Сборка, установка
После отладки и фиксации мелких проблем, небольшого рефакторинга и обратной связи от друзей плагин можно собрать и установить в среду разработки.
Сборка выполняется стандартной командой:
npx @vscode/vsce package
Программа vsce выполнит валидацию файлов и соберет пакет плагина в папку out. Чтобы пройти проверку пакета при наличии локальных ключей и сертификатов, добавлен флаг --allow-package-secrets privatekey.
Вы также можете опубликовать плагин в официальном маркетплейсе VS Code (инструкция доступна в документации). После публикации расширение проходит автоматическую проверку и становится доступно для установки в течение нескольких минут.

Финальный этап — установка плагина. Для онлайн- и офлайн-сред поддерживается установка как из локального файла, так и напрямую из маркетплейса:
code --install-extension ffa-0.0.3.vsix # установить из файла code --install-extension techvlad.ffa # установить из маркетплейса (если расширение туда загружено)
После установки вы получаете полностью рабочий инструмент в интерфейсе вашей IDE:

Исходный код плагина опубликован в открытом Git-репозитории. Вы можете скачать его, изучить архитектуру или адаптировать под свои задачи.
Заключение
Описанный вариант мобильного рабочего места не является абсолютной заменой классической десктопной среды: необходимо поддерживать сервер, организовывать безопасный доступ и иметь стабильное подключение к интернету. Тем не менее это отличное резервное решение для работы «в поле» или экстренной отладки.
Под подобные задачи всегда можно разработать собственный плагин: достаточно немного времени, и вот рутинные консольные команды легко превращаются в понятные кнопки интерфейса. Это напоминает создание специализированной оснастки для обработки деталей. Представленный плагин — лишь наглядная демонстрация того, что автоматизация VS Code доступна каждому. В целом, типовой список команд и сценариев можно доверить нейросети: она сгенерирует базовый шаблон, после чего останется лишь отладить логику и собрать готовый VSIX-пакет.
Комментарии (2)

TimReset
27.08.2026 11:35Вот тут я на андроид планшете запускал локально idea и компилил и дебажил java и rust
https://habr.com/en/articles/757222/
punhin
Интересная статья. Жаль только, что сама по себе Аврора - редкая птица на устройствах в России. С одной стороны, на хабре где-то год назад видел цифру, что число устройств на Авроре перевалило за 500 тысяч, при этом объёмы производства по сведениям Минпромторга составляют 60-80 тысяч в год. Хотя опять же - звучат высказывания о том, что учителям и медикам в ближайшем будущем будут выданы устройства на Авроре, и тогда их общее число увеличится до полутора миллионов. С другой стороны - свободная продажа аппаратов исчисляется очень скромными тысячами устройств в год, и оно понятно - ОС корпоративная, с защитами соответствующего класса и всё такое. Так что по популярности ОС Аврора вполне сопоставима с... ну, например, Ubuntu touch, который я сейчас мучаю в свободное от других занятий время.