4.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
Development (full app)
bash scripts/dev.sh
Builds backend, desktop, regenerates Wails bindings, type-checks frontend, then starts wails dev with hot reload.
Build for production
bash scripts/build.sh
Per-component build/check
# 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
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 |
docs/ |
— | DEVELOPMENT.md (setup + build guide), TODO.md (implementation status) |
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.outDiris../desktop/frontend/distso Go's//go:embedworks - Import bound methods from
@/wailsjs/go/main/Appin 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:
- Import
useActiveDevicefrom@/hooks/use-active-device - Gate all polling/streaming behind
isMonitoring - Store per-device data via
patchDeviceCache(deviceId, data)— never cleared on device switch - 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:changedWails event — emitted every 1 s for the device list
Key conventions
- Never use
namespaceTypeScript syntax — it conflicts with Wails-generatedmodels.tsanderasableSyntaxOnlymust stay off intsconfig.app.json - shadcn/ui uses Base UI (not Radix UI) —
DialogTriggerhas noasChildprop; use controlledopenstate instead tsconfig.app.jsonhas nobaseUrl; path alias@/*→./src/*works viamoduleResolution: 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