# Claude Meter Минимальное Wear OS приложение для **Galaxy Watch 6 Classic** (и любых Wear OS 3+). Показывает утилизацию rate-limit Claude Code прямо на часах — 5h и 7d окна. 灵感: [Clawdmeter](https://github.com/HermannBjorgvin/Clawdmeter) — но на часах, без ESP32 и без ПК-демона. ## Архитектура ``` ┌─────────────────┐ Data Layer API ┌──────────────────┐ │ mobile (телефон) │ ──────────────────▶ │ wear (часы) │ │ │ /token │ │ │ • ввод OAuth │ │ • опрос API │ │ • спаривание │ │ • Compose UI │ │ • установка APK │ ──── WiFi ADB ──────▶ │ • EncryptedShared │ │ │ pair → connect → │ Preferences │ │ │ pm install │ │ └─────────────────┘ └──────────────────┘ ``` ## Модули | Модуль | Назначение | |--------|-----------| | `wear/` | Часы: Compose for Wear UI, HTTP-опрос `api.anthropic.com`, хранение токена | | `mobile/` | Телефон: ввод токена, отправка через Data Layer API, ADB-спаривание + установка | ## Сборка ```bash gradlew assembleDebug ``` APK: - `mobile/build/outputs/apk/debug/mobile-debug.apk` — телефон (38 МБ, включает wear APK в assets) - `wear/build/outputs/apk/debug/wear-debug.apk` — часы (22 МБ) ## Установка и использование ### Шаг 1: Установить mobile-приложение на телефон ```bash adb install mobile/build/outputs/apk/debug/mobile-debug.apk ``` ### Шаг 2: Спаривание с часами 1. На часах: **Settings → Developer options → Wireless debugging → «Pair device with pairing code»** 2. На телефоне в приложении **Claude Meter Setup**: - Ввести IP часов (виден на экране Wireless debugging) - Ввести pairing порт (виден на экране pairing) - Ввести 6-значный код - Нажать «Спарить» 3. Дождаться «✅ Спарено!» ### Шаг 3: Установка приложения на часы 1. На часах: вернуться на главный экран Wireless debugging (виден session порт) 2. На телефоне: ввести session порт → «Установить на часы» 3. APK пушится через `shell:cat` и устанавливается через `pm install` ### Шаг 4: Отправка токена 1. На ПК: найти `accessToken` в `~/.claude/.credentials.json` 2. На телефоне: вставить токен → «Отправить токен» 3. На часах: открыть **Claude Meter** → видит проценты ## Технические детали ### API Опрашивает `https://api.anthropic.com/v1/messages` — POST (haiku, max_tokens=1). Rate-limit заголовки: - `anthropic-ratelimit-unified-5h-utilization` (0–1) — 5-часовое окно - `anthropic-ratelimit-unified-5h-reset` (unix timestamp) — сброс 5h - `anthropic-ratelimit-unified-7d-utilization` (0–1) — 7-дневное окно - `anthropic-ratelimit-unified-7d-reset` (unix timestamp) — сброс 7d - `anthropic-ratelimit-unified-5h-status` — статус (ok/throttled/blocked) ### WiFi ADB Использует [libadb-android](https://github.com/MuntashirAkon/libadb-android) — полный ADB протокол на Kotlin: - **SPAKE2 pairing** — ключевой обмен с 6-значным кодом - **TLS 1.3** — через Conscrypt - **RSA 2048** — самоподписанный X.509 сертификат, хранится в `filesDir` - **HiddenApiBypass** — доступ к `android.sun.security.x509.*` Поток: pair (pairing port + code) → connect (session port) → push APK → `pm install` ### Стек | Компонент | Технология | |-----------|-----------| | UI (wear) | Compose for Wear, ScalingLazyColumn | | UI (mobile) | Compose Material3 | | HTTP | `HttpURLConnection` (stdlib) | | Хранение токена | `EncryptedSharedPreferences` | | Передача токена | Wearable Data Layer API | | ADB | libadb-android (SPAKE2 + TLS) | | TLS | Conscrypt | | Build | AGP 8.7.3, Gradle 8.13, Kotlin 1.9.22, compileSdk 35 | ## Структура проекта ``` ClaudeMeter/ ├── settings.gradle.kts # :mobile, :wear ├── build.gradle.kts # AGP 8.7.3, Kotlin 1.9.22 ├── gradle.properties ├── gradle/wrapper/ ├── mobile/ │ ├── build.gradle.kts # libadb-android, Conscrypt, Compose, Data Layer │ └── src/main/ │ ├── AndroidManifest.xml │ └── java/com/eps/claudemeter/ │ ├── App.kt # HiddenApiBypass + Conscrypt init │ ├── AdbConnectionManager.kt # RSA ключ + X.509 сертификат │ └── MainActivity.kt # UI: токен + спаривание + установка ├── wear/ │ ├── build.gradle.kts # Compose for Wear │ └── src/main/ │ ├── AndroidManifest.xml │ └── java/com/eps/claudemeter/ │ ├── ApiPoller.kt # HTTP-опрос + парсинг заголовков │ ├── TokenStore.kt # EncryptedSharedPreferences │ ├── TokenReceiverService.kt # WearableListenerService │ └── MainActivity.kt # Compose for Wear UI └── README.md ``` ## Ограничения (v0) - Обновление по тапу, не фоновое (WorkManager — отложено) - Нет complication (виджет на циферблате — отложено) - Токен протухает → нужно перепастить на телефоне