Skip to content

Commands

View raw .md

Catalogue of every user-facing command shipped by dowel. Twenty-two commands, grouped by intent.

On this page

Every command is invoked as dart run dowel <name>, or as ./bin/dowel <name> once the project has run install (the fast wrapper). Commands are auto-discovered through the registered providers list; nothing wires by hand.

Need a quick reminder of what a command does without leaving the terminal? Run dart run dowel list for the full registry grouped by namespace, or dart run dowel help <name> for the per-command flag surface. This page exists for the deeper view: the boot mode, the MCP exposure, and the grouping rationale.

How to read this page#

Each group section ships a single table with four columns:

  • Command is the canonical name you type after dart run dowel (or ./bin/dowel).
  • Description is a one-line summary of the command, drawn from the description getter that dart run dowel list prints (reworded here where the getter's wording has fallen behind the behaviour, for example the ~/.dowel/state.json path it still names for start and stop).
  • Boot Mode is the CommandBoot value the dispatcher reads before invoking handle() (see lib/src/console/command_boot.dart). none means pure CLI: no Flutter binding, no VM Service connection. connected means the command dials this project's session and fails fast if no app is running.
  • MCP Tool is the canonical dowel_* tool name surfaced over stdio JSON-RPC by mcp:serve, or the literal no when the command is not in the substrate allowlist. The allowlist lives in lib/src/mcp/mcp_server.dart (_safeDowelCommandNames, ten commands) and intentionally omits help, codegen, installer, and MCP-meta commands.

Naming conventions#

Two shapes appear in the catalogue:

  • Single word (start, stop, status, logs, restart, reload, hot-restart, doctor, tinker, help, list, install) for top-level actions on the substrate.
  • Namespaced <group>:<verb> (make:plugin, make:command, make:fast-cli, plugin:install, plugin:uninstall, plugins:refresh, mcp:serve, mcp:install, mcp:uninstall, commands:refresh) for actions scoped to a subsystem.

hot-restart is a single word that happens to contain a hyphen: it lives in the lifecycle group and is not namespaced, so list prints it among the commands without a heading. It sends the R keypress to flutter run.

Lifecycle#

Seven commands that own the running Flutter process: spawn, stop, query, tail, restart, reload, hot-restart. All run pure CLI; none of them boot Flutter or Magic in the dowel process. State lives in a per-project session directory under ~/.dowel/sessions/, written by start and consumed by everything that needs the VM Service URI. ~/.dowel/state.json remains a pointer to whichever session started last. Any command that acts on the recorded app refuses when the session belongs to another project, so a stop from the wrong checkout cannot kill a sibling's run.

All seven are also surfaced as MCP tools. Together with list, doctor and tinker from the Introspection group they make up the ten MCP tools, the agent-facing surface area of the substrate.

Command Description Boot Mode MCP Tool
start Boot flutter run -d <device> detached and record the VM Service URI to this project's session. none dowel_start
stop Stop the running flutter app's whole process group, wait until it and its web port are gone, and delete this project's session. none dowel_stop
status Print JSON status of the recorded flutter app. none dowel_status
logs Print or --follow the captured flutter run log. none dowel_logs
restart Stop and start the running flutter app; carries the prior session's device, web port, VM Service port, CDP port, --flutter-arg values and profile build mode across. none dowel_restart
reload Hot reload the running app (sends r to flutter run's stdin). State preserved. none dowel_reload
hot-restart Hot restart the running app (sends R to flutter run's stdin). Drops Dart state, keeps process. none dowel_hot_restart

Scaffolding#

Four commands that write source files into the consumer project. They are deliberately excluded from the MCP allowlist: source mutation is better routed through the client's own file tools, and the stub system uses placeholder substitution ({{ name }}, {{ pascalName }}, {{ commandPrefix }}) that benefits from interactive prompts.

Command Description Boot Mode MCP Tool
make:plugin Scaffold a new dowel plugin skeleton. none no
make:command Scaffold a new DowelCommand subclass under lib/app/commands/ (or lib/src/commands/ when run inside a plugin). none no
make:fast-cli Scaffold the POSIX bin/dowel wrapper and pre-compile the AOT cache under .dowel/cli-bundle/ for about 100 ms startup. none no
install Scaffold the canonical native Flutter consumer wrapper (bin/dispatcher.dart plus lib/app/_plugins.g.dart plus lib/app/commands/_index.g.dart) and chain make:fast-cli in-process. none no

Plugin management#

Three commands that maintain the .dowel/plugins.json registry and its generated barrel lib/app/_plugins.g.dart. Atomic writes (.tmp plus rename) across every mutation, so concurrent readers (editors, lint daemons) never observe partial state. plugin:install routes through two modes (manifest, direct registration) depending on whether the plugin ships an install.yaml.

Command Description Boot Mode MCP Tool
plugin:install Register a third-party dowel plugin (install.yaml manifest preferred; direct registration into the dowel scaffold otherwise). none no
plugin:uninstall Uninstall a third-party dowel plugin (reverses the install manifest). none no
plugins:refresh Regenerate lib/app/_plugins.g.dart from .dowel/plugins.json registry. none no

MCP#

Three commands: mcp:serve runs the dowel MCP server, and mcp:install and mcp:uninstall wire it into a host like Claude Code, Cursor, or Windsurf. The mcp:* meta commands recurse into the server and are intentionally excluded from the allowlist. Per-tool visibility is configured via .dowel/mcp.json, environment variables, and CLI flags (the three layers compose Cargo-style: file plus env plus flags, with deny rules always winning).

Command Description Boot Mode MCP Tool
mcp:serve Run the dowel MCP server (stdio JSON-RPC) for Claude Code, Cursor, Windsurf. none no
mcp:install Add the dowel MCP server entry to .mcp.json (idempotent; preserves other server entries). none no
mcp:uninstall Remove the dowel MCP server entry from .mcp.json (preserves other entries). none no

Introspection#

Four commands that observe the substrate or its host. tinker is the only command in the catalogue with CommandBoot.connected: it dials the running app's VM Service. It is still exposed as dowel_tinker (its --eval one-shot path drives the MCP tool); help is the one command here outside the MCP allowlist.

Command Description Boot Mode MCP Tool
help Show detailed help for a single command. none no
list List every registered command grouped by namespace. none dowel_list
doctor Run environment preflight checks (flutter, dart, port availability). none dowel_doctor
tinker Connected REPL into the running Flutter app (Dart expression evaluation via VM Service). connected dowel_tinker

Code generation#

One command that rewrites the lib/app/commands/_index.g.dart barrel. Codegen sits in its own bucket because the consumer rarely runs it by hand: make:command and plugin:install invoke it as a follow-up step. The generated barrel is never edited manually; the source of truth is the set of *_command.dart files under lib/app/commands/.

Command Description Boot Mode MCP Tool
commands:refresh Rescan lib/app/commands/ and rewrite the auto-discovery index. none no

Boot mode at a glance#

Twenty-one of the twenty-two commands run with CommandBoot.none. Only tinker is CommandBoot.connected, because its job is to evaluate Dart expressions against a live VM Service isolate. Everything else (lifecycle commands included) shells out to flutter run or operates on disk; the dowel process itself never depends on a Flutter binding.

This separation is what lets the substrate ship as a pure-Dart package: the consumer wrapper supplies the optional Magic / Flutter context, while the framework itself stays runtime-free.

A third boot mode, headless, is reserved for a V1.x release that will let Magic-bound commands (think migrate, db:seed) boot just enough of the host to read Magic.Config without spinning up a UI.

Seven commands earn their own pages because their flags, modes, or composition rules outgrow a single table row:

Slug rule: the deep-dive URL drops the : separator in favour of -, so plugin:install lives at commands/plugin-install/, mcp:serve at commands/mcp-serve/ and make:fast-cli at commands/make-fast-cli/. The remaining fifteen commands share this index page; reach for dart run dowel help <name> for their full flag surface.

esc

Search index did not load.

No match for "".

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