skip to content

In FVM, how do fvm use and fvm global differ, and which SDK does fvm flutter pick when both are set?

level: middleimportance: must knowfreq 45%

answer

  1. project pin versus machine default
  2. nearest .fvmrc wins
  3. global is a default link
  4. put default/bin on PATH
  5. fallback to PATH's flutter

basics

~20 s

fvm use pins a version for one project in .fvmrc; fvm global sets a machine-wide default link. fvm flutter uses the nearest project pin first, then the global version, then whatever flutter is on PATH.

solid answer

~40 s

`fvm use <version>` is **per project**: it writes `.fvmrc`, links `.fvm/flutter_sdk` and updates project tooling. `fvm global <version>` is **per machine**: it points the link `~/fvm/default` at a cached SDK, and you put `~/fvm/default/bin` on `PATH` so plain `flutter` uses it; FVM warns if your `PATH` resolves `flutter` elsewhere, and `fvm global --unlink` removes it. When you run `fvm flutter` or `fvm dart`, FVM searches from the current directory upward for the nearest `.fvmrc`; if it finds a pin it runs that version, otherwise it uses the global version, and without either it falls back to `flutter` on `PATH`. `fvm list` shows cached versions with Global and Local columns, and `fvm releases` lists installable releases, stable by default.

code

bash · 9 lines
bash
fvm global 3.47.5                       # machine default -> ~/fvm/default
export PATH="$HOME/fvm/default/bin:$PATH" # once, in your shell profile

cd ~/work/client_a && fvm use 3.41.4     # project pin
fvm flutter --version                    # 3.41.4 (project pin wins)
cd ~ && fvm flutter --version            # 3.47.5 (no .fvmrc above, global used)

fvm list                                 # Global and Local columns show both
fvm use stable --pin                     # pin stable's latest release as an exact version

go deeper

for a junior

Know that fvm use is for one project and fvm global is the machine default, and that fvm list shows both.

for a middle

Explain the lookup order, nearest .fvmrc then global then PATH, why global needs default/bin on PATH, and channel pins versus exact versions.

for a senior

Diagnose the wrong SDK running with fvm doctor and fvm list, use --pin or exact versions for reproducibility, and structure pins in nested folders.

for a principal

Set a policy for global defaults versus mandatory project pins so developer machines cannot drift from what CI builds.

## Two scopes FVM manages SDKs at two scopes, and confusing them is the most common FVM mistake. | | `fvm use <version>` | `fvm global <version>` | |---|---|---| | Scope | one project (and its subfolders) | the whole machine | | Stored in | `.fvmrc` in the project root | the link `<fvm dir>/default` | | Links created | `.fvm/flutter_sdk`, `.fvm/versions/<version>` | `default` pointing at the cached SDK | | Side effects | SDK setup, `.gitignore`, `pub get`, VS Code settings | a warning if `PATH` resolves `flutter` elsewhere | | Undo | `fvm use` another version | `fvm global --unlink` | The FVM directory is `~/fvm` by default (`FVM_CACHE_PATH` or `fvm config --cache-path` changes it); cached SDKs live in its `versions/` folder. ## How fvm flutter chooses an SDK `fvm flutter`, `fvm dart` and `fvm exec` all run the same selection: 1. **Project pin.** Starting at the current directory, walk up the directory tree to the nearest folder containing `.fvmrc`. If it pins a version, make sure it is cached and use it. 2. **Global version.** Otherwise, if `fvm global` has set one, use it. 3. **`PATH`.** Otherwise, run whatever `flutter` or `dart` the shell finds. The chosen SDK's `bin` directories are **prepended to `PATH`** for the child process, so tools that the command spawns also see the right SDK. Because the lookup walks upward, a package in `packages/shared` without its own `.fvmrc` uses the pin at the repository root, while an app with its own `.fvmrc` overrides it. ## Making plain flutter use the global version `fvm global` changes a link; it cannot change your shell. For plain `flutter` to use it, `<fvm dir>/default/bin` must be on `PATH`, typically ahead of any other Flutter install. After setting the global version, FVM compares `which flutter` with the expected paths and prints the current and the suggested path when they disagree. In VS Code's integrated terminal the editor may override `PATH`, and FVM says so. ## Seeing what is where - **`fvm list`** — cached SDKs with their channel, Flutter and Dart versions, release date, and markers in the **Global** and **Local** columns; a **Projects** column counts known projects pinning each SDK and labels unpinned ones `Unused`. - **`fvm releases`** — releases available to install; `-c` filters by channel and defaults to `stable`. - **`fvm doctor`** — the project, the pin and the environment FVM sees, useful when the wrong SDK runs. - **`fvm remove <version>`** or **`fvm cleanup`** — free disk space from versions nothing uses. ## Channels versus exact versions Both commands accept a channel name (`stable`, `beta`) or an exact version. A channel pin follows whatever that cached channel checkout is, so two machines can differ. For reproducibility: - pin exact versions, or - use `fvm use stable --pin`, which resolves the channel's latest release and writes that exact version. `fvm flutter upgrade` is refused when the selected version is a release rather than a channel, because upgrading a pinned release would silently change it.

  • In a repository with .fvmrc at the root and none in packages/shared, which SDK does fvm flutter test use inside packages/shared?
    The root's. FVM walks up from the current directory to the nearest `.fvmrc`, so a subfolder without its own file inherits the root pin. A nested project that runs `fvm use` gets its own `.fvmrc`, which then takes precedence for that subtree.
  • Why does FVM refuse fvm flutter upgrade on a project pinned to 3.47.5?
    A release pin means exactly that version. Running `flutter upgrade` inside the cached SDK would move it to a newer build while the pin still says 3.47.5, and every project sharing the cache would change too. FVM allows upgrade only on channel installs; to move a project, run `fvm use` with the new version.

saying these in an interview costs you the question

  • Uses fvm global to pin a single project's version
  • Expects fvm global to change PATH by itself
  • Thinks fvm flutter ignores .fvmrc files in parent directories
  • Pins a channel name and calls the build reproducible
  • Runs fvm flutter upgrade to move a release-pinned project