export const meta = {
  title: `Authoring a new plugin`,
  description: `Plugins enable you to add additional commands and functionality to existing Amplify CLI. Learn how to create, publish, consume a plugin package.`,
};

  

The Amplify CLI provides the command `amplify plugin init` (with alias `amplify plugin new`) for the development of plugins. This command first collects requirements, and then creates the skeleton of the plugin package for you to start the development. The newly created plugin is added to your local Amplify CLI plugin platform, so you can conveniently test its functionalities while it is being developed. It can be easily removed from the local plugin platform with the `amplify plugin remove` command, and added back with the `amplify plugin add` command.

### Step 1: Install Amplify CLI

import all0 from "/src/fragments/cli-install-block.mdx";

<Fragments fragments={{all: all0}} />

### Step 2: Initialize plugin

```bash
amplify plugin init
```

You will be prompted to enter the plugin name, then select the plugin type, and event subscriptions. The CLI will then create a plugin package for you and add it to the local Amplify CLI plugin platform.

### Step 3: Test your plugin

The newly created plugin package is already added to the local Amplify CLI, so you can start testing it immediately.
Let's say you have chosen to use the default plugin name: `my-amplify-plugin`

```console
$ amplify my-amplify-plugin help
help command to be implemented.
```

You will see that the default help message is printed out.
At this point, there are only two sub commands in the plugin package, `help` and `version`, with dummy implementations. If you try to execute any other command, it will trigger the Amplify CLI plugin platform to perform a fresh scan, and then after it failed to find the command, it will print out the default help message.

From here, you can start to develop the plugin package. See below for the detailed explanation of the package structure.

### Step 4: Publish to NPM

After the completion of one development cycle and you are ready to release your plugin to the public, you can publish it to the NPM: [https://docs.npmjs.com/getting-started/publishing-npm-packages](https://docs.npmjs.com/getting-started/publishing-npm-packages)

### Step 5: Install and Use

Once your plugin is published to the NPM, other developers can install and use it

```bash
npm install -g my-amplify-plugin
amplify plugin add my-amplify-plugin
amplify my-amplify-plugin help
```

## Plugin Package Structure

Here's the plugin package directory structure

```md
|_my-amplify-plugin/
  |_commands/
  |   |_ help.js
  |   |_ version.js
  |
  |_event-handlers
  |   |_handle-PostInit.js
  |   |_handle-PostPush.js
  |   |_handle-PreInit.js
  |   |_handle-PrePush.js
  |
  |_amplify-plugin.json
  |_index.js
  |_package.json
```

### amplify-plugin.json

The `amplify-plugin.json` file is the plugin's manifest file, it specifies the plugin's name, type, commands and event handlers. The Amplify CLI uses it to verify and add the plugin package into its plugin platform.

Here's the contents of the file when it's first generated by the `amplify plugin init` command for a util plugin.

```json
 {
  "name": "my-amplify-plugin",
  "type": "util",
  "commands": [
    "version",
    "help"
  ],
  "eventHandlers": [
    "PreInit",
    "PostInit",
    "PrePush",
    "PostPush"
  ]
}
```

### index.js

The `"main"` file specified in the `package.json` is the Amplify CLI's entry to invoke the plugin's functionalities specified in the manifest file `amplify-plugin.json`.

Here's the contents of the file when it's first generated by the `amplify plugin init` command for a util plugin.

```js
const path = require('path');

async function executeAmplifyCommand(context) {
  const commandsDirPath = path.normalize(path.join(__dirname, 'commands'));
  const commandPath = path.join(commandsDirPath, context.input.command);
  const commandModule = require(commandPath);
  await commandModule.run(context);
}

async function handleAmplifyEvent(context, args) {
  const eventHandlersDirPath = path.normalize(path.join(__dirname, 'event-handlers'));
  const eventHandlerPath = path.join(eventHandlersDirPath, `handle-${args.event}`);
  const eventHandlerModule = require(eventHandlerPath);
  await eventHandlerModule.run(context, args);
}

module.exports = {
  executeAmplifyCommand,
  handleAmplifyEvent,
};
```

### commands

The `commands` folder contains files that implement the `commands` specified in the manifest file `amplify-plugin.json`.

### event-handlers

The `event-handlers` folder contains files that implement the `eventHandlers` specified in the manifest file `amplify-plugin.json`.

import all1 from "/src/fragments/cli/plugins/custom-transformer.mdx";

<Fragments fragments={{all: all1}} />
