# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

### Development (full app)
```bash
bash scripts/dev.sh
```
Builds backend, desktop, regenerates Wails bindings, type-checks frontend, then starts `wails dev` with hot reload.

### Build for production
```bash
bash scripts/build.sh
```

### Per-component build/check
```bash
# Backend
cd backend-go && go build ./...

# Desktop (Go)
cd desktop && go build ./...

# Frontend type-check only
cd frontend-react && npx tsc -b --noEmit

# Frontend bundle (outputs to desktop/frontend/dist/)
cd frontend-react && npm run build

# Wails desktop binary
cd desktop && export PATH="$PATH:$(go env GOPATH)/bin" && wails build

# Android SDK
cd android-sdk && ./gradlew :sdk:assembleDebug
```

### Regenerate Wails JS bindings
```bash
cd desktop && export PATH="$PATH:$(go env GOPATH)/bin" && wails generate module
```
Run this after adding or changing any exported method on `App` in `desktop/app.go`. Output goes to `frontend-react/src/wailsjs/` — do not edit those files manually.

---

## Architecture

```
Android App → Instrumentation SDK → ADB Tunnel → Go Backend → React Frontend → Wails Desktop Shell
```

### Monorepo layout

| Directory | Module / Package | Role |
|---|---|---|
| `desktop/` | `git.achmad.dev/admin/droidscope/desktop` | Wails app — entry point, `app.go` exposes bound methods |
| `backend-go/` | `git.achmad.dev/admin/droidscope/backend` | Go packages: ADB, device, logcat, network, storage, etc. |
| `frontend-react/` | — | Vite + React + TypeScript UI |
| `android-sdk/` | `dev.achmad.droidscope` | Kotlin instrumentation SDK |
| `scripts/` | — | `dev.sh`, `build.sh`, `download-adb.sh` |

### Go workspace
`go.work` links `./desktop` and `./backend-go` for local resolution. `desktop/go.mod` also has a `replace` directive — both are needed (`go.work` for IDE/build, `replace` for `go mod tidy`).

### Wails ↔ React bridge
- `desktop/wails.json`: `"frontend:dir": "../frontend-react"`, `"wailsjsdir": "../frontend-react/src"`
- Vite `build.outDir` is `../desktop/frontend/dist` so Go's `//go:embed` works
- Import bound methods from `@/wailsjs/go/main/App` in React

### State model (frontend)
- **`selectedDeviceId`** — which device the info panel is showing (can be anything)
- **`profiledDeviceId`** — the active monitoring target for all feature panels (logcat, network, etc.)
- These are separate concepts in `app-store.ts` (Zustand)

### Active device scoping (all feature panels)
Every feature panel outside Device Management must:
1. Import `useActiveDevice` from `@/hooks/use-active-device`
2. Gate all polling/streaming behind `isMonitoring`
3. Store per-device data via `patchDeviceCache(deviceId, data)` — never cleared on device switch
4. Render `<NoDeviceSelected />` when `!isMonitoring`

### ADB binary resolution (runtime)
`desktop/internal/adbembed/` — resolves in order: embedded binary → `$ANDROID_HOME/platform-tools/adb` → `adb` on `$PATH`. Embed directive uses `//go:embed all:bin` (not `//go:embed bin`) because the placeholder file is hidden.

### Static vs live device data
- `GetDeviceInfo(deviceId)` — one-time fetch, ~20 static fields (model, OS version, ABI, etc.)
- `GetDeviceLiveStats(deviceId)` — polled every 1 s (RAM, battery, thermal, storage, IP)
- `devices:changed` Wails event — emitted every 1 s for the device list

---

## Key conventions

- Never use `namespace` TypeScript syntax — it conflicts with Wails-generated `models.ts` and `erasableSyntaxOnly` must stay off in `tsconfig.app.json`
- shadcn/ui uses Base UI (not Radix UI) — `DialogTrigger` has no `asChild` prop; use controlled `open` state instead
- `tsconfig.app.json` has no `baseUrl`; path alias `@/*` → `./src/*` works via `moduleResolution: bundler`
- Do not run `go work sync` — it fails for unpublished modules; the workspace + replace approach handles everything
- Never commit anything under `frontend-react/src/wailsjs/` — it is auto-generated
