Cobalt — открытая платформа приложений для электронных книг Kobo: лаунчер, подписанный магазин приложений (App Store), Rust SDK и рантайм, который держит каждое приложение в собственном непривилегированном процессе.
Установка выполняется один раз через USB. После этого каждое приложение устанавливается, обновляется и удаляется прямо на устройстве по Wi-Fi. Перезагрузка возвращает штатный интерфейс Kobo.
Проект не аффилирован с Rakuten Kobo.
Работа на реальном Kobo
Каждое приложение — это статический бинарник под ARM, работающий как отдельный непривилегированный процесс на штатном железе. App Store устанавливает, обновляет и удаляет приложения по Wi-Fi, проверяя подписи перед каждым запуском.
Статьи arXiv и агенты для написания кода — прямо на экране
Приведённые скриншоты сделаны с реального устройства, а не в эмуляторе. Приложение arXiv читает HTML-версию, которую arXiv публикует для каждой статьи начиная с декабря 2023 года: аннотации, разделы, формулы и таблицы результатов, разбитые на страницы под размер экрана.
Приложения
Каждый скриншот ниже сделан на Kobo Clara BW. Приложения из магазина версионируются независимо от платформы; остальные поставляются вместе с установкой платформы.
Launcher
Открывает установленные приложения и всегда сохраняет путь обратно к штатному ридеру Kobo.
App Store
Устанавливает, обновляет, удаляет и переустанавливает подписанные приложения по Wi-Fi.
arXiv
Просматривает новейшие препринты по теме и читает полный текст прямо на экране.
Sudoku
Доступно только через магазин по замыслу: установка доказывает доставку приложения, которого нет в исходном USB-пакете.
Morse
Передаёт набранное сообщение азбукой Морзе через подсветку экрана, буква за буквой на весь экран.
Audiobook Studio
Исследует тему, пишет текст, озвучивает и воспроизводит оригинальную аудиокнигу.
Gutenbird
Читает любую OPDS-библиотеку: Project Gutenberg, Standard Ebooks, Open Library или собственную.
Hacker News
Разделы Top, New, Ask и Show с полными ветками комментариев.
Feeds
Находит RSS-ленту сайта и показывает статьи без исходной вёрстки страницы.
Daily Brief
Собирает новости дня в фоне, пока используется другое приложение.
AI Command Center
Задаёт вопрос и превращает ответ в текст, удобный для чтения с сенсорным управлением.
Sidekick
Одобряет или отклоняет запросы от агентов, пишущих код, не отрываясь от клавиатуры компьютера.
Terminal
Нативная для экрана оболочка, где клавиши мгновенно отправляют ввод.
Components
Элементы управления, макеты, типографика и состояния UI-набора инструментов на экране.
Settings
Подключение, оборудование и обновления платформы — отдельно от магазина.
Todo
Постоянный список с сенсорным вводом и отметкой выполненных пунктов.
Tic-tac-toe
Два игрока, частичное обновление отдельных ячеек поля.
Magnet
Находит датчик Холла за корпусом ридера и сообщает об изменении его состояния.
SDK: приложение — это один файл на Rust
Разработчику нужно реализовать трейт KoboApp, описать экраны декларативно — остальное берёт на себя рантайм: раскладку, планирование обновления e-ink дисплея, навигацию назад и жизненный цикл приложения.
Приложения не открывают ресурсы устройства напрямую — они запрашивают доступ. Сеть, хранилище, аудио, подсветка и Wi-Fi защищены системой разрешений, а отказ возвращается как значение, которое приложение может обработать.
- E-ink интерфейс
- Текст, плитки, диалоги, клавиатуры, пагинация, планирование частичного обновления экрана
- Симуляторы
- Симуляторы в браузере и в рантайме с диагностикой раскладки
- Асинхронные операции
- HTTPS, докачка по диапазонам, отменяемые задачи, запланированные пробуждения
- Состояние
- Атомарное хранилище данных для каждого приложения по ключам
- Публикация
- Подписанные статические бинарники под ARMv7, публикуемые при слиянии PR приложения
kobo new my-app
cd my-app
kobo dev
use kobo_sdk::{
ActionId, Context, KoboApp, ScreenBuilder,
};
#[derive(Default)]
struct Hello { taps: u32 }
impl KoboApp for Hello {
fn on_start(&mut self, ctx: &mut Context) {
self.show(ctx);
}
fn on_action(
&mut self, ctx: &mut Context, a: ActionId,
) {
if a == kobo_sdk::action_id("tap") {
self.taps += 1;
}
self.show(ctx);
}
}
impl Hello {
fn show(&self, ctx: &mut Context) {
let screen = ScreenBuilder::new("hello")
.top_bar("Hello")
.heading(format!("{} taps", self.taps))
.button("tap", "Tap me")
.build();
ctx.set_screen(screen);
}
}
fn main() {
let app = Hello::default();
let _ = kobo_sdk::run("hello", app);
}
Магазин: подписанные пакеты, проверенные перед запуском
App Store читает подписанный каталог из фиксированного GitHub-релиза. Каждый пакет содержит один исполняемый файл под ARM и подписанный манифест. Рантайм проверяет каталог, пакет, установленный манифест и сам бинарник перед каждым запуском приложения.
Релизы приложений не зависят от релизов платформы: слияние PR с приложением собирает его под ARM, подписывает и обновляет каталог. Не требуется ни повышение версии Cobalt, ни переустановка — приложение просто появляется в магазине.
Сама платформа Cobalt также обновляется по Wi-Fi, через раздел Settings, по отдельному от каталога приложений каналу. USB-кабель нужен лишь однажды.
Транзакции установки и обновления каталога устойчивы к сбоям: прерванное обновление оставляет ридер с прежней версией.
Установка из исходников
- Зарядите Kobo Clara BW (N365) и подключите его по USB. Другие модели отклоняются платформой, а не определяются приблизительно.
- Запустите настройку:
git clone https://github.com/BandarLabs/Cobalt.git
cd Cobalt
rustup target add armv7-unknown-linux-musleabihf
cargo run -p kobo-cli -- setup
- Перезапустите ридер и откройте Cobalt в меню Kobo.
- Откройте Store. Дальше всё происходит по Wi-Fi.
Полная инструкция, включая шаги восстановления, доступна в документации проекта на GitHub.
Как добавить своё приложение
Вклад в виде нового приложения оформляется как обычный pull request. Если оно работает на реальном устройстве и PR это подтверждает — оно будет принято и опубликовано.
- Разработать приложение. Добавить его как пакет workspace в
apps/<app-id>/и зарегистрировать вapps/catalog.json. - Протестировать. Добавить модульные тесты и тесты раскладки, запустить в симуляторах браузера и рантайма.
- Запустить на собственном устройстве. На реальном Clara BW, а не только в симуляторе.
- Открыть PR с гифкой или фотографиями работы приложения. После проверки и слияния процесс публикации подпишет пакет, и он появится в магазине — без отдельного релиза платформы.
Владельцам других моделей Kobo также рады: портирование приветствуется, но сначала стоит открыть issue, чтобы согласовать профиль устройства.
Поддержка устройств и безопасность
Cobalt не заменяет загрузочную цепочку Kobo. Запись на устройство разрешена только при точном совпадении модели оборудования и версии прошивки, а перезагрузка возвращает штатный ридер. Первая установка изменяет файлы в пользовательском разделе хранилища и предоставляется без каких-либо гарантий.
Аппаратно протестирован только профиль Clara BW. Установка на другие модели не рекомендуется до появления проверенного и протестированного на железе профиля. Cobalt — независимый проект, не связанный с Rakuten Kobo.