# 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 `` 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