Android UI Inspection (Koder Eye-first)
Em sessão com Android conectado via ADB, preferir Koder Eye (HTTP API em 127.0.0.1:9876 após `adb forward tcp:9876 tcp:9876`) a screenshots crus. ~10× menos tokens, bounds/IDs/estado exatos do OS. Cair pra screencap só em casos visuais (ícone, cor, canvas, FLAG_SECURE).
Policy — Inspeção de UI Android (Koder Eye antes de screencap)
Em qualquer sessão com dispositivo Android conectado via ADB, *referir o Koder Eye a screenshots crus*para inspecionar a UI. Aplicável a qualquer agente de IA (Claude Code, Codex, Gemini CLI, etc.) que opere no monorepo Koder.
Por quê
Vision custa ~10× mais tokens que JSON da accessibility tree. Eye dá:
- Bounds exatos (
[x, y, w, h]) — screenshot força adivinhar coordenadas - View IDs (
dev.koder.eye:id/start_btn) — invisíveis em pixel - Estado direto do OS:
enabled,clickable,checked,focused - Texto exato de TextViewButtonEditText/Switch — sem erros de OCR
- Diff estrutural entre snapshots — duas screenshots podem parecer idênticas e diferir em estado
- Long-poll de eventos (
/events?wait=10000) — sem polling de screencap
Custo por inspeção:
| Ação | Tokens |
|---|---|
| Screenshot enviado ao chat | ≈1500 (image) |
GET /screen/text |
50–500 (text) |
GET /screen/buttons |
100–400 (text) |
GET /screen/diff |
50–800 (text, ≈0 quando nada mudou) |
10 screenshots ≈ 15 000 tokens vs. 10 queries Eye ≈ 2 000 tokens.
Setup obrigatório por sessão
Fazer *ntes*de declarar Eye indisponível:
adb -s <serial> forward tcp:9876 tcp:9876
curl -s localhost:9876/healthz # endpoint é /healthz, NÃO /health
# Esperado: {"ok":true,"version":"...","accessibility":true,"media_projection":false}Se /healthz responder, Eye está pronto.
Se conexão for recusada após forward:
adb -s <serial> shell am start -n dev.koder.eye/.MainActivity
# tap no botão "Start Server" (ou input tap após uiautomator dump)Se Eye não estiver instalado:
adb -s <serial> install -r ~/dev/koder/dev/eye/app/android/app/build/outputs/apk/release/app-release.apk*ão interpretar connection refused sem forward como "Eye indisponível".*
Quando usar Eye (matriz de decisão)
| Pergunta a responder | Use |
|---|---|
| Botão X está visível agora? | ✅ GET /screen/buttons |
| Qual o pacote/atividade em foreground? | ✅ GET /screen | jq -r .root.pkg |
| Tela mudou desde a última ação? | ✅ GET /screen/diff?since=<hash> |
| Esse texto aparece na tela? | ✅ GET /screen/text |
| Esperar até dialog aparecer | ✅ GET /events?wait=10000 |
| Quantos itens visíveis em uma lista? | ✅ Eye conta nodes |
Coordenadas exatas pra input tap |
✅ Eye dá bounds |
| Botão está enabled ou só parece? | ✅ enabled: true|false direto do OS |
Quando cair pra screenshot
Eye é cego ou inferior pra:
- *onteúdo bitmap*— splash com logo+slogan como PNG, banners, ícones, OG images
- *anvas / SurfaceView / WebView*— games, players, mapas, custom-drawn views
- *spectos visuais*— cor, contraste, alinhamento, polish de design, validação de tema
- *elas com FLAG_SECURE*— banking, password manager, Signal/WhatsApp; ambos (Eye e screencap) bloqueados
- *rimeira inspeção de app desconhecido*— vision dá contexto de marca/layout que Eye não dá
- *erificação de ícone / avatar carregado*— accessibility tree raramente expõe imagens
Estratégia recomendada
*ye-first, screenshot só no miss:*
curl -s localhost:9876/screen/texte/screen/buttons- Se a resposta resolve → done
- Se Eye retorna tree suspeitamente vazio (suspeita de canvas), OU a pergunta é intrinsecamente visual →
adb exec-out screencap -p > ~/temp/s.png
Comandos de referência
# Texto na ordem de leitura
curl -s localhost:9876/screen/text | jq .
# Botões + bounds + labels
curl -s localhost:9876/screen/buttons | jq .
# Snapshot + diff
HASH=$(curl -s localhost:9876/screen | jq -r .screen_hash)
# ... ação ...
curl -s "localhost:9876/screen/diff?since=$HASH" | jq '{added: (.added|length), removed: (.removed|length), modified: (.modified|length)}'
# Long-poll de evento (até 10s)
curl -s "localhost:9876/events?wait=10000" | jq .
# Captura PNG no device (sem subir pro chat)
curl -s -X POST -H 'Content-Type: application/json' -d '{}' localhost:9876/capture | jq .Referências
- Doc completa:
~/dev/koder/context/tools/koder-eye.md(matriz detalhada, status de features, RFCs) - Source:
~/dev/koder/dev/eye/ - RFC base:
products/dev/eye/docs/rfcs/RFC-001-on-device-ui-analysis.md