Skip to content

Monorepo Toolkit

Dependency Manager ​

The deps command manages dependencies in the monorepo workspace. It handles adding and removing packages from the centralized shared/dependencies package, wiring internal workspace packages together, and adding external pub.dev packages to specific packages.

Subcommands ​

deps add ​

Adds a pub.dev dependency to the shared/dependencies package and optionally registers it in a barrel file for re-export:

bash
# Add a package to shared/dependencies
dart run monorepo_toolkit deps add freezed_annotation

# With a version constraint
dart run monorepo_toolkit deps add freezed_annotation -v "^2.4.0"

# Add to a specific barrel file category
dart run monorepo_toolkit deps add get_it -v "^7.6.0" -c injection

When a category is specified, the package export is added to the corresponding barrel file (e.g., lib/injection.dart). If the barrel file does not exist, it is created automatically.

FlagAbbrDescription
--version-vVersion constraint (e.g., ^2.4.0)
--category-cBarrel file category to add the export to

What deps add bloc_concurrency -v ^0.3.0 -c bloc changes:

dependency managerA shared package goes in once and is imported from one barrel

Step 1 of 3, before: Packages that many features share live in shared/dependencies, which re-exports them from category barrels such as bloc.dart. A feature depends on dependencies, not on each pub.dev package.

shared/dependencies/pubspec.yaml
dependencies:  auto_route: ^11.1.0  # …  flutter_bloc: ^9.1.1  # …
shared/dependencies/lib/bloc.dart
/// State management exports.////// This barrel file exports flutter_bloc for BLoC/Cubit state management.library;export 'package:flutter_bloc/flutter_bloc.dart';
features/<feature>/lib/src/search_bloc.dart
import 'package:dependencies/bloc.dart';class SearchBloc extends Bloc<SearchEvent, SearchState> {  SearchBloc() : super(const SearchState()) {    on<SearchSubmitted>(_onSubmitted);  }  // …}

deps add edits shared/dependencies only. Flutter-free packages (the _api contracts) use shared/dependencies_core, which you edit by hand.

deps remove ​

Removes a dependency from the shared/dependencies package and cleans up all barrel file exports:

bash
dart run monorepo_toolkit deps remove freezed_annotation
FlagAbbrDescription
--force-fSkip confirmation prompt

deps internal ​

Adds one workspace package as a dependency of another. Automatically calculates the relative path between the two packages:

bash
# Add monitoring_api as a dependency of home_impl
dart run monorepo_toolkit deps internal home_impl monitoring_api

The first argument is the source package (the one that needs the dependency), and the second is the target package (the one being depended on).

What that command changes:

dependency managerOne command wires a workspace package, with the path worked out

Step 1 of 3, before: home_impl needs the monitoring_api contract but does not depend on it yet. The two live in different folders, so the relative path is easy to get wrong by hand.

features/home/home_impl/pubspec.yaml
name: home_impl# …dependencies:  # …  locale_core:    path: ../../../shared/locale_core  router_registry:    path: ../../../shared/router_registry

deps external ​

Adds a pub.dev dependency directly to a specific internal package (not to shared/dependencies):

bash
# Add dio to network_sdk_dio
dart run monorepo_toolkit deps external network_sdk_dio dio "^5.4.0"

# Add as a dev dependency
dart run monorepo_toolkit deps external auth_impl mockito -v "^5.4.0" --dev
FlagAbbrDescription
--version-vVersion constraint
--dev-dAdd as a dev dependency instead of a regular dependency

deps check ​

Read-only audit of the third-party packages that individual packages pin directly. It reports:

  • a package pinned with different constraints in several workspace packages (drift);
  • a pin of a package the dependencies / dependencies_core barrels already re-export, in a package that depends on a barrel.
bash
dart run monorepo_toolkit deps check

It exits 1 when it finds either, so CI can run it. A pin can be intentional, for example a package that must also generate outside a monorepo; the output is a list to review, not an auto-fix.

deps align ​

Rewrites every direct pin of one package to a single constraint, then runs dart pub get at the workspace root. yaml_edit keeps comments, formatting and key order.

bash
# Highest constraint already in use
dart run monorepo_toolkit deps align dio

# A specific constraint
dart run monorepo_toolkit deps align dio "^5.9.0"

"Highest" compares lower bounds, then upper bounds. Path, sdk and git entries are not touched.

deps diagnose ​

Runs dart pub get. When version solving fails, it reads the failure text, lists each package that is required with different constraints and who requires each one, and suggests deps align <package> for packages you pin directly. A package that only appears as a transitive dependency has no pin to align; change the dependent instead.

bash
dart run monorepo_toolkit deps diagnose

It never writes dependency_overrides by default, because overrides hide a real conflict. --write-overrides writes the highest conflicting constraint of each package to pubspec_overrides.yaml at the workspace root, copies the root pubspec's existing overrides into it, warns, and retries pub get. Do not commit that file; align the pins and delete it. Failures without a constraint pair (an SDK or null-safety mismatch) are printed as pub reported them.

When to use each subcommand ​

  • deps add -- For packages that many features share (GetIt, injectable, auto_route). These go into the centralized shared/dependencies package.
  • deps external -- For packages only one or two packages need (e.g., dio in network_sdk_dio).
  • deps internal -- For wiring workspace packages together (e.g., making auth_impl depend on auth_api).
  • deps remove -- For cleaning up unused shared dependencies.
  • deps check / deps align / deps diagnose -- When two packages pin the same third-party package differently, or pub get fails on a version conflict.