tjdrhs90/flutter-flame-harness/flame-harness-generator
Claude Code and agent skill by tjdrhs90/flutter-flame-harness
- community
Checking that the SKILL.md file is still in the repository.
Phase 5 — build the Flame game in 3 gated sub-phases (core loop → systems+components → UI+content), then self-evaluate against the contract.
Install
npx vskill@latest install tjdrhs90/flutter-flame-harness/flame-harness-generatorSKILL.md
flame-harness-generator
Phase 5 of the flutter-flame-harness pipeline. Builds the Flame game in three gated sub-phases (5a → 5b → 5c). Each sub-phase ends with a HARD GATE (flutter analyze zero issues + flutter test all pass) before the next sub-phase begins. On round N > 1, reads the previous evaluator feedback and fixes only the listed failures.
All file schemas (config.md, state.md, handoff/round-N-gen.md, feedback/round-N-qa.md) and the phase transition table are defined in docs/harness-protocol.md — that document is the single source of truth (§2 for state.md schema; §4 for handoff layout; §5 for feedback layout; §7 for the generator → evaluator transition). Do not redefine schemas here.
Round Handling and Feedback Intake
Determine current round
Read docs/harness/state.md. Extract current_round (integer, ≥ 1).
Round 1 — build from scratch
When current_round is 1:
- Read
docs/harness/config.md(extractapp_slug,app_name,bundle_id,
default_language, skip_admob).
- Read the latest PRD (
docs/harness/plans/*-prd.md, sort descending, take first). - Read the latest design doc (
docs/harness/plans/*-design.md, sort descending, take first). - Read
docs/harness/contract.md. Confirm## Status: AGREEDis present; abort with
flame-harness-generator: contract not AGREED — run flame-harness-contract first if missing.
- Read
checkpointfromstate.md(seedocs/harness-protocol.md§2). Re-entry: if a prior run
crashed/paused mid-phase, skip every sub-phase ≤ checkpoint (its HARD GATE already passed and its output exists) and resume at the next one — e.g. checkpoint: 5a → start at 5b. If checkpoint is "", start at 5a. This makes the generator safe to re-run without redoing (or colliding with) completed work.
Round N > 1 — fix only listed failures (feedback intake)
When current_round is greater than 1:
- Read
docs/harness/feedback/round-<N-1>-qa.md(perdocs/harness-protocol.md§5 layout). - Parse the
## Failed Criteriasection to extract each failing criterion and its prescribed fix. - Do NOT redesign or refactor areas that were not listed as failures. Make only the minimum
changes required to satisfy the listed fixes.
- If
docs/harness/feedback/round-<N-1>-qa.mddoes not exist, abort with:
flame-harness-generator: feedback file for round <N-1> not found — cannot determine fixes.
- Apply each fix, then run the HARD GATE for the affected sub-phase before writing the handoff.
Sub-phase 5a — Scaffold + Core Loop
5a.1 Create the Flutter project (flutter create)
Run flutter create. The Dart package name must be snake_case (lowercase + underscores, no hyphens) — convert app_slug (e.g. swing-line → swing_line). This package name is separate from the bundle id:
Idempotency: flutter create fails if the target already exists, which would break a resume or a re-run of round 1. The guard above makes 5a.1 safe to re-enter — it reuses an existing scaffold instead of hard-failing. (If the user passed --clean, rm -rf "$GAME" first, then create fresh.)
Bundle id — set it explicitly and IDENTICALLY on both platforms (do not trust the value `flutter create` derives from the project name). flutter create builds the bundle id from --org + project-name, which can leave underscores / case differences and can diverge between iOS and Android. Force both to the canonical config.bundle_id (com.<company>.<id>, lowercase [a-z0-9] only — see docs/harness-protocol.md):
- iOS: set
PRODUCT_BUNDLE_IDENTIFIER=<bundle_id>in all three build configs
(Debug/Release/Profile) in ios/Runner.xcodeproj/project.pbxproj.
- Android: set both
applicationIdandnamespace=<bundle_id>inandroid/app/build.gradle.kts. - Verify iOS
PRODUCT_BUNDLE_IDENTIFIER== AndroidapplicationId==config.bundle_id,
byte-for-byte (same case, no _, no -). The AdMob app and store records use this exact id.
Important (per `docs/harness-protocol.md`): After flutter create succeeds, move the docs/harness/ directory into the game project so all artifacts share one repository:
All subsequent reads/writes of harness files use the new path inside the game project.
5a.2 Remove default template files
Delete the generated counter demo to start from a clean slate:
These files will be replaced by the game implementation below.
5a.3 Configure pubspec.yaml
Set the following fields in pubspec.yaml:
name:<app_slug>(fromconfig.md)description:<app_name>(fromconfig.md)publish_to: noneversion: 1.0.0+1— explicit semverMAJOR.MINOR.PATCH+BUILD(App Store marketing version =
1.0.0, not 1.0; the build phase bumps the +BUILD on each upload).
Add to dependencies (use the latest compatible versions; minimum versions shown):
Add to dev_dependencies (image is used by tool/gen_icon.dart + tool/strip_bg.dart):
Add asset directories to flutter::
Run flutter pub get and confirm it exits 0.
5a.4 Create the lib/ directory structure
Create the following directories (and assets/ directories):
This structure matches the PRD's lib/ layout.
5a.5 game_config.dart — all tuning constants
Create lib/game/game_config.dart. This file must centralize every tuning constant that affects gameplay (speeds, spawn rates, scores, timings, physics). No magic numbers are permitted in any other game file — all values must reference a constant in GameConfig.
Template:
Fill all values from the PRD's game-mechanics section. Add more constants as needed; remove any that the specific game does not use.
5a.6 GameState enum
Create lib/game/game_state.dart:
5a.7 FlameGame subclass
Create lib/game/<app_slug>_game.dart. This is the root FlameGame (or FlameGame with HasCollisionDetection when the PRD requires collision detection). Do not add the removed HasTappables mixin — it was dropped in Flame 1.7 and will cause a compile error. Tap input is handled via TapCallbacks on individual components (see §5a.8). It must:
- Declare
GameState _state = GameState.menu;and a getterGameState get state. - Expose
void startGame(),void pauseGame(),void resumeGame(),void gameOver()methods
that transition _state and show/hide Flutter overlays by name.
- Override
onLoad()to load assets and add the background component (callsuper.onLoad()first). - Register all overlay names needed by screens (e.g.
'menu','hud','pause','gameOver'). - Performance (see `docs/game-gotchas.md`): if components need to query peers each frame,
compute the active lists once in the game root's update(dt) and have components read that cache — never call world.children.whereType<X>() per-component per-frame. Reuse static final Paint objects; don't recreate Paint/shaders/blur every frame.
5a.8 Input handling
Wire up the input method specified in the PRD:
- Tap/click →
TapCallbacksmixin on the player component (preferred for mobile). - Drag →
DragCallbacksmixin. - Keyboard →
KeyboardEventsmixin on the game class.
5a.9 main.dart entry point
Create lib/main.dart:
Replace <AppSlugGame> with the actual class name.
Startup order & lifecycle (required — see the Lifecycle patterns in `docs/game-gotchas.md`). main() must run in this order: WidgetsFlutterBinding.ensureInitialized() → await SharedPreferences.getInstance() (so synchronous prefs reads later work) → orientation → (if ads) ATT-after-first-frame → UMP consent → MobileAds.initialize() → runApp(...).
Host the GameWidget in a StatefulWidget that implements WidgetsBindingObserver: didChangeAppLifecycleState on paused/inactive → game.pauseEngine() + BGM pause; on resumed → resume. Clean up (stop audio, dispose pools, cancel timers) on the game's onDetach()/onRemove(). Gate stale input on resume with a _canInput flag.
5a.10 Minimal passing test
Create test/game_config_test.dart:
5a.11 CI workflow
Copy templates/ci.yml.template → .github/workflows/ci.yml (GitHub Actions running flutter analyze --no-fatal-infos + flutter test on push/PR), mirroring the shipped games' CI.
5a.12 Initialize version control
The generated game is its own git repository — initialize it and commit as the build progresses, so the work has atomic history from the start (and the user can diff/revert per sub-phase).
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/flame-harness-generator/SKILL.md
Popularity
- Repository stars
- 60
- Repository forks
- 5
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/tjdrhs90/flutter-flame-harness/flame-harness-generator)