| <!-- | |
| Copyright 2025 The Flutter Authors | |
| Use of this source code is governed by a BSD-style license that can be | |
| found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. | |
| --> | |
| # Dart & Flutter DevTools Extensions | |
| Extend Dart & Flutter's developer tool suite, | |
| [Dart DevTools](https://docs.flutter.dev/tools/devtools), with your own custom tool. | |
| DevTools' extension framework allows you to build tools that can leverage existing frameworks | |
| and utilities from DevTools (VM service connection, theming, shared widgets, utilities, etc.). | |
| You can add a DevTools extension to an existing pub package, or you can create a new package | |
| that provides a DevTools extension only. In both these scenarios, the end-user must list a | |
| dependency on the package providing the DevTools extension in order to see the extension | |
| in DevTools. | |
| When DevTools detects an extension is available, either from the user's app or their IDE, | |
| the extension will show up in its own DevTools tab. The DevTools extension's content, a | |
| Flutter web app, is embedded in an iFrame displayed dynamically in DevTools. | |
|  | |
| ### What types of tools are supported? | |
| With the DevTools extensions framework you can build many types of tools, including: | |
| - Companion tools for existing packages | |
| - New tools that are shipped as their own package | |
| - Tools that interact with a running application | |
| - Tools that **do not** interact with a running application | |
| - Tools that interact with project files opened in the IDE | |
| - _Planned for the future_: tools that interact with the Analysis server (upvote this | |
| [issue](https://github.com/flutter/devtools/issues/7658) if you want this feature sooner!) | |
| The DevTools Extensions framework comes with out of the box features that make | |
| distributing your extension to users seamless: | |
| - Users can use your tool from DevTools in the browser | |
| - Users can use your tool embedded directly in their IDE | |
| - Users can discover and open your tool from Dart & Flutter supported IDEs | |
| Follow the instructions below to get started, and use the | |
| [end-to-end example](https://github.com/flutter/devtools/tree/master/packages/devtools_extensions/example/) | |
| for reference. | |
| # Table of contents | |
| 1. [Create a DevTools extension](#create-a-devtools-extension) | |
| - [Step 1: Setup your package hierarchy](#step-1-setup-your-package-hierarchy) | |
| - [Standalone extensions](#standalone-extensions) | |
| - [Companion extensions](#companion-extensions) | |
| - [Step 2: Configure your extension](#step-2-configure-your-extension) | |
| - [Step 3: Build your extension](#step-3-build-your-extension) | |
| - [Step 4: Debug your extension](#step-4-debug-your-extension) | |
| 2. [Publish your package with a DevTools extension](#publish-your-package-with-a-devTools-extension) | |
| 3. [Resources and support](#resources-and-support) | |
| 4. [Testimonies from extension authors](#testimonies-from-extension-authors) | |
| ## Create a DevTools Extension | |
| ### Step 1: Setup your package hierarchy | |
| #### Standalone extensions | |
| For a standalone extension (an extension that is not being shipped as part of an existing | |
| pub package), it is acceptable to include your extension source code in the same package | |
| that the extension is shipped with. This will simplify development, and since users of your | |
| package will add a dependency on your package as a `dev_dependency`, the size of your | |
| package will not affect the user's app size. Your package structure will look like this: | |
| ``` | |
| my_new_tool | |
| extension/ | |
| devtools/ | |
| build/ | |
| ... # pre-compiled output of the Flutter web app under lib/ | |
| config.yaml | |
| lib/ # source code for your extension Flutter web app | |
| src/ | |
| ... | |
| ``` | |
| Since the extension must be built as a Flutter web app, use `flutter create` to generate | |
| the package for your DevTools extension: | |
| ```console | |
| flutter create --template app --platforms web my_new_tool | |
| ``` | |
| Now, use the `my_new_tool` package to [configure your extension](#configure-your-extension) | |
| in the next step. | |
| #### Companion extensions | |
| For a companion extension (an extension that is shipped as part of an existing pub package), | |
| we recommend that you place your extension source code outside of your pub package. This | |
| will help keep your package size as small as possible, since you will want to avoid inflating | |
| the size of user apps that depend on your package. Here is the recommended package structure: | |
| ``` | |
| some_pkg/ # formerly the repository root of your pub package | |
| packages/ | |
| some_pkg/ # your pub package | |
| extension/ | |
| devtools/ | |
| build/ | |
| ... # pre-compiled output of some_pkg_devtools_extension/lib | |
| config.yaml | |
| some_pkg_devtools_extension/ | |
| lib/ # source code for your extension Flutter web app | |
| ``` | |
| ### Step 2: Configure your extension | |
| In the Dart package that will provide the DevTools extension to users, | |
| add a top-level `extension` directory: | |
| ``` | |
| some_pkg | |
| extension/ | |
| lib/ | |
| ... | |
| ``` | |
| Under the `extension` directory, create the following structure: | |
| ``` | |
| extension | |
| devtools/ | |
| build/ | |
| config.yaml | |
| ``` | |
| The `config.yaml` file contains metadata that DevTools needs to load the extension. | |
| ```yaml | |
| name: some_pkg | |
| issueTracker: <link_to_your_issue_tracker.com> | |
| version: 0.0.1 | |
| materialIconCodePoint: '0xe0b1' | |
| requiresConnection: true # optional field - defaults to true | |
| ``` | |
| Copy the `config.yaml` file content above and paste it into the `config.yaml` file you just | |
| created in your package. **It is important that you use the exact file name and field names | |
| as shown, or else your extension may fail to load in DevTools.** | |
| For each key, fill in the appropriate value for your package. | |
| * `name`: the package name that this DevTools extension belongs to. The value of this field | |
| will be used in the extension page title bar. **(required)** | |
| * `issueTracker`: the url for your issue tracker. When a user clicks the “Report an issue” | |
| link in the DevTools UI, they will be directed to this url. **(required)** | |
| * `version`: the version of your DevTools extension. This version number should evolve over | |
| time as you ship new features for your extension. The value of this field will be used in the | |
| extension page title bar. **(required)** | |
|  | |
| * `materialIconCodePoint`: corresponds to the codepoint value of an icon from | |
| [material/icons.dart](https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/icons.dart). | |
| This icon will be used for the extension’s tab in the top-level DevTools tab bar. **(required)** | |
|  | |
| * `requiresConnection`: whether the extension requires a connected Dart or Flutter app to | |
| use. This is an optional field that will default to `true` if unspecified. **(optional)** | |
| For the most up-to-date documentation on the `config.yaml` spec, see | |
| [extension_config_spec.md](https://github.com/flutter/devtools/blob/master/packages/devtools_extensions/extension_config_spec.md) | |
| Now it is time to build your extension. | |
| ### Step 3: Build your extension | |
| 1. Create the Flutter web app | |
| - **Skip this step if you are building a standalone extension, since you already did | |
| this when you set up your package hierarchy.** | |
| From the directory where you want your extension source code to live, run the following | |
| command, replacing `some_pkg_devtools_extension` with | |
| `<your_package_name>_devtools_extension`: | |
| ```console | |
| flutter create --template app --platforms web some_pkg_devtools_extension | |
| ``` | |
| 2. Add the `package:devtools_extensions` dependency to your extension Flutter web app. | |
| ```console | |
| flutter pub add devtools_extensions | |
| ``` | |
| You will likely also want to add a dependency on | |
| [package:devtools_app_shared](https://pub.dev/packages/devtools_app_shared), which contains | |
| shared services, utilities, and UI components for you to use while building your extension. | |
| See [devtools_app_shared/example](https://github.com/flutter/devtools/tree/master/packages/devtools_app_shared/example) | |
| for sample usages. | |
| ```console | |
| flutter pub add devtools_app_shared | |
| ``` | |
| 3. Add the `DevToolsExtension` widget at the root of your Fluter web app. | |
| In `lib/main.dart`, add the following: | |
| ```dart | |
| import 'package:devtools_extensions/devtools_extensions.dart'; | |
| import 'package:flutter/material.dart'; | |
| void main() { | |
| runApp(const SomePkgDevToolsExtension()); | |
| } | |
| class SomePkgDevToolsExtension extends StatelessWidget { | |
| const SomePkgDevToolsExtension({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return const DevToolsExtension( | |
| child: Placeholder(), // Build your extension here | |
| ); | |
| } | |
| } | |
| ``` | |
| The `DevToolsExtension` widget automatically performs all extension initialization required | |
| to interact with DevTools. From anywhere in your extension web app, you can access the globals: | |
| - `extensionManager`: a manager for interacting with DevTools or the extensions framework | |
| - `serviceManager`: a manager for interacting with the connected vm service, if present | |
| - `dtdManager`: a manager for interacting with the Dart Tooling Daemon, if present | |
| ### Step 4: Debug your extension | |
| #### Use the Simulated DevTools Environment (recommended for development) | |
| For debugging purposes, you will likely want to use the "simulated DevTools environment". This | |
| is a simulated environment that allows you to build your extension without having to develop it | |
| as an embedded iFrame in DevTools. Running your extension this way will wrap your extension | |
| with an environment that simulates the DevTools-to-extension connection. It also | |
| gives you access to hot restart and a faster development cycle. | |
|  | |
| 1. Your DevTools extension. | |
| 2. The VM service URI for a test app that your DevTools extension will interact with. This app | |
| should depend on your extension’s parent package. | |
| 3. Buttons to perform actions that a user may trigger from DevTools. | |
| 4. Logs showing the messages that will be sent between your extension and DevTools. | |
| The simulated environment is enabled by an environment parameter `use_simulated_environment`. | |
| To run your extension web app with this flag enabled, add a configuration to your `launch.json` | |
| file in VS code: | |
| ```json | |
| { | |
| ... | |
| "configurations": [ | |
| ... | |
| { | |
| "name": "devtools_extension + simulated environment", | |
| "cwd": "relative/path/to/your/extension", | |
| "request": "launch", | |
| "type": "dart", | |
| "args": [ | |
| "--dart-define=use_simulated_environment=true" | |
| ], | |
| }, | |
| ] | |
| } | |
| ``` | |
| or launch your app from the command line with the added flag: | |
| ```console | |
| flutter run -d chrome --dart-define=use_simulated_environment=true | |
| ``` | |
| #### Use a real DevTools Environment | |
| To use a real DevTools environment, you will need to perform a series of setup steps: | |
| 1. Develop your extension to a point where you are ready to test your changes in a | |
| real DevTools environment. Build your flutter web app and copy the built assets from | |
| `your_extension_web_app/build/web` to your pub package's `extension/devtools/build` directory. | |
| Use the `build_and_copy` command from `package:devtools_extensions` to help with this step. | |
| ```sh | |
| cd your_extension_web_app; | |
| flutter pub get; | |
| dart run devtools_extensions build_and_copy --source=. --dest=../some_pkg/extension/devtools | |
| ``` | |
| To ensure that your extension is setup properly for loading in DevTools, run the | |
| `validate` command from `package:devtools_extensions`. The `--package` argument | |
| should point to the root of the Dart package that this extension will be published | |
| with. | |
| ```sh | |
| cd your_extension_web_app; | |
| flutter pub get; | |
| dart run devtools_extensions validate --package=../some_pkg | |
| ``` | |
| 2. Prepare a test environment with a dependency on your pub package that is providing the | |
| extension. | |
| - In the Dart or Flutter project where you are adding a dependency on your package, add a | |
| [path](https://dart.dev/tools/pub/dependencies#path-packages) dependency that points to your | |
| local package source code (the package that contains the `extension/devtools/` directory with | |
| your extension's assets). Once you have done this, run `pub get` on the package. | |
| - **If your extension requires a running application**, then you'll need to run the app that | |
| depends on your extension. | |
| - **If your extension does not require a running application**, then you will need to | |
| open the test Dart or Flutter project that depends on your package in a supported IDE | |
| (VS Code or IntelliJ / Android Studio). | |
| 3. Start DevTools in one of the following ways: | |
| - **If your extension requires a running application**, you can open DevTools either from the URI | |
| that was printed to command line when you ran the test app, or from the IDE where you | |
| ran your test app. | |
| - **If your extension does not require a running application**, you can open your Dart or Flutter | |
| project that depends on your package in a supported IDE (VS Code or IntelliJ / Android Studio). | |
| Open DevTools from the IDE to see your extension in the browser. | |
| - Requires Dart SDK >= 3.5 and Flutter SDK >= 3.23 | |
| - **If you need local or unreleased changes from DevTools**, you'll need to build and run | |
| DevTools from source. See the DevTools [CONTRIBUTING.md]() for a guide on how to do this. | |
| You'll need to build DevTools with the server and the front end to test extensions - see | |
| [instructions](https://github.com/flutter/devtools/blob/master/CONTRIBUTING.md#development-devtools-server--devtools-flutter-web-app). | |
| 4. Connect your test app to DevTools if it is not connected already, and you should see a tab | |
| in the DevTools app bar for your extension. The enabled or disabled state of your extension is | |
| managed by DevTools, which is exposed from an "Extensions" menu in DevTools, available from the | |
| action buttons in the upper right corner of the screen. | |
| ## Publish your package with a DevTools extension | |
| In order for a package to provide a DevTools extension to its users, it must be published with the | |
| expected content in the `your_package/extension/devtools/` directory (see the | |
| [setup instructions](#setup-your-package-hierarchy) above). | |
| 1. Ensure the `extension/devtools/config.yaml` file exists and is configured per the | |
| [specifications above](#setup-your-package-hierarchy). You can run the `validate` command | |
| from `package:devtools_extensions` to verify. | |
| ```sh | |
| cd your_extension_web_app; | |
| flutter pub get; | |
| dart run devtools_extensions validate --package=path/to/pkg_providing_your_extension_assets | |
| ``` | |
| 2. Use the `build_and_copy` command provided by `package:devtools_extensions` to build | |
| your extension and copy the output to the `extension/devtools` directory: | |
| ```sh | |
| cd your_extension_web_app; | |
| flutter pub get; | |
| dart run devtools_extensions build_and_copy --source=. --dest=../some_pkg/extension/devtools | |
| ``` | |
| Then publish your package. When running `pub publish`, you will see a warning if you | |
| do not have the `config.yaml` file and a non-empty `build` directory as required. | |
| ### What if I don't want the `extension/devtools/build/` contents checked into source control? | |
| As a package author, the content that you check into your git repository is completely up to you. | |
| If you want the contents of `extension/devtools/build/` to be git ignored, then you'll just need | |
| to ensure that the extension web app is always built and included in `extension/devtools/build/` | |
| when you publish your package. To do so, add the following to a `.pubignore` file in the | |
| `extension/devtools/` directory: | |
| ``` | |
| !build | |
| ``` | |
| This will ensure that, even if the `extension/devtools/build` directory has been been git | |
| ignored, the directory will still be included when publishing the package on pub. | |
| To verify the published extension contents are always up to date, consider adding a tool | |
| script to your repo that looks something like this: | |
| **publish.sh** | |
| ```sh | |
| pushd your_extension_web_app | |
| flutter pub get | |
| dart run devtools_extensions build_and_copy --source=. --dest=../your_pub_package/extension/devtools | |
| popd | |
| pushd your_pub_package | |
| flutter pub publish | |
| popd | |
| ``` | |
| ## Resources and support | |
| Please join the [Flutter Discord server](https://github.com/flutter/flutter/blob/master/docs/contributing/Chat.md) and then check out | |
| the [#devtools-extension-authors](https://discord.com/channels/608014603317936148/1159561514072690739) | |
| channel to connect with other DevTools extension authors and the DevTools team. | |
| For feature requests or bugs, please [file an issue](https://github.com/flutter/devtools/issues/new) | |
| on the DevTools Github repository. | |
| For other documentation and guides, check out the | |
| [DevTools Extensions](https://docs.flutter.dev/tools/devtools/extensions) page on flutter.dev or | |
| [Dart and Flutter DevTools extensions](https://medium.com/flutter/dart-flutter-devtools-extensions-c8bc1aaf8e5f), | |
| a free article on Medium. | |
| ## Testimonies from extension authors | |
| Several packages authors in the Dart and Flutter ecosystem have built their own DevTools | |
| extensions to provide their users with a great developer experience. | |
| * "DevTools extensions are a neat way to save hours of debugging by showing information | |
| that would be otherwise difficult to obtain." - Remi Rousselet, | |
| [package:provider](https://pub.dev/packages/provider) | |
| * "By allowing developers to inspect databases and find potential issues in the familiar | |
| DevTools environment, Drift's DevTools extension saves users a lot of time and makes the | |
| package easier to use. Writing the extension was straightforward, and I think even simple | |
| extensions can help users a lot." - Simon Binder, [package:drift](https://pub.dev/packages/drift) | |
| * "Our DevTools extension allows Serverpod to make our developer tooling available for more | |
| platforms and with better integration with the Dart ecosystem. Having the tools bundled with | |
| our Serverpod package is a huge benefit, as our users won't have to install any additional | |
| applications." - Viktor Lidholt, [package:serverpod](https://pub.dev/packages/serverpod) | |
| * "Thanks to DevTools extensions we could develop a separate inspector tab for interacting | |
| with native platform views (such as a native Android button). It allowed our Patrol users | |
| to explore native view hierarchies without installing any additional tooling - distributed | |
| within the Patrol package itself." - Mateusz Wojtczak & the Patrol | |
| team, [package:patrol](https://pub.dev/packages/patrol) | |
| ## Supported Flutter versions | |
| This package follows the `flutter/packages` | |
| [policy](https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#supported-flutter-versions) | |
| for supported Flutter versions, which states that a package will support the latest `stable` | |
| version of Flutter, as well as the current `master`. In practice, this package will often | |
| support older versions as well, as minimum version requirements are generally only updated | |
| when there is a specific need, such as using a new DevTools or Flutter feature. |