A plugin can be a simple implementation of [triggers](/docs/development/plugin-triggers.md) or can implement a command structure of its own. Dokku has no restrictions on the language in which a plugin is implemented; it only cares that the plugin implements the appropriate [commands](/docs/development/plugin-creation.md#command-api) or [triggers](/docs/development/plugin-triggers.md) for the API. **NOTE:** any file that implements triggers or uses the command API must be executable.
When developing a plugin, the `install` trigger must be implemented such that it outputs the built executable(s) using a directory structure that implements the plugin's desired command and/or triggers the API. See the [smoke-test-plugin](https://github.com/dokku/smoke-test-plugin) for an example.
Implements the additional command interface and will translate to `dokku plugin:cmd` on the command line. (i.e. [`dokku plugin:install`](https://github.com/dokku/dokku/tree/master/plugins/plugin/subcommands/install)).
The `plugin.toml` file is used to describe the plugin in help output, and helps users understand the purpose of the plugin. This _must_ have a description and a version. The version _should_ be bumped at every plugin release.
Commands, subcommands, triggers and source shell scripts should all be executable. On a Unix-like machine, the following command can be used to make them executable:
```shell
chmod +x path/to/file
```
Non-executable commands, subcommands, and triggers will be ignored.
dokku_log_fail "user/repo image not found... Did you run 'dokku plugin:install'?"
fi
```
If `user/repo` doesn't exist, Dokku exits just before the `awk` command and the `dokku_log_fail` message will never go to `STDOUT`. printed with echo. The `set -e` option should be used in this case.
Here is the `help` entry for `set`:
```
help set
Options:
-e Exit immediately if a command exits with a non-zero status.
-o option-name
pipefail the return value of a pipeline is the status of
the last command to exit with a non-zero status,
or zero if no command exited with a non-zero status
Trace mode is useful for getting debugging output from plugins when the `--trace` flag is specified or `dokku trace:on` is triggered. This should be done at the top of each shell script:
```shell
#!/usr/bin/env bash
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
```
In the above example, the third line enables bash's debug mode, which prints command traces before executing command.
## Verify the existence of dependencies
If a plugin depends on a specific command-line tool, check whether that tool exists before utilizing it. Either `command -v` or `which` may be used to do so:
For plugins which expose commands, implement a `help` command. This may be empty, but should contain a listing of all available commands.
Commas - `,` - are used in the help output for columnizing output. Verify that the plugin conforms to the spec by running `dokku help --all` and manually verifying the output.
All commands _should_ be namespaced. In cases where a core plugin is overridden, the plugin _may_ utilize the a namespace in use by the core, but generally this should be avoided to reduce confusion as to where the command is implemented.
As of 0.3.3, a catch-all should be implemented that exits with a `DOKKU_NOT_IMPLEMENTED_EXIT` code. This allows Dokku to output a `command not found` message.
In the case that a plugin needs to set app configuration settings and a restart should be avoided (default Heroku-style behavior) these "internal" commands provide this functionality:
To allow other plugins access to (some of) a plugin's functionality, functions can expose by including a `functions` file in the plugin for others to source. All functions in that file should be considered publicly accessible by other plugins.
Any functions that must be kept private should reside in the plugin's `trigger/` or `commands/` directories. Other files may also be used to hide private functions; the official convention for hiding private functions is to place them an `internal-functions` file.
Dokku allows image tagging and deployment of tagged images. This means hard-coding the `$IMAGE` as `dokku/$APP` is no longer sufficient.
Plugins should use `get_running_image_tag()` and `get_app_image_name()` as sourced from `common/functions`. See the [plugin triggers](/docs/development/plugin-triggers.md) doc for examples.
> **Note:** This is only for plugins that are not `pre/post-build-*` plugins
Certain systems may require a wrapper function around the `docker` binary for proper execution. Utilizing the `$DOCKER_BIN` environment variable when calling docker for those functions is preferred.
As of 0.5.0, labels are used to help cleanup intermediate containers with `dokku cleanup`. Plugins that create containers and images should add the correct labels to the `build`, `commit`, and `run` docker commands.
Note that where possible, a label `com.dokku.app-name=$APP` - where `$APP` is the name of the app - should also be included. This enables `dokku cleanup APP` to cleanup the specific containers for a given app.
Avoid copying files from running containers as these files may change over time. Instead copy files from the image built during the deploy process. This can be done via the `copy_from_image` helper function. This will correctly handle various corner cases in copying files from an image.
Plugins should **not** call the `dokku` binary directly from within plugins because clients using the `--app` argument are potentially broken when doing so.
Plugins should instead source the `functions` file for a given plugin when attempting to call Dokku internal functions. In cases where plugin functions cannot be sourced (eg if a plugin is implemented in Golang), then call the relevant [plugin triggers](/docs/development/plugin-triggers.md) instead.