Skip to content

Scaffolding with drush generate

When to Use

Use this to start a new Tool API plugin. The generator writes the plugin and two tests, and its access check fails closed until you define one.

Version: applies to drupal/tool 1.0.0-beta11 (beta; no security advisory coverage). Paths are under modules/contrib/tool/.

Steps

  1. Run the generator. Name plugin:tool, alias tool (tool 1.0.0-beta11 src/Drush/Generators/ToolGenerator.php).
drush generate plugin:tool
  1. Answer the prompts. Module machine name, tool label, plugin ID, class (suffix Tool), description (required, no default), operation (default Read), and "Is the tool destructive (irreversible write/trigger)?" (default no).

  2. Review the three files it writes.

File Content
src/Plugin/tool/Tool/{class}.php #[Tool] with one example string input and one result MapOutputDefinition
tests/src/Unit/Tool/{class}AccessTest.php Unit access test
tests/src/Kernel/Tool/{class}Test.php Kernel test
  1. Define access. The generated checkAccess() throws \LogicException ("Access control for %s has not been defined.") until you declare a permission and delete the override, or implement it. See Access Control for what that exception does to callers.

  2. Replace the example input and output. The template comment says keys not in output_definitions "are dropped"; they are not typed outputs, but they still reach callers raw. See Output Definitions.

  3. Fix the generated catch (\Exception $e), which returns $e->getMessage() to callers. See doExecute and ExecutableResult.

  4. Rebuild and inspect.

drush cr
drush tool:info my_module_my_tool --format=json

Decision Points

At this step... If... Then...
Access The rule depends only on the account Add permission: and delete the checkAccess() override
Access The rule depends on input values Implement checkAccess()
Operation The tool stores data Pick Write, not the default Read

Common Mistakes

  • Keeping the generic description → it is what agents read; the generator refuses a default for that reason
  • Deleting the generated tests → they are the cheapest place to pin the access rule
  • Leaving the default Read operation on a tool that writes → see Operation and Destructive

See Also

  • Defining a Tool → the attribute in full
  • Access Control → choosing permission vs checkAccess()
  • Reference: modules/contrib/tool/src/Drush/Generators/