Skip to main content
This page covers everything you run regularly while developing — keeping dependencies in sync after a pull, regenerating Dart code after model changes, running the app locally, and producing web and Android builds. For first-time machine setup, see First Time Setup.

Hiro Server — sync after pulling

Run this every time you pull changes or switch branches:
./dev-sync.sh
It performs the following steps:
hirocli stop          # release Windows file lock on the binary before overwriting
cd hiroserver
uv sync
uv tool install --editable hirocli --upgrade --force
uv sync alone is not enough after code changes. hirocli is a uv tool — its entry-point scripts are baked at install time. If pyproject.toml or the package structure changes, the old script will point at a stale or missing module and fail with ModuleNotFoundError. Always run ./dev-sync.sh after pulling. On Windows the server must be stopped first so the binary file lock is released.

Flutter — dev task runner (dev.sh)

device_apps/dev.sh is the primary entry point for all Flutter build and maintenance tasks. It verifies the pinned Flutter version (from .fvmrc) before running anything.
cd device_apps

./dev.sh --outdated          # list packages with newer versions available
./dev.sh --codegen           # run build_runner (freezed / riverpod / drift)
./dev.sh --web               # build Flutter web  →  build/web/
./dev.sh --android           # build APK for arm64-v8a  →  build/app/outputs/flutter-apk/
./dev.sh --all               # codegen + web + android in sequence
./dev.sh --codegen --android # combine any flags
All of these are also available as named launch configurations in VS Code / Cursor (Run & Debug panel).

Flutter — run for development

For interactive development (hot reload), use flutter_build.sh directly:
cd device_apps
./flutter_build.sh run
Add -d <device-id> to target a specific device or emulator. Use ./flutter_build.sh devices to list available targets.

Flutter — build for web

./dev.sh --web
Output is written to build/web/. To host under a sub-path (e.g. /app/):
./flutter_build.sh build web --base-href /app/
You may see Wasm dry-run warnings about flutter_secure_storage_web using dart:html. These are informational — the standard JavaScript/CanvasKit build succeeds normally. Wasm support for that package is a known upstream limitation.

Flutter — build for Android

./dev.sh --android
Builds a single APK targeting android-arm64 (arm64-v8a) — the correct ABI for modern 64-bit Android devices. Output is written to build/app/outputs/flutter-apk/. For a Google Play release bundle or a split-ABI build:
# All ABIs split — smaller per-ABI files for direct device install
./flutter_build.sh build apk --split-per-abi

# Release App Bundle — required for Google Play upload
./flutter_build.sh build appbundle --release

Flutter — code generation (standalone)

During active development, use watch mode so code is regenerated automatically on file save:
dart run build_runner watch --delete-conflicting-outputs
Always run ./dev.sh --codegen once after flutter pub get on a fresh clone, before attempting any build or run command.
android/gradle.properties sets kotlin.incremental=false. This is required when the Flutter Pub cache (C:\Users\...\AppData\Local\Pub\Cache) and the project (D:\...) are on different Windows drives — the Kotlin incremental compiler cannot compute relative paths across drive letters and fails the build otherwise.

Troubleshooting

The generated source files do not exist yet. Run code generation first, then retry the build:
dart run build_runner build --delete-conflicting-outputs
This must be run at least once after a fresh clone and any time you add a new @freezed model or @riverpod provider.
This happens on Windows when the Flutter Pub cache is on a different drive than the project (e.g. cache on C:, project on D:). The Kotlin incremental compiler cannot resolve cross-drive relative paths.The fix is already applied in this repo (android/gradle.properties contains kotlin.incremental=false). If you see this error, verify that line is present:
kotlin.incremental=false
If you have removed it or are starting from a different branch, add it back and run flutter clean before retrying.
This is a symptom of the same cross-drive Kotlin incremental cache issue described above. Check that kotlin.incremental=false is set in android/gradle.properties, then clean and rebuild:
flutter clean
./flutter_build.sh build apk --target-platform android-arm64
These warnings are printed by Flutter’s Wasm dry-run check and are expected. The standard JavaScript/CanvasKit web build completes successfully regardless. You can suppress the warnings with --no-wasm-dry-run, but they do not indicate a real build problem.
The server code changed but the installed tool entry-point still points to the old module layout. Run the sync script to reinstall:
./dev-sync.sh
On Windows, stop the server first (hirocli stop) so the binary file lock is released before the reinstall.
Hot reload does not trigger code generation. After adding a new @freezed model or @riverpod provider, stop the app, run build_runner build, then restart:
dart run build_runner build --delete-conflicting-outputs
flutter run