skip to content

In a multi-package Flutter repository managed with Melos, what does melos bootstrap do, and how do Melos scripts run a command across packages?

level: middleimportance: should knowfreq 30%

answer

  1. a community CLI, not part of the SDK
  2. bootstrap links local packages together
  3. config under melos: in root pubspec
  4. exec runs inside each package
  5. packageFilters: dependsOn, dirExists, scope

basics

~20 s

melos bootstrap resolves every package's dependencies so local packages use each other's source, and runs bootstrap hooks. Scripts under the melos: key run a command once, or with exec run it inside each package matching packageFilters.

solid answer

~40 s

Melos is a community command-line tool for Dart and Flutter repositories that hold many packages. `melos bootstrap` resolves dependencies across the repository so each local package uses its siblings' source rather than hosted versions, and runs any configured bootstrap hooks. In the current 8.x line, used with a pub workspace, the configuration lives under a `melos:` key in the root `pubspec.yaml`; older setups kept it in a separate `melos.yaml`. Scripts there are invoked with `melos run <name>`. A script's `run:` executes a shell command once, while `exec:` runs a command inside every package, with options such as `concurrency`, and `packageFilters` like `dependsOn`, `dirExists`, `scope`, `ignore` or `noPrivate` choose which packages. `melos exec -- flutter test` does the same ad hoc, and `melos version` bumps versions and writes changelogs.

code

yaml · 32 lines
yaml
# pubspec.yaml at the repository root
name: super_app_workspace
publish_to: none

environment:
  sdk: ^3.13.0

workspace:
  - apps/super_app
  - packages/core_ui
  - packages/rides
  - packages/food
  - packages/wallet

dev_dependencies:
  melos: ^8.5.0

melos:
  scripts:
    analyze:
      exec: dart analyze --fatal-infos
    test:
      exec:
        command: flutter test
        concurrency: 1
      packageFilters:
        dirExists:
          - test
    gen:
      exec: dart run build_runner build --delete-conflicting-outputs
      packageFilters:
        dependsOn: build_runner

go deeper

for a junior

Recall that Melos is a community CLI for repositories with many packages, and that bootstrap links local packages together.

for a middle

Explain where current Melos reads its config, the difference between run and exec, and how packageFilters pick packages.

for a senior

Show how you would script analysis, tests and code generation across packages for CI, with concurrency and fail-fast chosen deliberately.

for a principal

Judge whether Melos is still needed on top of pub workspaces, and what it adds for versioning and changelogs versus plain scripts.

## What Melos is A Flutter app split into feature packages, or a family of published packages, ends up with many `pubspec.yaml` files in one repository. Running `flutter pub get`, `flutter test` or code generation in each by hand does not scale. **Melos** is a community-maintained CLI (a dev dependency, not part of the Flutter or Dart SDK) that treats the repository as one workspace and runs commands across its packages. Several large open-source Flutter plugin and package repositories are organized with it. (How pub itself shares one resolution across packages, the `workspace:` list and `resolution: workspace`, is pub's feature; Melos builds on it.) ## Where the configuration lives | Setup | Config location | Package list | |---|---|---| | Current Melos (8.x), with pub workspaces | `melos:` key in the root `pubspec.yaml` | the root's `workspace:` list | | Older Melos releases | a separate `melos.yaml` at the root | `packages:` globs in `melos.yaml` | Both styles still appear in real repositories, so check which one a project uses before editing: a `melos:` section in the root pubspec next to `workspace:`, or a `melos.yaml` with `packages:` globs. ```yaml # pubspec.yaml at the repository root name: super_app_workspace publish_to: none environment: sdk: ^3.13.0 workspace: - apps/super_app - packages/core_ui - packages/rides - packages/food - packages/wallet dev_dependencies: melos: ^8.5.0 melos: scripts: analyze: exec: dart analyze --fatal-infos test: exec: command: flutter test concurrency: 1 packageFilters: dirExists: - test gen: exec: dart run build_runner build --delete-conflicting-outputs packageFilters: dependsOn: build_runner ``` ## melos bootstrap `melos bootstrap` prepares the repository after a clone or a dependency change: 1. It resolves dependencies for all packages so that a package depending on a sibling (for example `rides` on `core_ui`) uses the local source, not a hosted copy. 2. It runs **bootstrap hooks** configured under `command: bootstrap:`, for example a `pre` script that validates the package list. 3. Options such as `runPubGetInParallel` control how resolution is run. With pub workspaces, a single resolution covers every member; older Melos setups achieved local linking by writing override files into each package. ## Scripts: run versus exec A script is invoked with `melos run <name>`. - **`run:`** executes a shell command once, from the repository root. Useful for chaining other scripts (`melos run analyze && melos run test`). - **`exec:`** runs a command **inside each selected package**, one package at a time or in parallel. It can be a string, or a map with `command` and `concurrency`. - **`packageFilters`** selects packages for an `exec` script: - `dependsOn`: only packages that depend on a given package, e.g. code generation only where `build_runner` is a dependency; - `dirExists`: only packages with a folder, e.g. `test` or `android`; - `scope` and `ignore`: include or exclude by package-name glob; - `noPrivate`: skip packages marked `publish_to: none`, handy for a publish dry run. The same can be done ad hoc from the command line: `melos exec -c 1 --fail-fast -- flutter test` runs `flutter test` in every package, one at a time, stopping at the first failure. ## Other commands worth naming - `melos version` bumps package versions and writes changelogs from commit history, configured under `command: version:` (for example `linkToCommits` and `workspaceChangelog`). - `melos clean` removes build artifacts and can run clean hooks. ## A typical CI flow 1. `melos bootstrap` after checkout, so every package resolves against local siblings. 2. `melos run analyze`, failing on any analyzer issue across all packages. 3. `melos run gen` where packages use code generation, before tests that need generated files. 4. `melos run test`, optionally limited to changed packages by the CI system. Choosing `concurrency: 1` for heavy steps keeps memory use predictable on small CI machines; lighter steps can run several packages in parallel. ## Where Melos stops Melos runs commands across packages; it is not a build cache or a remote executor. It does not make `flutter build` faster, and it does not change how the app is compiled: the shipped app is still one Flutter build. FVM 4 added a Melos integration that keeps Melos's `sdkPath` setting pointed at the project's pinned Flutter SDK, so every package runs on the same Flutter version.

  • Why would you give the code-generation script a dependsOn: build_runner filter?
    Only packages that use code generation declare `build_runner`. The filter runs `dart run build_runner build` in exactly those packages, instead of failing or wasting time in packages that have no generator configured.
  • What is the difference between melos run test and melos exec -- flutter test?
    `melos run test` runs the script named `test` from the configuration, with whatever filters and concurrency it declares. `melos exec -- flutter test` runs the given command in every package Melos sees, using only the filters passed on the command line.

saying these in an interview costs you the question

  • Thinks Melos ships inside the Flutter SDK
  • Says melos bootstrap publishes local packages to pub.dev
  • Expects scripts in a pubspec scripts key read by pub
  • Believes exec runs the command once at the root
  • Assumes Melos caches build outputs like a build system