conceptadev/fvm
66.7
Adequate · 23 September 2026
11.1k
lines of production code
Dart
primary language
5
measurements over time
What this system is
This system is a command-line tool for managing multiple Flutter SDK versions, enabling developers to install, switch, and cache specific SDK releases across different projects. It provides a structured API and a Model Context Protocol (MCP) server to allow external tooling and AI agents to programmatically query SDK states, manage installations, and perform cleanup operations. The core functionality handles SDK caching, version pinning, and project configuration updates, ensuring consistent development environments.
How it got here
2019–2020 — Dart migration and v4.3.1 release
13 changes.
The project underwent a comprehensive migration of its core library from Go to Dart, accompanied by a complete rewrite of the command interface and SDK management workflows. This period culminated in the v4.3.1 release, which introduced a new JSON API, native binary compilation support, and extensive test coverage to stabilize the new architecture.
2021–2024 — Service layer and API restructuring
14 changes.
This period focused on introducing a structured service layer to manage configuration, caching, and project state, alongside a new JSON API for programmatic access. The work involved refactoring core data models and implementing robust release client logic with fallback mechanisms, supported by extensive test coverage and local validation scripts.
2025–2026 — MCP integration and test expansion
6 changes.
This period focused on integrating Model Context Protocol (MCP) support via a new standalone server and expanding comprehensive test coverage across services, workflows, and cache migrations. Development also included enforcing code quality through Husky hooks and restructuring release tooling into a modular package.
Features
Added tooling for Homebrew formula generation and test fixture recording
The tool directory now includes a Homebrew formula template (fvm.template.rb) for packaging FVM, a Grind script (grind.dart) to automate compilation, testing, and coverage tasks, and a utility script (record\_test\_fixtures.dart) to generate test fixtures for Flutter version metadata and release data.
tool · high confidence
Enforce code quality checks via Husky pre-commit and pre-push hooks
The project now automatically runs static analysis and formatting checks before commits and pushes. The pre-commit hook executes \lint\_staged\ on staged files and runs \dart analyze --fatal-infos\ across the entire project, while also invoking the DCM analyzer if available. The pre-push hook ensures the Dart/Flutter environment is correctly configured in the PATH and repeats the \dart analyze\ and optional DCM checks to prevent pushing code with analysis errors.
.husky · high confidence
Introduce standalone fvm\_mcp server for FVM tooling via MCP
The new \fvm\_mcp\ package provides a standalone Model Context Protocol (MCP) server that exposes FVM capabilities as tools. It offers read-only JSON API tools (such as \fvm.api.list\ and \fvm.api.releases\) and mutating tools (like \fvm.install\ and \fvm.remove\) that are gated by the installed FVM version—JSON API features require FVM ≥ 3.1.2, while mutating commands require FVM ≥ 3.2.0 for non-interactive support. The server is available as a standalone binary or can be embedded directly into the FVM CLI via a new \fvm mcp\ subcommand, allowing MCP clients to manage Flutter SDK versions and run FVM commands over stdio.
_fvm\mcp · high confidence
Introduces new utility library for string manipulation, versioning, and environment context
The \lib/src/utils\ directory now contains a comprehensive set of new helper modules. This includes \change\_case.dart\ for converting strings to camelCase, snake\_case, and other formats; \compare\_semver.dart\ and \helpers.dart\ for semantic version parsing, channel weighting, and Flutter/Dart version extraction; \context.dart\ (with its generated mapper) to centralize application state, configuration, and environment handling; and \constants.dart\ for defining global paths, URLs, and CI detection variables. Additional utilities cover file operations (\file\_utils.dart\, \extensions.dart\), Git operations (\git\_utils.dart\, \git\_clone\_progress\_tracker.dart\), and system path resolution (\which.dart\, \convert\_posix\_path.dart\).
lib/src/utils · high confidence
New JSON API and refactored command structure
This release introduces a new \fvm api\ command that exposes FVM data (installed versions, releases, project config, and cleanup recommendations) as structured JSON for external tooling and integrations. The command-line interface has been refactored with a new \BaseFvmCommand\ base class and helper extensions for argument parsing. Several existing commands have been rewritten or updated, including \cleanup\ (which now explicitly preserves recommended patch upgrades when removing unused SDKs), \config\ (with support for the \update-check\ setting), \doctor\ (improved IDE configuration validation), \global\ (with \--unlink\ and \--force\ flags), \install\ (setup runs by default), and \list\ (now shows project usage counts and handles forked versions correctly).
lib/src/commands · high confidence
New JSON API response models for cache, cleanup, releases, projects, and context
The application now includes a structured set of data models for its internal JSON API, enabling consistent serialization and deserialization of responses. Users interacting with the cache can now see detailed version information including unreferenced SDKs, while cleanup operations expose specific patch upgrade actions and removable unused versions. Additionally, dedicated models handle Flutter release channels, individual project configurations, and the current FVM context, all powered by the dart\_mappable library for reliable JSON mapping.
lib/src/api/models · high confidence
New JSON API service for programmatic FVM access
A new \ApiService\ has been introduced in \lib/src/api\ to expose FVM data via a structured JSON interface, enabling integrations and external tooling to query the current context, project details, cached SDK versions (including size and unreferenced status), cleanup plans (upgrades and unused SDKs), and available Flutter releases with filtering options.
lib/src/api · high confidence
New bin/compile.dart script for native binary installation
A new script, bin/compile.dart, has been added to the project. This script automates the process of compiling the FVM Dart package into a native executable and installing it to /usr/local/bin on macOS and Linux systems. It handles the compilation via \dart compile exe\, moves the resulting binary to the destination, cleans up temporary files, and deactivates any previously globally activated version of FVM. The existing bin/main.dart entry point remains unchanged, continuing to serve as the standard CLI runner.
bin · high confidence
New releases client with caching and fallback logic
A new \FlutterReleaseClient\ service has been introduced to manage Flutter SDK release data. This client implements an instance-level cache to avoid redundant network requests and includes a robust fallback mechanism: it attempts to fetch release metadata from a GitHub-hosted JSON file first, and if that fails, it falls back to the official Google Storage endpoint. This ensures better reliability for users, particularly in regions where direct access to Google services may be restricted, as indicated by the specific error messaging for users in China.
_lib/src/services/releases\service · high confidence
Removals
Removal of placeholder CLI commands
The CLI no longer exposes the \beta\, \dev\, \master\, \prune\, \remove\, \stable\, and \root\ commands. These files, which contained only stub implementations or default Cobra scaffolding, have been deleted, cleaning up the command interface by removing unused entry points.
cmd · high confidence
Architecture
Refactored SDK management into dedicated workflow classes
The SDK management logic in lib/src/workflows has been reorganized into a set of specialized workflow classes to improve code structure and maintainability. This change introduces dedicated handlers for specific tasks: version validation (ValidateFlutterVersionWorkflow), cache integrity and corruption recovery (EnsureCacheWorkflow), project constraint checking (CheckProjectConstraintsWorkflow), and dependency resolution (ResolveProjectDependenciesWorkflow). It also adds automated configuration updates for VS Code (UpdateVsCodeSettingsWorkflow), Melos (UpdateMelosSettingsWorkflow), and .gitignore (SetupGitIgnoreWorkflow), alongside a streamlined orchestration flow in UseVersionWorkflow. This refactoring centralizes the logic for switching Flutter SDK versions, ensuring that project references, IDE settings, and dependencies are consistently updated while handling edge cases like corrupted caches and version mismatches more robustly.
lib/src/workflows · high confidence
Behavioural changes
FVM version 4.3.1 release with updated command runner
This release updates the FVM package version to 4.3.1. The core command runner in \lib/src/runner.dart\ has been restructured to explicitly register a comprehensive set of subcommands (including Install, Use, List, Cleanup, Remove, Releases, Flutter, Dart, Fork, Doctor, Spawn, Config, Exec, Destroy, API, Global, Flavor, and IntegrationTest) and integrates a \PubUpdater\ to check for and notify users of available updates. It also introduces logic to warn users about deprecated (\FVM\_GIT\_CACHE\) and legacy (\FVM\_HOME\) environment variables, guiding them toward the new \FVM\_FLUTTER\_URL\ and \FVM\_CACHE\_PATH\ settings respectively.
lib/src · high confidence
Introduce new service layer for configuration, caching, and project management
The application now uses a structured service layer in lib/src/services to manage core behaviors. AppConfigService consolidates configuration merging from global, environment, and project sources, including legacy environment variable support. CacheService handles SDK version listing, integrity verification, and removal, while CleanupService identifies unused SDKs and suggests patch upgrades. GitService manages the local git cache with hardened operations, file locking, and corruption fallbacks. ProjectService and ProjectRegistryService track project roots and pinned versions to enable accurate 'unused' SDK detection in list commands. ProcessService ensures git commands run in isolated environments to prevent repository context leakage.
lib/src/services · high confidence
Migration from Go to Dart implementation
The library's implementation language has changed from Go to Dart. The previous Go-based setup logic (lib/setup.go) which handled channel cloning, directory renaming, and running Flutter doctor has been removed. It is replaced by a new Dart entry point (lib/fvm.dart) that exports a comprehensive set of Dart-based models, services (cache, project, releases), and utilities, indicating a complete rewrite of the core library functionality.
lib · high confidence
New data models for cached versions, cleanup actions, and configuration
The models layer now includes new mappable classes to support updated SDK management and configuration handling. CacheFlutterVersion provides detailed metadata for cached SDKs, including robust setup detection and version parsing from both modern JSON metadata and legacy files. CleanupAction and PatchUpgrade models define the structure for tracking and applying cached patch upgrades during cleanup operations. Additionally, the config model introduces EnvConfig and AppConfig classes with new options like useGitCache and gitCachePath, enabling global git cache configuration for faster version installs.
lib/src/models · high confidence
New release data models for SDK version tracking
The releases service now uses new \FlutterReleasesResponse\ and \FlutterSdkRelease\ models to parse and manage SDK version data. These models introduce support for tracking specific Dart SDK versions and architectures per release, enabling the system to correctly identify and prefer native archives for the current platform. This change also adds explicit mapping for release channels (stable, beta, dev) and improves the robustness of parsing release metadata, ensuring that version lookups and channel inference work accurately across different operating systems and architectures.
_lib/src/services/releases\service/models · high confidence
Release tooling migrated to a dedicated package structure
The release automation scripts have been reorganized into a standalone \tool/release\_tool\ package. This change introduces a new \grind.dart\ entry point that configures the \cli\_pkg\ library for publishing the FVM tool to GitHub and Homebrew, including a new \getReleases\ task to fetch and list recent releases. The migration also includes a dedicated test suite (\grind\_test.dart\) to verify release fetching logic and HTTP request handling, ensuring the release process is more modular and testable.
_tool/release\tool · high confidence
Test coverage
Added comprehensive test suite for FVM commands and version handling; Added integration test for FVM v3 to current cache migration; Added service-layer test coverage for configuration, caching, and Git operations; Added test coverage for FVM command-line interface; Added test helpers for fast, deterministic Flutter SDK mocking; Added test support assets for PTY-based SIGINT handling and sample project templates; Added tests for FVM services; Added unit tests for FlutterVersion model; Added unit tests for cache version, root version file, and project registry models; Added unit tests for path conversion, file lock detection, and git clone progress tracking; Added unit tests for utility functions; Expanded test coverage for FVM command-line operations; Expanded test coverage for FVM workflow behaviors; New local testing and migration validation scripts.
Dependencies
New documentation site and MCP server dependencies added
The project now includes a new Nextra-based documentation site under the \docs/\ directory, introducing dependencies such as Next.js, React, Tailwind CSS, and Algolia DocSearch. Additionally, a new \fvm\_mcp\ package has been added to expose FVM as an MCP server, bringing in the \dart\_mcp\ dependency. The main FVM CLI and its release tooling have also updated their dependency sets, including upgrades to \cli\_pkg\ in the release tool and various core packages in the main \pubspec.yaml\.
(dependencies) · high confidence
Updated Flutter release metadata and version bump
The tool's local release manifest files (releases\_macos.json, releases\_windows.json, releases\_linux.json) have been updated with the latest Flutter SDK versions from the official infrastructure, ensuring the CLI can discover and install the most recent stable, beta, and dev channels. This change also includes a version bump for the tool itself, reflecting the current release state.
(repo-wide) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 61 → 67 (+5.5)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 98 → 92 (-5.5)
- Architecture 98 → 98 (-0.7)
- Maturity 60 → 61 (+1.0)
- Readiness 49 → 62 (+12.6)
- Security 65 → 65 (+0.5)
- Domain Modelling 100 → 100 (+0.0)
Resolved (35)
- Boundary-crossing change coupling: base_command.dart ↔ config_model.dart (lib/src/commands/base_command.dart)
- Boundary-crossing change coupling: base_command.dart ↔ flutter_service.dart (lib/src/commands/base_command.dart)
- Change coupling: dart_command.dart ↔ exec_command.dart (lib/src/commands/dart_command.dart)
- Change coupling: doctor_command.dart ↔ flavor_command.dart (lib/src/commands/doctor_command.dart)
- Coverage not included — suite not readable by the collector
- Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
- High IaC: DS-0025 (.docker/alpine/Dockerfile)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- …and 15 more
New (100)
- CacheService.getAllVersions (cognitive 25) (lib/src/services/cache_service.dart)
- Change coupling clique: install_command.dart, remove_command.dart, use_command.dart (lib/src/commands/install_command.dart)
- ClassTooLong: GitService (lib/src/services/git_service.dart)
- CleanupCommand._printPlan (cognitive 20) (lib/src/commands/cleanup_command.dart)
- DoctorCommand._printIdeLinks (cognitive 52) (lib/src/commands/doctor_command.dart)
- DoctorCommand._printIdeLinks (cyclomatic 16) (lib/src/commands/doctor_command.dart)
- Documentation: no installation or build instructions (README.md)
- Duplicated block (10 lines × 2) (lib/src/services/app_config_service.dart)
- Duplicated block (11 lines × 2) (lib/src/runner.dart)
- Duplicated block (12 lines × 2) (fvm_mcp/lib/src/server.dart)
- Duplicated block (13 lines × 2) (fvm_mcp/lib/src/server.dart)
- Duplicated block (17–18 lines × 2) (fvm_mcp/lib/src/server.dart)
- EnsureCacheWorkflow.call (cognitive 26) (lib/src/workflows/ensure_cache.workflow.dart)
- EnsureCacheWorkflow.call (cyclomatic 20) (lib/src/workflows/ensure_cache.workflow.dart)
- FlutterService._tryCloneFromGitCache (cognitive 20) (lib/src/services/flutter_service.dart)
- FunctionTooLong: MainHeading.MainHeading (docs/components/MainHeading.tsx)
- FvmCommandRunner.runCommand (cognitive 20) (lib/src/runner.dart)
- GitService._dissociateVersionFromGitCache (cognitive 18) (lib/src/services/git_service.dart)
- GitService._purgeOsMetadataFromRefs (cognitive 20) (lib/src/services/git_service.dart)
- GitService._withGitCacheLock (cognitive 38) (lib/src/services/git_service.dart)
- …and 80 more
Changes since last survey
- 44 commits — 38 feature/other, 6 fixes
By area
- (root) — 21 commits
- lib/src — 11 commits
- docs/pages — 6 commits
- (repo) — 4 commits
- .github/actions — 1 commit
- .github/workflows — 1 commit
Notable commits
- fix: fix: address project tracking review feedback
- fix: fix: make cleanup unused the same set as fvm list
- fix: fix: prevent git-cache migration from destroying unrelated repositories (#1060)
- fix: fix: prove api list usage hints and drop the local FVM pin
- fix: fix: skip the --remove-unused hint when nothing is removable
- fix: fix: wait for Flutter cleanup after SIGINT (#1054)
- change: Allow Fetch Data to update release cache
- change: Flat: latest data (2026-08-06T23:07:02.450Z) { "date": "2026-08-06T23:07:02.450Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 792, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 396, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 395, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-08-17T14:39:56.121Z) { "date": "2026-08-17T14:39:56.121Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 1654, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 827, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 825, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-08-19T22:28:04.124Z) { "date": "2026-08-19T22:28:04.124Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 792, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 396, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 395, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-08-19T23:26:01.312Z) { "date": "2026-08-19T23:26:01.312Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 862, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 431, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" } ] }
- change: Flat: latest data (2026-08-20T01:27:12.587Z) { "date": "2026-08-20T01:27:12.587Z", "files": [ { "name": "releases_linux.json", "deltaBytes": 430, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-08-27T00:11:38.697Z) { "date": "2026-08-27T00:11:38.697Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 862, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 431, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 430, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-08-27T19:36:26.220Z) { "date": "2026-08-27T19:36:26.220Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 792, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 396, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 395, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-09-03T18:20:04.659Z) { "date": "2026-09-03T18:20:04.659Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 862, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 431, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 430, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-09-09T18:20:14.280Z) { "date": "2026-09-09T18:20:14.280Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 792, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 396, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 395, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-09-11T19:12:27.224Z) { "date": "2026-09-11T19:12:27.224Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 862, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 431, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" } ] }
- change: Flat: latest data (2026-09-11T20:15:23.921Z) { "date": "2026-09-11T20:15:23.921Z", "files": [ { "name": "releases_linux.json", "deltaBytes": 430, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-09-11T21:13:14.658Z) { "date": "2026-09-11T21:13:14.658Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 792, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 396, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 395, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- change: Flat: latest data (2026-09-18T21:13:41.558Z) { "date": "2026-09-18T21:13:41.558Z", "files": [ { "name": "releases_macos.json", "deltaBytes": 792, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_macos.json" }, { "name": "releases_windows.json", "deltaBytes": 396, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_windows.json" }, { "name": "releases_linux.json", "deltaBytes": 395, "source": "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" } ] }
- …and 24 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
conceptadev/fvm was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 23 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 19d3dde10bcac026a2194859d150e729af693e90 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-955b9cee9818.