Use when fixing bugs, adding regression tests, adding new features, when compilation is slow, or when learning twin test naming conventions in flutter_rust_bridge
61
71%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.claude/skills/frb-develop-feature/SKILL.mdNote: Check your user-level
remote-testingrules before running commands. Tests and codegen may require remote execution.
For both bug fixes and new features: iterate in frb_example/dart_minimal (fast compile), then migrate the final test to frb_example/pure_dart (full coverage).
dart_minimal is only an iteration workspace. A bug fix or feature PR is not ready when its only regression coverage lives in dart_minimal; stop before PR preparation and move the final test to pure_dart/pure_dart_pde.
| Phase | Location | Why |
|---|---|---|
| Reproduce / Iterate | frb_example/dart_minimal | Fast compile = quick feedback |
| Migrate final regression / feature test | frb_example/pure_dart + pure_dart_pde | Twin tests = automatic coverage of all codegen modes |
For bugs, first make the failure reproducible in dart_minimal, write down the exact reproduction report, fix it there, and only then move the regression test to pure_dart. For features, follow the same fast-iteration loop before adding the final pure_dart coverage.
Write one final test → get ~6 variants automatically via TwinNormal suffix.
Before pushing, opening a PR, requesting review, or monitoring CI as if the work is ready:
frb_example/dart_minimal to frb_example/pure_dart.pure_dart use the TwinNormal suffix pattern where applicable.pure_dart_pde coverage.frb-feature-flag before treating the coverage as final.dart_minimal reproducer unless it is intentionally kept as a minimal example in addition to the pure_dart regression.If any of these checks fail, return to Phase 2. Do not treat a passing dart_minimal test as final readiness.
For every bug fix, the PR description must include a reproduction report before the fix is presented as convincing.
Capture the report immediately after reproducing the bug and before changing the fix code. It must include:
Use this PR description shape:
## Reproduction
Baseline commit: `<commit-hash>`
Steps:
1. `<command or edit>`
2. `<command>`
Observed:
```text
<error output>
```
Expected:
<expected behavior>If the reproduction needs temporary test code in frb_example/dart_minimal, describe the exact temporary Rust/Dart edits in the steps. Keep the temporary reproducer only while debugging, then migrate the final regression test to frb_example/pure_dart.
digraph workflow {
rankdir=TB;
node [shape=box];
"Write reproducer/test in dart_minimal" -> "Run reproducer";
"Run reproducer" -> "Failure reproduced?" [shape=diamond];
"Failure reproduced?" -> "Write reproduction report" [label="yes"];
"Failure reproduced?" -> "Adjust reproducer" [label="no"];
"Adjust reproducer" -> "Run reproducer";
"Write reproduction report" -> "Fix";
"Fix" -> "Run focused test";
"Run focused test" -> "Pass?" [shape=diamond];
"Pass?" -> "Move final test to pure_dart" [label="yes"];
"Pass?" -> "Fix" [label="no"];
"Move final test to pure_dart" -> "Add TwinNormal suffix" -> "Run code gen" -> "All tests pass?";
"All tests pass?" -> "Done" [label="yes"];
"All tests pass?" -> "Debug" [label="no"];
"Debug" -> "All tests pass?";
}Add the smallest test or bug reproducer:
frb_example/dart_minimal/rust/src/api/minimal.rsfrb_example/dart_minimal/test/minimal_test.dartFor bug fixes, this test should fail before the fix and pass after the fix. There is usually no need to create any new files.
Run the reproducer and record the reproduction report:
Before changing the fix code, save the baseline commit hash, exact commands or temporary edits, and the observed failure output. This report must go into the PR description.
Add the implementation or fix:
Usually need to modify frb_codegen, frb_dart, and/or frb_rust.
Run codegen and test:
(cd frb_example/dart_minimal && cargo run --manifest-path ../../frb_codegen/Cargo.toml -- generate)
./frb_internal test-dart-native --package frb_example/dart_minimalAfter codegen: Check your user-level
remote-testingrules. If codegen was run remotely, pull changes back to local.
Iterate until test passes
Keep the temporary dart_minimal reproducer while debugging. Passing here only proves the fix is ready to migrate; it is not the final regression placement. Remove or simplify the temporary reproducer after the final regression test has been migrated to pure_dart.
Move the final feature or regression test to frb_example/pure_dart:
frb_example/pure_dart/rust/src/api/my_feature.rsfrb_example/pure_dart/test/api/my_feature_test.dartEither add to existing files or create new files. Then remove temporary reproducer code from frb_example/dart_minimal unless it is intentionally useful as a minimal example.
Add TwinNormal suffix to all functions and types:
| Context | Suffix | Example |
|---|---|---|
| snake_case | _twin_normal | my_func_twin_normal() |
| PascalCase | TwinNormal | MyStructTwinNormal |
This triggers automatic test generation (~6 variants) under different codegen modes. Always mimic existing frb_example/pure_dart tests for exact patterns.
Run codegen and test:
# Codegen
./frb_internal precommit-generate
# Native tests (can run in parallel)
./frb_internal test-dart-native --package frb_example/pure_dart
./frb_internal test-dart-native --package frb_example/pure_dart_pde
# Web tests (optional, for web platform coverage)
./frb_internal test-dart-web --package frb_example/pure_dart
./frb_internal test-dart-web --package frb_example/pure_dart_pdeAfter codegen: Check your user-level
remote-testingrules. If codegen was run remotely, pull changes back to local.
Native tests must pass - they test different codegen configurations. Web tests are optional but recommended for web platform coverage.
Iterate until test passes
You may use frb_example/dart_minimal again if there are bugs and need fast iteration.
| Task | Command |
|---|---|
| Test dart_minimal | ./frb_internal test-dart-native --package frb_example/dart_minimal |
| Test pure_dart | ./frb_internal test-dart-native --package frb_example/pure_dart |
| Test pure_dart_pde | ./frb_internal test-dart-native --package frb_example/pure_dart_pde |
| Web test pure_dart | ./frb_internal test-dart-web --package frb_example/pure_dart |
| Web test pure_dart_pde | ./frb_internal test-dart-web --package frb_example/pure_dart_pde |
| Code generation | ./frb_internal precommit-generate |
website/docs/guides/contributing/overview.md - System architecture, codegen flow, directory structure| Directory | Purpose |
|---|---|
frb_codegen/ | Code generator (IR → Rust/Dart output) |
frb_dart/ | Dart runtime library |
frb_rust/ | Rust runtime library |
frb_example/ | Examples + tests (pure_dart has most coverage) |
| Mistake | Fix |
|---|---|
| Fixing a bug directly in pure_dart | First reproduce and iterate in dart_minimal, then migrate the regression test |
| Leaving final coverage only in dart_minimal | Move the final regression to pure_dart/pure_dart_pde before PR preparation |
| Skipping frb_example/dart_minimal phase | Start there - saves time on compilation |
| Forgetting TwinNormal suffix | Add before code gen in frb_example/pure_dart |
| Moving test without updating imports | Check import paths after migration |
| Not running code gen after move | Always run ./frb_internal precommit-generate |
frb-code-generation - Which generation commands to runfrb-test - How to run tests locallyfrb-debugging - Debug code generation issuesfrb-prepare-pr - Preparing a PR for review1d5348b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.