Skip to content

plugin:install

View raw .md

Register a third-party dowel plugin into the consumer project. After adding a package to pubspec.yaml and running flutter pub get, plugin:install wires the plugin's DowelServiceProvider without requiring manual edits to bin/dispatcher.dart or lib/app/_plugins.g.dart.

On this page

Basic Usage#

bash
dart run dowel plugin:install <name>

<name> is the plugin's pubspec package name (e.g. magic_logger). The package must be listed in pubspec.yaml and resolved via flutter pub get before this command runs.

Pre-flight checks: the package must appear in pubspec.yaml, and .dart_tool/package_config.json must contain the package name. Any failure exits with code 1 before any write is attempted. A plugin without an install.yaml also needs the scaffold from dart run dowel install (lib/app/_plugins.g.dart); without it the command exits with code 1 and tells you to run install first.


Synopsis#

Full signature as declared in lib/src/commands/plugin_install_command.dart:

text
plugin:install
  {name                  : Plugin pubspec package name (e.g. magic_logger)}
  {--bootstrap-command=  : Plugin install sub-command to chain after registration}
  {--use-yaml-only       : Fail if install.yaml not found instead of registering the plugin directly}
  {--force               : Bypass conflict detection (inherited from DowelInstallCommand)}
  {--dry-run             : Print staged ops without writing (inherited)}
  {--non-interactive     : Skip prompts, use defaults (inherited)}
  {--no-bootstrap        : Skip post-install bootstrap hint message (inherited)}

The four inherited flags come from DowelInstallCommand.baseFlags and are available on every install command, not only plugin:install.

Flag Effect
--bootstrap-command=cmd Overrides the post-registration bootstrap hint (e.g. logger:install).
--use-yaml-only Error out when no install.yaml found; no direct registration (Mode 2).
--force Bypass conflict detection; overwrite user-modified files.
--dry-run Print every staged op without touching disk.
--non-interactive Skip interactive prompts; use defaults. Required in non-TTY environments.
--no-bootstrap Suppress the post-install bootstrap hint message.

Two Routing Modes#

The core of handle dispatches through two code paths. Mode 1 wins when an install.yaml manifest is present; Mode 2 runs otherwise, and needs the scaffold barrel from dart run dowel install.

Mode 1: install.yaml Manifest Flow#

Condition: resolveInstallYaml(name) returns a non-null path. The resolver checks <plugin_root>/install.yaml first, then <plugin_root>/assets/install.yaml (resolveInstallYaml in lib/src/commands/plugin_install_command.dart).

ManifestParser.parseFile parses the YAML into an InstallManifest. ManifestInstaller stages InstallOperation objects on an InstallTransaction. InstallTransaction.commit writes every file to a .tmp path first; on full success, all .tmp files are renamed atomically. Any .tmp write failure deletes all staged temps and returns Error(rolledBack: true). On Success, the plugin entry is written to .dowel/plugins.json and PluginsRefreshCommand regenerates lib/app/_plugins.g.dart in-process.

Preferred authoring path: declarative, conflict-checked, dry-run-capable, and partially reversible via plugin:uninstall (V1 limitations; see Reversibility).

Mode 2: Direct Registration#

Condition: No install.yaml found AND lib/app/_plugins.g.dart exists at the project root. Without that barrel the command exits with code 1 and asks you to run dart run dowel install first.

_registerDowelProvider runs directly: writes a PluginEntry to .dowel/plugins.json and regenerates _plugins.g.dart. No wrapper edit occurs. Covers plugins without a manifest. Naming convention: my_plugin maps to package:my_plugin/cli.dart and class MyPluginDowelProvider. Pass --use-yaml-only to error out instead of reaching this path.


Examples#

1. Manifest-based plugin install (Mode 1)#

bash
flutter pub add magic_logger
dart run dowel plugin:install magic_logger

Output:

text
Success: applied 4 ops; record at .dowel/installed/magic_logger.json
Bootstrap with: dowel logger:install

2. Canonical scaffold, no install.yaml (Mode 2)#

bash
flutter pub add awesome_plugin
dart run dowel plugin:install awesome_plugin

Output:

text
Registered "awesome_plugin" via the dowel scaffold (no install.yaml needed).

3. Dry-run preview#

bash
dart run dowel plugin:install magic_logger --dry-run

Output:

text
DryRun: previewed 4 ops; no changes written
  WriteFile           lib/config/logger.dart
  InjectImport        lib/main.dart
  InjectAfterPattern  lib/app/providers/app_service_provider.dart
  AddPubspecAsset     assets/logging/

Idempotency#

Re-running plugin:install for the same plugin is safe in both modes. PluginsRegistryFile.addPlugin replaces by name so .dowel/plugins.json always contains exactly one entry per plugin. ConfigEditor.addImportToFile and insertCodeAfterPattern skip injection when the target content is already present.

All InstallTransaction file writes use .tmp + atomic rename: concurrent readers never observe partial state. A mid-commit .tmp write failure deletes all staged temps and returns Error(rolledBack: true) before any rename occurs.


Reversibility#

plugin:uninstall <name> is the complement to plugin:install. A Mode 1 manifest commit writes .dowel/installed/<name>.json listing every op and content hash. V1 reversibility is partial: WriteFile ops are fully reversed (tamper-check then delete); InjectImport, InjectBeforePattern, and InjectAfterPattern ops are logged as [skipped] (no anchor-bracketed markers in V1; operator must reverse by hand). Mode 2 installs write no record, so plugin:uninstall cannot auto-reverse them. Full bidirectional reversibility is planned for V1.1.


  • plugin:uninstall: removes a plugin registered via plugin:install, using the .dowel/installed/<name>.json record.
  • plugins:refresh: regenerates lib/app/_plugins.g.dart from .dowel/plugins.json when the codegen barrel drifts out of sync.
  • install.yaml schema: full reference for the declarative manifest format consumed by Mode 1.
esc

Search index did not load.

No match for "".

Try a class like rounded-lg or a widget like WButton.