docs: replace PLAN.md with README, add CLAUDE.md, DEVELOPMENT.md, TODO
PLAN.md (AI requirements doc) converted to README.md (human-facing project overview with feature status table). CLAUDE.md added for Claude Code with commands, architecture, and key conventions. DEVELOPMENT.md covers first-time setup, per-component build commands, hot-reload guidance, and ADB bundling notes. TODO.md tracks implementation status across all phases.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user