docs: full README with architecture, setup, tech details

This commit is contained in:
wenil
2026-06-19 11:44:18 +03:00
parent 4083609b12
commit bc415ce6a1
+128 -69
View File
@@ -1,77 +1,136 @@
# Claude Meter — лимит Claude Code на часах
# Claude Meter
Минимальное Wear OS приложение для Galaxy Watch 6 Classic (и любых Wear OS 3+).
Опрашивает `api.anthropic.com` так же, как [Clawdmeter](https://github.com/HermannBjorgvin/Clawdmeter),
но без ESP32/демона/BLE — часы ходят на API сами по WiFi.
Минимальное Wear OS приложение для **Galaxy Watch 6 Classic** (и любых Wear OS 3+).
Показывает утилизацию rate-limit Claude Code прямо на часах — 5h и 7d окна.
Показывает:
- **5h** — загрузка 5-часового окна (%) и минуты до сброса
- **7d** — загрузка недельного окна (%) и минуты до сброса
- **status** — `normal` / `banned` / `unknown`
灵感: [Clawdmeter](https://github.com/HermannBjorgvin/Clawdmeter) — но на часах, без ESP32 и без ПК-демона.
Цвет: зелёный <70%, янтарь 7090%, красный ≥90%.
## Архитектура
## Архитектура (минимум)
- **mobile** (телефон) — одно приложение, две функции:
1. Поле ввода OAuth-токена + кнопка «Отправить токен» (через Wearable Data Layer).
2. Установка wear APK на часы по WiFi ADB — без компьютера, прямо с телефона.
Использует [dadb](https://github.com/mobile-dev-inc/dadb) — pure-Kotlin ADB-клиент.
Wear APK встроен в mobile APK (assets), копируется при установке.
- **wear** (часы):
- `TokenReceiverService``WearableListenerService`, ловит `/token` даже когда app закрыто.
- `TokenStore``EncryptedSharedPreferences` (токен шифруется на устройстве).
- `ApiPoller` — один `HttpURLConnection` POST к `api.anthropic.com/v1/messages`
(`max_tokens=1`, haiku — самый дешёвый запрос ради rate-limit заголовков).
- `MainActivity` — Compose for Wear, авто-опрос при запуске + кнопка «Обновить».
## APK
После `./gradlew assembleDebug`:
- `mobile/build/outputs/apk/debug/mobile-debug.apk` — для телефона (27 МБ, включает wear APK)
- `wear/build/outputs/apk/debug/wear-debug.apk` — для часов (22 МБ, можно ставить и вручную)
## Установка
### Шаг 1: поставить mobile APK на телефон
```
adb install -r mobile/build/outputs/apk/debug/mobile-debug.apk
```
Или скопировать APK на телефон и открыть.
### Шаг 2: включить отладку по WiFi на часах
1. На часах: Settings → About watch → тапнуть 7 раз по «Build number» → Developer mode.
2. Settings → Developer options → **Debug over WiFi** → включить.
3. Запомнить IP-адрес (показан в Developer options под «Debug over WiFi»).
### Шаг 3: установить wear APK с телефона
1. Открыть **Claude Meter Setup** на телефоне.
2. В секции «2. Установка приложения на часы» ввести IP часов и порт (5555).
3. Нажать «Установить на часы».
4. При первом подключении — подтвердить RSA-ключ на часах (появится диалог).
5. Готово — приложение Claude Meter появилось на часах.
> ADB-ключ генерируется один раз, хранится в `filesDir` приложения на телефоне.
> При следующих установках подтверждение на часах не нужно.
### Шаг 4: отправить токен
1. Скопировать `accessToken` из `~/.claude/.credentials.json` на ПК.
2. В секции «1. Токен Claude Code» вставить токен → «Отправить токен».
3. На часах открыть **Claude Meter** — увидит токен → покажет проценты.
Токен протухает (OAuth) — перепастить на телефоне, «Отправить» снова.
`// ponytail: token on-device, re-paste on OAuth expiry.`
## Где взять токен
Claude Code хранит OAuth-токен в `~/.claude/.credentials.json`:
```json
{"claudeAiOauth": {"accessToken": "***..."}}
┌─────────────────┐ Data Layer API ┌──────────────────┐
│ mobile (телефон) │ ──────────────────▶ │ wear (часы) │
│ │ /token │ │
│ • ввод OAuth │ │ • опрос API │
│ • спаривание │ │ • Compose UI │
│ • установка APK │ ──── WiFi ADB ──────▶ │ • EncryptedShared │
│ │ pair → connect → │ Preferences │
│ │ pm install │ │
└─────────────────┘ └──────────────────┘
```
## Что добавлять потом (не сейчас)
## Модули
- **Фоновое обновление** — `WorkManager` periodic (~15 мин). Сейчас по тапу + при запуске.
- **Complication на циферблате** — always-on виджет с %. Больше бойлерплейта, делаем когда v0 зайдёт.
- **График истории** — Room + простая диаграмма. YAGNI пока.
- **Авто-рефреш токена** — если Claude Code добавит refresh-token flow. Сейчас ручная перепоставка.
| Модуль | Назначение |
|--------|-----------|
| `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 (виджет на циферблате — отложено)
- Токен протухает → нужно перепастить на телефоне