From 96399f3c9c6614b7825f72698ed91e679aed8e7d Mon Sep 17 00:00:00 2001 From: Dani Herrero Date: Sun, 17 May 2026 06:20:44 +0200 Subject: [PATCH 1/2] feat: add non-interactive agent_setup.sh and AGENTS.md/CLAUDE.md Adds scripts/agent_setup.sh, a non-interactive variant of project_setup.sh that takes --app-name, --package and --logo flags so an automation agent can customize a fresh project without stdin prompts. The original project_setup.sh is left untouched for human use. AGENTS.md documents the stack, monorepo layout, daily commands and conventions for AI agents. CLAUDE.md is a one-line pointer to AGENTS.md for Claude Code. Co-Authored-By: Claude Opus 4.7 (1M context) --- AGENTS.md | 149 +++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + scripts/agent_setup.sh | 92 +++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100755 scripts/agent_setup.sh diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a505cfe --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,149 @@ +# Agent Instructions — Flutter Dashing Kit + +You are a senior Flutter engineer working on a mobility-oriented mobile application built on top of the **Flutter Dashing Kit** boilerplate (by 7span). Default to Spanish when talking to the user; keep all code, comments and AI-facing documentation in English. + +## Stack + +- **Flutter** 3.13+ / **Dart** SDK `>=3.7.2 <4.0.0` +- **Melos** 7.3.0 — Dart workspace + monorepo orchestrator (`useRootAsPackage: true`) +- **flutter_bloc** — state management +- **auto_route** — Navigator 2.0 typed routing with code generation +- **envied** — typed env vars compiled from `.env.{dev,staging,prod}` +- **slang** — type-safe i18n / localization +- **Firebase** — multi-environment via flavors (`development`, `staging`, `prod`) +- **Atomic Design** in `packages/app_ui` (atoms / molecules / organisms / templates) +- **mason** — code scaffolding (see `bricks/feature`) +- **husky** + `lint_staged` — pre-commit `dart format -l 70` and `dart analyze --fatal-infos --fatal-warnings` +- **flutter_lints** — base lint ruleset (see `analysis_options.yaml`) + +## Repository Layout + +``` +flutter-dashing-kit/ +├── apps/ +│ └── app_core/ # Main Flutter app +│ ├── lib/ +│ │ ├── main_development.dart # Entry point — dev flavor +│ │ ├── main_staging.dart # Entry point — staging flavor +│ │ ├── main_production.dart # Entry point — prod flavor +│ │ ├── bootstrap.dart # Shared app bootstrap (DI, error zone) +│ │ ├── app/ # App-level wiring: routes, config, observers +│ │ ├── core/ # data / domain / presentation core +│ │ └── modules/ # Feature modules (auth, home, profile, …) +│ ├── android/ # Android-specific (gradle, flavors) +│ ├── ios/ # iOS-specific (xcconfig, Podfile) +│ └── pubspec.yaml +├── packages/ +│ ├── api_client/ # HTTP client + interceptors +│ ├── app_notification_service/ # Push notifications wrapper +│ ├── app_subscription/ # In-app purchases / subscriptions +│ ├── app_translations/ # Generated i18n strings (slang) +│ ├── app_ui/ # Design system (atomic design) +│ └── widgetbook/ # Component catalog +├── bricks/ +│ └── feature/ # Mason brick to scaffold a feature module +├── scripts/ # Setup scripts (see "Scripts" below) +├── pubspec.yaml # Workspace root + melos config +└── analysis_options.yaml +``` + +## Daily Commands + +Run from the repository root unless noted otherwise. + +| Command | Purpose | +| --- | --- | +| `melos bs` | Bootstrap the workspace (resolve deps for every package) | +| `melos run analyze` | Run `dart analyze` across all packages | +| `melos run format` | Format with `dart format -l 70` and apply `dart fix` | +| `melos run build-runner` | Regenerate code in `apps/app_core` (auto_route, envied, freezed, json_serializable…) | +| `melos run asset-gen` | Regenerate `packages/app_ui` asset references | +| `melos run locale-gen` | Regenerate slang i18n files in `packages/app_translations` | +| `melos run widgetbook-gen` | Regenerate Widgetbook catalog | +| `melos run build-apk` / `build-bundle` / `build-ipa` | Production builds | +| `melos run go-ios-go` | Reset iOS Pods and reinstall | +| `flutter run -t apps/app_core/lib/main_development.dart --flavor development` | Launch the dev flavor | +| `flutter run -t apps/app_core/lib/main_staging.dart --flavor staging` | Launch the staging flavor | +| `mason get feature && mason make feature` | Scaffold a new feature module | + +After editing anything that participates in code generation (routes, envied schemas, freezed models, JSON serializable classes), **run `melos run build-runner`** before committing. + +## Scripts + +| Script | When to use | Notes | +| --- | --- | --- | +| `scripts/check_environment_configuration.sh` | Verify Flutter / Melos / build_runner are installed and current | Non-interactive. Safe to run unattended. | +| `scripts/init.sh` | First-time boilerplate initialisation (env files, bootstrap, mason init, husky install) | Mostly non-interactive. Safe to run unattended. | +| `scripts/agent_setup.sh` | **Automation-friendly** project customisation: app name, package id, launcher icon | Accepts `--app-name`, `--package`, `--logo`. Prefer this over `project_setup.sh` in scripted environments. | +| `scripts/project_setup.sh` | Interactive customisation for humans | Uses `read` prompts; **cannot run unattended**. Do not invoke from an agent — use `agent_setup.sh` instead. | +| `scripts/firebase_setup.sh` / `firebase_app_distribution.sh` / `remove_firebase.sh` | Firebase configuration helpers | Read each script before running; some require credentials. | +| `scripts/delete_pubspec_lock.sh` | Wipe pubspec.lock files | Only when intentionally resetting locked versions. | + +The scripts use a `#!/bin/zsh` shebang. On Linux/CI prefer invoking them explicitly: `sh scripts/...` (POSIX-compatible parts) or `zsh scripts/...` if zsh is installed. `agent_setup.sh` uses `#!/usr/bin/env bash` and works on both Linux and macOS. + +## Conventions + +### State management (BLoC) + +- One BLoC per feature/use-case; keep it presentation-agnostic. +- Events are verbs (`LoadProfileRequested`); states are nouns or adjectives (`ProfileLoading`, `ProfileLoaded`). +- Use `Equatable` (or `freezed`) for events and states. +- Prefer `BlocProvider` scoped to the route/screen over global providers. + +### Routing (auto_route) + +- Declare routes in `apps/app_core/lib/app/routes/`. After any change, run `melos run build-runner`. +- Use typed route classes (`const FooRoute(id: 'x')`), not string paths. + +### Env vars (envied) + +- Define typed env schemas; values come from `apps/app_core/.env.{dev,staging,prod}`. +- Never commit `.env.*` files with real secrets. The `init.sh` script seeds them with placeholders. +- After editing an envied schema, run `melos run build-runner`. + +### i18n (slang) + +- Add/edit translations in `packages/app_translations/lib/i18n/*.i18n.json`. +- Run `melos run locale-gen` to regenerate type-safe accessors. +- Reference strings as `t.feature.key`, never as raw strings in widgets. + +### UI / Atomic Design (`packages/app_ui`) + +- **atoms/**: indivisible widgets (buttons, icons, typography tokens). +- **molecules/**: small compositions of atoms (form field with label + error). +- **organisms/**: feature-level widgets (cards, list items with actions). +- **templates/**: page-level layout scaffolds. +- New visual primitives go into `app_ui`, not into the app module. + +### Code style + +- Lines wrap at **70 columns** (`dart format -l 70`). +- `dart analyze` must pass with `--fatal-infos --fatal-warnings` (enforced by `lint_staged`). +- Single quotes preferred (matches `flutter_lints` recommendation). +- Require trailing commas — `dart fix --apply --code=require_trailing_commas` runs in `melos run format`. + +### Scaffolding a feature + +```sh +mason get feature # one-time per workspace +mason make feature --name +``` + +The brick generates the module skeleton under `apps/app_core/lib/modules/`. + +### Git workflow + +- Branch naming: `feat/`, `fix/`, `refactor/`, `docs/`, `chore/`. +- Never commit on `main`. +- Pre-commit hooks (husky + `lint_staged`) run `dart format -l 70` and `dart analyze --fatal-infos --fatal-warnings` on staged Dart files. Do not bypass with `--no-verify`. +- Push the branch to `origin` after each commit; open a PR targeting `main` for review. + +## What NOT to do + +- Do not edit `scripts/project_setup.sh` to remove its prompts — the upstream (`7span/dashing-kit`) keeps it interactive. For non-interactive needs, use or extend `scripts/agent_setup.sh`. +- Do not change the package identifier or app name by hand-editing `build.gradle.kts`, `AndroidManifest.xml`, or iOS plists. Go through `scripts/agent_setup.sh --package=… --app-name=…`. +- Do not commit generated files outside the ones the original boilerplate already tracks (slang outputs and auto_route outputs are committed; build_runner-generated `*.g.dart` / `*.freezed.dart` follow the boilerplate's convention). +- Do not introduce new state management libraries (Riverpod, GetX, MobX). Stick to BLoC. +- Do not bypass the `analysis_options.yaml` for a specific lint without an inline `// ignore: ` comment justifying it. +- Do not run `flutter clean` followed by `melos bs` as a debugging reflex; investigate first. +- Do not change Flutter SDK constraints in `pubspec.yaml` without checking compatibility across every workspace package. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/scripts/agent_setup.sh b/scripts/agent_setup.sh new file mode 100755 index 0000000..49cd9f1 --- /dev/null +++ b/scripts/agent_setup.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# +# Non-interactive variant of scripts/project_setup.sh. +# Accepts flags so an automation agent can customise app name, Android/iOS +# package identifier and launcher icon without stdin prompts. +# +# All flags are optional. Omitted flags leave the corresponding value unchanged. + +set -euo pipefail + +APP_NAME="" +PACKAGE_NAME="" +LOGO_PATH="" + +usage() { + cat <<'USAGE' +Usage: agent_setup.sh [options] + +Options: + --app-name Replace the Android appLabel "Core App" (and its QA/Staging + variants) in apps/app_core/android/app/build.gradle.kts. + --package Change the Android/iOS package identifier using + `dart run change_app_package_name:main `. Note: Firebase + configuration must be re-uploaded manually afterwards. + --logo Copy to packages/app_ui/assets/images/logo.png and + regenerate launcher icons with flutter_launcher_icons. + -h, --help Show this help. + +Run from the repository root. +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --app-name) APP_NAME="${2:-}"; shift 2 ;; + --app-name=*) APP_NAME="${1#*=}"; shift ;; + --package) PACKAGE_NAME="${2:-}"; shift 2 ;; + --package=*) PACKAGE_NAME="${1#*=}"; shift ;; + --logo) LOGO_PATH="${2:-}"; shift 2 ;; + --logo=*) LOGO_PATH="${1#*=}"; shift ;; + -h|--help) usage; exit 0 ;; + *) echo "Unknown option: $1" >&2; usage; exit 1 ;; + esac +done + +if [[ -z "$APP_NAME" && -z "$PACKAGE_NAME" && -z "$LOGO_PATH" ]]; then + echo "Nothing to do. Pass at least one of --app-name, --package or --logo." >&2 + usage + exit 1 +fi + +# `sed -i` differs between GNU (Linux) and BSD (macOS). Detect once. +if sed --version >/dev/null 2>&1; then + sed_inplace() { sed -i "$@"; } +else + sed_inplace() { sed -i '' "$@"; } +fi + +GRADLE_FILE="apps/app_core/android/app/build.gradle.kts" + +if [[ -n "$APP_NAME" ]]; then + if [[ ! -f "$GRADLE_FILE" ]]; then + echo "Error: $GRADLE_FILE not found. Run this script from the repo root." >&2 + exit 1 + fi + sed_inplace "s/manifestPlaceholders\[\"appLabel\"\] = \"Core App\"/manifestPlaceholders[\"appLabel\"] = \"${APP_NAME}\"/g" "$GRADLE_FILE" + sed_inplace "s/manifestPlaceholders\[\"appLabel\"\] = \"Core App QA\"/manifestPlaceholders[\"appLabel\"] = \"${APP_NAME} QA\"/g" "$GRADLE_FILE" + sed_inplace "s/manifestPlaceholders\[\"appLabel\"\] = \"Core App Staging\"/manifestPlaceholders[\"appLabel\"] = \"${APP_NAME} Staging\"/g" "$GRADLE_FILE" + echo "✓ appLabel updated to '${APP_NAME}' in ${GRADLE_FILE}" +fi + +if [[ -n "$PACKAGE_NAME" ]]; then + pushd apps/app_core >/dev/null + dart run change_app_package_name:main "$PACKAGE_NAME" + popd >/dev/null + echo "✓ Package identifier changed to '${PACKAGE_NAME}'" + echo " ⚠ Firebase config (google-services.json / GoogleService-Info.plist) must be re-uploaded manually." +fi + +if [[ -n "$LOGO_PATH" ]]; then + if [[ ! -f "$LOGO_PATH" ]]; then + echo "Error: logo file not found at '$LOGO_PATH'." >&2 + exit 1 + fi + cp "$LOGO_PATH" packages/app_ui/assets/images/logo.png + pushd apps/app_core >/dev/null + dart run flutter_launcher_icons + popd >/dev/null + echo "✓ Launcher icon regenerated from '${LOGO_PATH}'" +fi + +echo "Done." From 9dd4d87f0423940d0c06083c0b1bc9f7cdc69a66 Mon Sep 17 00:00:00 2001 From: Dani Herrero Date: Sun, 17 May 2026 06:37:49 +0200 Subject: [PATCH 2/2] Update agent instructions in AGENTS.md Removed instruction to default to Spanish when talking to the user. --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index a505cfe..0096262 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Agent Instructions — Flutter Dashing Kit -You are a senior Flutter engineer working on a mobility-oriented mobile application built on top of the **Flutter Dashing Kit** boilerplate (by 7span). Default to Spanish when talking to the user; keep all code, comments and AI-facing documentation in English. +You are a senior Flutter engineer working on a mobility-oriented mobile application built on top of the **Flutter Dashing Kit** boilerplate (by 7span). ## Stack