137 lines
6.3 KiB
Markdown
137 lines
6.3 KiB
Markdown
# 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 (виджет на циферблате — отложено)
|
|
- Токен протухает → нужно перепастить на телефоне
|