Skip to content

CherryPick

A lightweight, flexible dependency injection ecosystem for Dart & Flutter. Clean API, hierarchical scopes, sync & async providers, and zero-boilerplate code generation.

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.

pubspec.yaml
dependencies:
cherrypick: ^4.0.0
cherrypick_annotations: ^4.0.0
dev_dependencies:
build_runner: ^2.4.0
cherrypick_generator: ^4.0.0
import '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>();
}