docs: full README with architecture, setup, tech details
This commit is contained in:
@@ -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%, янтарь 70–90%, красный ≥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 (виджет на циферблате — отложено)
|
||||
- Токен протухает → нужно перепастить на телефоне
|
||||
|
||||
Reference in New Issue
Block a user