Краб живёт внутри телефона
Daniel получил root на Xiaomi Mi 8, поместил OpenCrabs в Ubuntu chroot прямо на устройстве и подключил к нему приложение на Flutter по ACP. Дальше краб сам написал Android-приложение, собрал APK на телефоне через aapt2, javac, d8 и apksigner и установил его. Без ПК, без облака, без Gradle, без SDK.
Кто-то говорит, что Flutter отстой… ага (ирония) @opencrabs внутри телефона, связан по a2a с кастомным приложением на flutter. Он может менять ОС. Может написать android-приложение, скомпилировать и открыть… всё внутри этого чёртова телефона
Первое приложение, полностью собранное внутри телефона с помощью @opencrabs, да, код написан в телефоне, apk собран и открыт. Компьютер не нужен ;)
Устройство: Xiaomi Mi 8 (dipper), Android 10 / API 29, MIUI 12, aarch64, ядро 4.9.186, 5,6 ГБ ОЗУ. Root брался из самого boot-образа: Magisk патчит его на телефоне, fastboot прошивает, а верификатор распаковывает результат и смотрит на ramdisk вместо того, чтобы доверять логу патча. Прямо сейчас: magisk -c выдаёт 30.7:MAGISK:R.
Перенести Linux userland на Android удалось со второй попытки. Первое поколение ставило бинарник aarch64-linux-android как модуль Magisk со скриптом-супервизором, а это означало порт cfg из 59 файлов и борьбу glibc против musl. Второе поколение, то, что работает сегодня, это chroot с Ubuntu 24.04.5 на glibc 2.39, как раз то, что нужно выпущенному бинарнику linux-arm64. Ловушка, которая съела больше всего времени: /apex представляет собой tmpfs из отдельных bind-монтирований, поэтому один bind на /apex копирует пустой каталог, и любой Android-бинарник умирает с «required file not found», что выглядит как ошибка прав, а на деле означает отсутствующий интерпретатор. Лечится тем, что каждый элемент /apex/* монтируется отдельно.
Дальше приложение. Daniel хотел интерфейс диалога, который ему нравится в вебе, но собранный нативно на Flutter, а не в WebView. Поэтому приложение говорит по ACP (JSON-RPC 2.0 поверх stdio) с opencrabs acp, запущенным в chroot, тем же протоколом, что использует TUI: живые куски рассуждений, карточки инструментов, запросы разрешений, расход токенов. Без браузера, без сервера, без открытого порта.
- Переживает перезагрузку, и телефон при этом никто не трогает: задача JobScheduler, которая безусловно перевзводит себя, сервисный хук, который ждёт
sys.boot_completedи заново поднимает семь монтирований, и цикл, который повторно применяет appops MIUI для простоя и автозапуска, потому что powerkeeper снимает исключение из оптимизации батареи примерно через 20 с после загрузки - Доказательство, из logcat после настоящей перезагрузки: рукопожатие ok на 12 с, сервис поднят, исключение для батареи зафиксировано, затем headless-самотест 12 пройдено / 0 провалено, GREEN за 3,7 с, покрывающий версию бинарника, оболочку, сессии, обвязку загрузки, состояние сервиса, исключение батареи, распознавание голоса, разрешение на микрофон, привязку виджета, готовность ACP и реальный промпт
- APK, собранный на телефоне: MIUI поставляет свою плитку записи экрана с заглушкой всего на 20 КБ, поэтому нажатие открывает магазин приложений и ничего не записывает. Краб написал настоящую плитку быстрых настроек, собрал её в шесть шагов без Gradle и без SDK manager и поставил в панель рядом с WiFi. 12 784 байта.
- Цепочка сборки:
aapt2 compile→aapt2 link→javac --release 8противandroid.jar→d8из R8 → заворачиваем dex в zip →zipalign→apksigner signиverify - Установлено изнутри chroot, пакетный менеджер Android достигнут через
nsenter -t 1 -m, затем выданы права root записью строки политики Magisk, а в шторку плитка добавлена черезcmd statusbar add-tile - Одно тело, два мозга: ACP это stdio, и
ssh -Tтоже stdio, поэтому телефон может смотреть на Mac в локальной сети без моста и без открытого порта. Замерено:initializeза 1,2 с, удалённый список из 40 сессий, самотест 9/9 GREEN против удалённого мозга
Главное: плитка сама ничего не записывает. Она через su от Magisk вызывает тот же бинарник рекордера в chroot, который использует команда /rec в чате, так что рекордер один, файл состояния один, папка вывода одна. Краб написал Android-приложение, которое является рукояткой для Linux-инструмента внутри того же телефона. Приложение это палец, краб это мозг. Вот и вся архитектура проекта, в 13 КБ.
Лог рассуждений из той сессии это та деталь, которую стоит сохранить: краб остановился, чтобы проверить, действительно ли он на телефоне, и подтвердил это по среде выполнения, а не предположил.