github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/docs/content/users/extend/custom-commands.md (about)

     1  ---
     2  search:
     3    boost: 2
     4  ---
     5  # Custom Commands
     6  
     7  Custom commands can easily be added to DDEV, to be executed on the host or in containers.
     8  
     9  This involves adding a Bash script to the project in `.ddev/commands/host`, a specific container in `.ddev/commands/<containername>`, or globally in `~/.ddev/commands`.
    10  
    11  Example commands in `ddev/commands/*/*.example` can be copied, moved, or symlinked.
    12  
    13  For example, [.ddev/commands/host/mysqlworkbench.example](https://github.com/ddev/ddev/blob/master/pkg/ddevapp/global_dotddev_assets/commands/host/mysqlworkbench.example) can be used to add a `ddev mysqlworkbench` command. Rename it from `mysqlworkbench.example` to `mysqlworkbench`. If you’re on macOS or Linux (or some configurations of Windows) you can `cd .ddev/commands/host && ln -s mysqlworkbench.example mysqlworkbench`.
    14  
    15  The [`ddev mysql`](../usage/commands.md#mysql) runs the `mysql` client inside the `db` container command using this technique. See the [`ddev mysql` command](https://github.com/ddev/ddev/blob/master/pkg/ddevapp/global_dotddev_assets/commands/db/mysql).
    16  
    17  ## Notes for All Command Types
    18  
    19  * The command filename is not what determines the name of the command. That comes from the “Usage” doc line (`## Usage: commandname`).
    20  * To confirm that your custom command is available, run `ddev -h` and look for it in the list.
    21  
    22  ## Host Commands
    23  
    24  To provide host commands, place a Bash script in `.ddev/commands/host`. For example, a PhpStorm launcher to make the `ddev phpstorm` command might go in `.ddev/commands/host/phpstorm` with these contents. The `OSTypes` and `HostBinaryExists` annotations are optional, but are useful to prevent the command from showing up if it's not useful to the user.
    25  
    26  ```bash
    27  #!/usr/bin/env bash
    28  
    29  ## Description: Open PhpStorm with the current project
    30  ## Usage: phpstorm
    31  ## Example: "ddev phpstorm"
    32  ## OSTypes: darwin
    33  ## HostBinaryExists: "/Applications/PhpStorm.app"
    34  
    35  # Example is macOS-specific, but easy to adapt to any OS
    36  open -a PhpStorm.app ${DDEV_APPROOT}
    37  ```
    38  
    39  ## Container Commands
    40  
    41  To provide a command which will execute in a container, add a Bash script to `.ddev/commands/<container_name>`, for example, `.ddev/commands/web/mycommand`. The Bash script will be executed inside the named container. For example, see the [several standard DDEV script-based web container commands](https://github.com/ddev/ddev/blob/master/pkg/ddevapp/global_dotddev_assets/commands/web).
    42  
    43  You can run commands in custom containers as well as standard DDEV `web` and `db` containers. Use the service name, like `.ddev/commands/solr/<command>`. The only catch with a custom container is that your service must mount `/mnt/ddev-global-cache` like the `web` and `db` containers do; the `volumes` section of `docker-compose.<servicename>.yaml` needs:
    44  
    45  ```
    46      volumes:
    47        - ddev-global-cache:/mnt/ddev-global-cache
    48  ```
    49  
    50  For example, to add a `solrtail` command that runs in a Solr service, add `.ddev/commands/solr/solrtail` with:
    51  
    52  ```bash
    53  #!/bin/bash
    54  
    55  ## Description: Tail the main solr log
    56  ## Usage: solrtail
    57  ## Example: ddev solrtail
    58  
    59  tail -f /opt/solr/server/logs/solr.log
    60  ```
    61  
    62  ## Global Commands
    63  
    64  Global commands work exactly the same as project-level commands, but they need to go in your *global* `.ddev` directory. Your home directory has a `.ddev/commands` in it, where you can add host, web, or db commands.
    65  
    66  Changes to the command files in the global `.ddev` directory need a `ddev start` for changes to be picked up by a project, as the global commands are copied to the project on start.
    67  
    68  ## Shell Command Examples
    69  
    70  There are many examples of [global](https://github.com/ddev/ddev/tree/master/pkg/ddevapp/global_dotddev_assets/commands) and [project-level](https://github.com/ddev/ddev/tree/master/pkg/ddevapp/dotddev_assets/commands) custom/shell commands that ship with DDEV you can adapt for your own use. They can be found in your `~/.ddev/commands/*` directories and in your project’s `.ddev/commands/*` directories. There you’ll see how to provide usage, examples, and how to use arguments provided to the commands. For example, the [`xdebug` command](https://github.com/ddev/ddev/blob/master/pkg/ddevapp/global_dotddev_assets/commands/web/xdebug) shows simple argument processing and the [launch command](https://github.com/ddev/ddev/blob/master/pkg/ddevapp/global_dotddev_assets/commands/host/launch) demonstrates flag processing.
    71  
    72  ## Command Line Completion
    73  
    74  If your custom command has a set of pre-determined valid arguments it can accept, you can use the [`AutocompleteTerms`](#autocompleteterms-annotation).
    75  
    76  For dynamic completion, you can create a separate script with the same name in a directory named `autocomplete`.
    77  For example, if your command is in `~/.ddev/commands/web/my-command`, your autocompletion script will be in `~/.ddev/commands/web/autocomplete/my-command`.
    78  
    79  When you press tab on the command line after your command, the associated autocomplete script will be executed. The current command line (starting with the name of your command) will be passed into the completion script as arguments. If there is a space at the end of the command line, an empty argument will be included.
    80  
    81  For example:
    82  
    83  * `ddev my-command <tab>` will pass `my-command` and an empty argument into the autocomplete script.
    84  * `ddev my-command som<tab>` will pass `my-command`, and `som` into the autocomplete script.
    85  
    86  The autocomplete script should echo the valid arguments as a string separated by line breaks. You don't need to filter the arguments by the last argument string (e.g. if the last argument is `som`, you don't need to filter out any arguments that don't start with `som`). That will be handled for you before the result is given to your shell as completion suggestions.
    87  
    88  The web container's [`nvm` autocomplete script](https://github.com/ddev/ddev/blob/master/pkg/ddevapp/global_dotddev_assets/commands/web/autocomplete/nvm) shows how this can be used to forward completion requests to a relevant script in the container.
    89  
    90  ## Environment Variables Provided
    91  
    92  A number of environment variables are provided to these command scripts. These are generally supported, but please avoid using undocumented environment variables. Useful variables for host scripts are:
    93  
    94  * `DDEV_APPROOT`: File system location of the project on the host
    95  * `DDEV_DATABASE`: Database in use, in format `type:version` (example: `mariadb:10.5`)
    96  * `DDEV_DATABASE_FAMILY`: Database "family" (example: `mysql`, `postgres`), useful for database connection URLs
    97  * `DDEV_DOCROOT`: Relative path from approot to docroot
    98  * `DDEV_GID`: The GID the web container runs as
    99  * `DDEV_HOSTNAME`: Comma-separated list of FQDN hostnames
   100  * `DDEV_HOST_DB_PORT`: Localhost port of the database server
   101  * `DDEV_HOST_HTTPS_PORT`: Localhost port for HTTPS on web server
   102  * `DDEV_HOST_MAILPIT_PORT`: Localhost port for Mailpit
   103  * `DDEV_HOST_WEBSERVER_PORT`: Localhost port of the web server
   104  * `DDEV_MAILPIT_HTTP_PORT`: Router Mailpit port for HTTP
   105  * `DDEV_MAILPIT_HTTPS_PORT`: Router Mailpit port for HTTPS
   106  * `DDEV_MUTAGEN_ENABLED`: `true` if Mutagen is enabled
   107  * `DDEV_PHP_VERSION`: Current PHP version
   108  * `DDEV_PRIMARY_URL`: Primary project URL
   109  * `DDEV_PROJECT`: Project name, like `d8composer`
   110  * `DDEV_PROJECT_STATUS`: Project status determined from the `web` and `db` services health, like `starting`, `running`, `stopped`, `paused`, or another status returned from Docker, including `healthy`, `unhealthy`, `exited`, `restarting`
   111  * `DDEV_PROJECT_TYPE`: `backdrop`, `drupal`, `typo3`,`wordpress`, etc.
   112  * `DDEV_ROUTER_HTTP_PORT`: Router port for HTTP
   113  * `DDEV_ROUTER_HTTPS_PORT`: Router port for HTTPS
   114  * `DDEV_SITENAME`: Project name, like `d8composer`
   115  * `DDEV_TLD`: Top-level project domain, like `ddev.site`
   116  * `DDEV_UID`: The UID the web container runs as
   117  * `DDEV_WEBSERVER_TYPE`: `nginx-fpm`, `apache-fpm`, or `nginx-gunicorn`
   118  * `GOARCH`: Architecture (`arm64`, `amd64`)
   119  * `GOOS`: Operating system (`windows`, `darwin`, `linux`)
   120  
   121  Useful variables for container scripts are:
   122  
   123  * `DDEV_DOCROOT`: Relative path from approot to docroot
   124  * `DDEV_FILES_DIR`: *Deprecated*, first directory of user-uploaded files
   125  * `DDEV_FILES_DIRS`: Comma-separated list of directories of user-uploaded files
   126  * `DDEV_HOSTNAME`: Comma-separated list of FQDN hostnames
   127  * `DDEV_MUTAGEN_ENABLED`: `true` if Mutagen is enabled
   128  * `DDEV_PHP_VERSION`: Current PHP version
   129  * `DDEV_PRIMARY_URL`: Primary URL for the project
   130  * `DDEV_PROJECT`: Project name, like `d8composer`
   131  * `DDEV_PROJECT_TYPE`: `backdrop`, `drupal`, `typo3`,`wordpress`, etc.
   132  * `DDEV_ROUTER_HTTP_PORT`: Router port for HTTP
   133  * `DDEV_ROUTER_HTTPS_PORT`: Router port for HTTPS
   134  * `DDEV_SITENAME`: Project name, like `d8composer`
   135  * `DDEV_TLD`: Top-level project domain, like `ddev.site`
   136  * `DDEV_WEBSERVER_TYPE`: `nginx-fpm`, `apache-fpm`, or `nginx-gunicorn`
   137  * `IS_DDEV_PROJECT`: If `true`, PHP is running under DDEV
   138  
   139  ## Annotations Supported
   140  
   141  Custom commands support various annotations in the header for providing additional information to the user.
   142  
   143  ### `Description` Annotation
   144  
   145  `Description` should briefly describe the command in its help message.
   146  
   147  Usage: `## Description: <command-description>`
   148  
   149  Example: `## Description: my great custom command`
   150  
   151  ### `Usage` Annotation
   152  
   153  `Usage` should explain how to use the command in its help message.
   154  
   155  Usage: `## Usage: <command-usage>`
   156  
   157  Example: `## Usage: commandname [flags] [args]`
   158  
   159  ### `Example` Annotation
   160  
   161  `Example` should demonstrate how the command might be used. Use `\n` to force a line break.
   162  
   163  Usage: `## Example: <command-example>`
   164  
   165  Example: `## Example: commandname\ncommandname -h`
   166  
   167  ### `Flags` Annotation
   168  
   169  `Flags` should explain any available flags, including their shorthand when relevant, for the help message. It has to be encoded according the following definition:
   170  
   171  If no flags are specified, the command will have its flags parsing disabled. Global flags like `--help` will not work unless the command supports them.
   172  
   173  You can still do `ddev help <command>` to see the command's provided usage help.
   174  
   175  Usage: `## Flags: <json-definition>`
   176  
   177  This is the minimal usage of a flags definition:
   178  
   179  Example: `## Flags: [{"Name":"flag","Usage":"sets the flag option"}]`
   180  
   181  Output:
   182  
   183  ```bash
   184  Flags:
   185    -h, --help          help for ddev
   186    -f, --flag          sets the flag option
   187  ```
   188  
   189  Multiple flags are separated by a comma:
   190  
   191  Example: `## Flags: [{"Name":"flag1","Shorthand":"f","Usage":"flag1 usage"},{"Name":"flag2","Usage":"flag2 usage"}]`
   192  
   193  Output:
   194  
   195  ```bash
   196  Flags:
   197    -h, --help          help for ddev
   198    -f, --flag1         flag1 usage
   199        --flag2         flag2 usage
   200  ```
   201  
   202  The following fields can be used for a flag definition:
   203  
   204  * `Name`: the name as it appears on command line
   205  * `Shorthand`: one-letter abbreviated flag
   206  * `Usage`: help message
   207  * `Type`: possible values are `bool`, `string`, `int`, `uint` (defaults to `bool`)
   208  * `DefValue`: default value for usage message
   209  * `NoOptDefVal`: default value, if the flag is on the command line without any options
   210  * `Annotations`: used by cobra.Command Bash autocomplete code (see <https://github.com/spf13/cobra/blob/main/site/content/completions/bash.md>)
   211  
   212  ### `AutocompleteTerms` Annotation
   213  
   214  If your command accepts specific arguments, and you know ahead of time what those arguments are, you can use this annotation to provide those arguments for autocompletion.
   215  
   216  Usage: `## AutocompleteTerms: [<list-of-valid-arguments>]`
   217  
   218  Example: `## AutocompleteTerms: ["enable","disable","toggle","status"]`
   219  
   220  ### `CanRunGlobally` Annotation
   221  
   222  This annotation is only available for global host commands.
   223  
   224  Use `CanRunGlobally: true` if your global host command can be safely run even if the current working directory isn't inside a DDEV project.
   225  
   226  This will make your command available to run regardless of what your current working directory is when you run it.
   227  
   228  This annotation will have no effect if you are also using one of the following annotations:
   229  
   230  * `ProjectTypes`
   231  * `DBTypes`
   232  
   233  Example: `## CanRunGlobally: true`
   234  
   235  ### `ProjectTypes` Annotation
   236  
   237  If your command should only be visible for a specific project type, `ProjectTypes` will allow you to define the supported types. This is especially useful for global custom commands. See [Quickstart for many CMSes](../../users/quickstart.md) for more information about the supported project types. Multiple types are separated by a comma.
   238  
   239  Usage: `## ProjectTypes: <list-of-project-types>`
   240  
   241  Example: `## ProjectTypes: drupal7,drupal,backdrop`
   242  
   243  ### `OSTypes` Annotation (Host Commands Only)
   244  
   245  If your host command should only run on one or more operating systems, add the `OSTypes` annotation. Multiple types are separated by a comma. Valid types are:
   246  
   247  * `darwin` for macOS
   248  * `windows` for Windows
   249  * `linux` for Linux
   250  
   251  Usage: `## OSTypes: <list-of-os-types>`
   252  
   253  Example: `## OSTypes: darwin,linux`
   254  
   255  ### `HostBinaryExists` Annotation (Host Commands Only)
   256  
   257  If your host command should only run if a particular file exists, add the `HostBinaryExists` annotation.
   258  
   259  Usage: `## HostBinaryExists: <path/to/file>`
   260  
   261  Example: `## HostBinaryExists: /Applications/Sequel ace.app`
   262  
   263  ### `DBTypes` Annotation
   264  
   265  If your command should only be available for a particular database type, add the `DBTypes` annotation. Multiple types are separated by a comma. Valid types the available database types.
   266  
   267  Usage: `## DBTypes: <type>`
   268  
   269  Example: `## DBTypes: postgres`
   270  
   271  ### `HostWorkingDir` Annotation (Container Commands Only)
   272  
   273  If your container command should run from the directory you are running the command in the host, add the `HostWorkingDir` annotation.
   274  
   275  Example: `## HostWorkingDir: true`
   276  
   277  ### `ExecRaw` Annotation (Container Commands Only)
   278  
   279  Use `ExecRaw: true` to pass command arguments directly to the container as-is.
   280  
   281  For example, when `ExecRaw` is true, `ddev yarn --help` returns the help for `yarn`, not DDEV's help for the `ddev yarn` command.
   282  
   283  We recommend  using this annotation for all container commands. The default behavior is retained to avoid breaking existing commands.
   284  
   285  Example: `## ExecRaw: true`
   286  
   287  ## Known Windows Issues
   288  
   289  ### Line Endings
   290  
   291  If you’re editing a custom command to be run in a container, it must have LF line endings and not traditional Windows CRLF line endings. Remember that a custom command in a container is a script that must execute in a Linux environment.
   292  
   293  ### Bash
   294  
   295  Commands can’t be executed if DDEV can’t find `bash`. If you’re running inside Git Bash in most any terminal, this shouldn’t be an issue, and DDEV should be able to find `git-bash` if it’s in `C:\Program Files\Git\bin` as well. But if neither of those is true, add the directory of `bash.exe` to your `PATH` environment variable.