Zero-overhead API
Clean, minimal syntax with strong typing and full control over the binding lifecycle — from transient factories to lazy singletons.
Zero-overhead API
Clean, minimal syntax with strong typing and full control over the binding lifecycle — from transient factories to lazy singletons.
Hierarchical scopes
Compose a tree of scopes and sub-scopes. Resolve dependencies through the hierarchy and dispose them deterministically.
Sync & async
Register and resolve synchronous providers, async factories, and dependencies that need runtime parameters.
Code generation
Annotate your modules and let cherrypick_generator write the wiring for you — no manual boilerplate.
Highly testable
Override bindings and build isolated scope trees so every test gets exactly the graph it needs.
Flutter-native
Expose DI scopes to the widget tree with CherryPickProvider — or use the core library in pure Dart on the server.
dependencies: cherrypick: ^4.0.0 cherrypick_annotations: ^4.0.0
dev_dependencies: build_runner: ^2.4.0 cherrypick_generator: ^4.0.0dependencies: cherrypick: ^4.0.0 cherrypick_flutter: ^4.0.0 cherrypick_annotations: ^4.0.0
dev_dependencies: build_runner: ^2.4.0 cherrypick_generator: ^4.0.0import 'package:cherrypick/cherrypick.dart';
// 1. Describe a module.class AppModule extends Module { @override void builder(Scope currentScope) { bind<ApiClient>().toProvide(() => ApiClient()); bind<DataRepository>() .toProvide(() => DataRepository(currentScope.resolve<ApiClient>())) .singleton(); }}
void main() { // 2. Open a scope and install the module. final scope = CherryPick.openRootScope()..installModules([AppModule()]);
// 3. Resolve. final repo = scope.resolve<DataRepository>();}