Calling a Tool from Drush
When to Use
Use this to find, inspect or run Tool API tools from the command line, or to let a local agent drive them. Tool API ships four Drush commands;
tool:runruns as anonymous unless you pass--uid.Version: applies to
drupal/tool1.0.0-beta11 (beta; no security advisory coverage). Paths are undermodules/contrib/tool/.
Commands
| Command | Aliases | Arguments and options (from the #[Command] attributes) |
|---|---|---|
tool:list |
tools, tlist |
--format=table\|markdown\|json (default table), --operation=explain\|read\|transform\|trigger\|write, --unmet=show\|hide\|only (default show) |
tool:search |
tsearch |
keywords (space-separated), --match=or\|and (default or), --format, --operation, --unmet |
tool:info |
tinfo |
tool_id, --format=table\|markdown\|json |
tool:run |
trun |
tool_id, --input (repeatable; JSON object or key=value), --json, --uid |
(tool 1.0.0-beta11 src/Drush/Commands/)
drush tool:list --operation=read --format=json
drush tool:search "entity save" --match=and
drush tool:info tool_belt:entity_list --format=json
drush tool:run tool_belt:entity_list --uid=2 --input='{"entity_type_id":"node"}' --json
These lines follow the declared options and inputs; they were not executed when this page was written.
What Each Returns
tool:list/tool:searchJSON: a list of{id, label, description, operation, destructive, provider, requirements: {met, message}}. Search matches substrings of the lowercase ID, label and description. Neither filters by the caller's permissions.tool:infoJSON: the summary pluspermission,inputs(type, label, description, required, multiple, locked),outputs,input_schema(full JSON Schema, locked inputs included) andoutput_schema. Table output adds a constraints column, a warning for unknown permission names, and a usage example. Unknown tool: exit 1. Unmet requirements: still exit 0.tool:run --jsonsuccess or tool failure:{"success": bool, "message": "...", "outputs": {...}}.outputsis whatevergetFormattedResult()carries, on failure too. Entities print as{entity_type, id, uuid, label}only.tool:run --jsoncommand error:{"success": false, "error": "...", "error_type": "..."}witherror_typeone oftool_not_found,invalid_option,user_not_found,user_blocked,invalid_input,access_denied,execution_failed(tool 1.0.0-beta11src/Drush/RunErrorType.php). Exit code 1 on any failure.
tool:run Sequence
From ToolRunCommand::runTool() and executeTool():
- Tool exists, options parse (
--uidmust be a non-negative integer). - Load the user. No
--uidor--uid=0meansAnonymousUserSession. Missing or blocked users stop here. - Switch to that account.
ToolManager::checkPermission()on the definition, before creating the tool.- Create the tool with the
drushinvoker (the caller identity; see Calling a Tool from PHP). It has no capabilities. setInputValue()for each--inputname. An undeclared name throws and reportsinvalid_input.validateInputs(), thenaccess(), thenexecute().- Print
getFormattedResult()values.
Common Mistakes
- Running write tools without
--uid→ access denied; the message adds "Ran as anonymous (uid 0); pass --uid=to run as a user." - Using
--uid=1by habit → superuser bypasses permission checks; use a role-scoped account to test the real rule - Passing an entity input from Drush → the
drushinvoker cannot supply entities; see Entity Inputs and Handles - Treating
tool:listas "tools this account can run" → it lists every tool; checkpermissionintool:info - Parsing table output in scripts → use
--format=jsonand--json; branch onerror_type
See Also
- Access Control → why
--uidmatters - checkRequirements → the
Requirementscolumn - Reference:
modules/contrib/tool/src/Drush/Commands/ToolRunCommand.php,modules/contrib/tool/src/Drush/Commands/ToolInfoCommand.php,modules/contrib/tool/src/Drush/Commands/ToolOutputTrait.php,modules/contrib/tool/docs/usage/drush.md