Page updated Jan 16, 2024

Command hooks

Use Command Hooks to execute custom scripts before, during, and after Amplify CLI commands (“amplify push”, “amplify api gql-compile”, and more). This allows you to extend Amplify’s best-practice defaults to meet your organization’s specific security guidelines and operational requirements.

Adding a command hook

Hooks need to be checked into source control in order to be made available across machines. amplify pull will not re-create the hooks folder automatically as these are considered changes that need to be committed to the repository.

Place your custom scripts in the amplify/hooks directory and set the script file name to the desired command with a pre or post designation. For example post-add-function.js will execute the script after amplify add function. For more information about the script naming convention, see How to name command hook scripts.

For this example, let's create a hook to ensure that a minimum major Amplify CLI version is used before deployment (amplify push).

Let's add pre-push.js in the amplify/hooks directory with the following contents. Note: You need to create a amplify/hooks folder if your Amplify project was created prior to Amplify CLI version 5.5.0

1const fs = require('fs');
2const parameters = JSON.parse(fs.readFileSync(0, { encoding: 'utf8' }));
3
4// Get the running Amplify CLI major version number
5const currentCLIMajorVersion = parameters.data.amplify.version.split('.')[0]
6console.log('Amplify CLI major version: ', currentCLIMajorVersion)
7
8const MINIMUM_MAJOR_AMPLIFY_CLI_VERSION = 5
9console.log('Minimum required Amplify CLI major version: ', MINIMUM_MAJOR_AMPLIFY_CLI_VERSION)
10
11if (currentCLIMajorVersion < MINIMUM_MAJOR_AMPLIFY_CLI_VERSION) {
12 // Non-zero exit code will stop the Amplify CLI command's execution
13 console.log('Minimum CLI version requirement not met.')
14 process.exit(1)
15} else {
16 console.log('Minimum CLI version requirement met.')
17 process.exit(0)
18}

Next, let's run amplify push:

1amplify push
1----- 🪝 pre-push execution start -----
2Amplify CLI major version: 5
3Minimum required Amplify CLI major version: 5
4Minimum CLI version requirement met.
5----- 🪝 pre-push execution end -----

How to name command hook scripts

To hook into a command, the script file in the amplify/hooks directory should be named with the following naming convention:

pre|post-<command>[-<sub-command>].extension

  • command (required) - Amplify command.
  • extension (required) - by default .js and .sh are mapped to Node.js and Bash. To support more extensions or scripting runtimes, see Adding a custom scripting runtime.
  • sub-command (optional) - Amplify sub-command. Can be used to increase hook specificity. Example: pre-add-auth and pre-mock-api.

The following is an exhaustive list of all commands along with their subcommands that are supported by Amplify CLI:

commandssub-commands (optional)
addall categories (api, auth, etc.)
codegen
env
updateall categories (api, auth, etc.)
env
removeall categories (api, auth, etc.)
env
pushanalytics, api, auth, function, hosting, interactions, storage, xr
pullenv
publish-
delete-
checkoutenv
listenv
getenv
mockapi, storage, function
buildfunction
statusnotifications
importauth, storage, env
gqlcompileapi
addgraphqldatasourceapi
statementscodegen
typescodegen

Note: Multiple hook scripts with the same filename are not allowed

Access parameters in hook scripts

Command hooks receive two parameters, data and error. Amplify CLI passes parameters to hook scripts as a JSON string through standard input.

data parameter structure

1{
2 "amplify": {
3 "version": String,
4 "environment": {
5 "envName": String,
6 "projectPath": String,
7 "defaultEditor": String
8 },
9 "command": String,
10 "subCommand": String,
11 "argv": [ String ]
12 }
13}
  • amplify
    • version - current Amplify CLI version
    • environment - current Amplify environment
      • envName - current Amplify environment name
      • projectPath - path to current Amplify project
      • defaultEditor - chosen editor in init step. Example vscode
    • command - hooked Amplify CLI command. Example: push
    • subCommand - hooked Amplify CLI subcommand or plugin. Example auth, env.
    • argv - list containing the arguments passed to Amplify CLI through the command line

error parameter structure

error is undefined if no error is emitted. Otherwise, it has the following structure:

1{
2 "message": String,
3 "stack": String
4}
  • message - the error message emitted by Amplify CLI
  • stack - the error stack emitted by Amplify CLI

How to access command hook parameters in Node.js

1const fs = require('fs');
2const parameters = JSON.parse(fs.readFileSync(0, { encoding: 'utf8' }));
3console.log(parameters.data, parameters.error)

How to access command hook parameters in Bash

First, install a JSON parser like jq.

Then, parse the parameters:

1parameters=`cat`
2data=$(jq -r '.data' <<< "$parameters")
3error=$(jq -r '.error // empty' <<< "$parameters")
4echo $data
5echo $error

How to conditionally stop an Amplify CLI command execution

To stop the execution of Amplify CLI, the hook scripts can exit with a non-zero exit code.

1process.exit(1)
1exit 1

Advanced command hook configurations

You can optionally add hooks-config.json in amplify/hooks to configure custom scripting runtimes or manage external dependencies.

Adding a custom scripting runtime

By default, Node.js and Bash are supported. To support additional runtimes, add extensions to the hooks-config.json file in the amplify/hooks folder.

An example showcasing python runtime support and different runtime settings based on operating system:

1{
2 "extensions": {
3 "py": {
4 "runtime": "python3"
5 },
6 "js": {
7 "runtime": "~/.nvm/versions/node/v14.17.1/bin/node",
8 "runtime_windows": "node",
9 "runtime_options": ["--require", "./payload.js"],
10 }
11 }
12}
  • The keys in the extensions ( js, py ) are values that will be used as extension in the naming convention used when naming the hook scripts.
  • runtime (required) - symlink (node, python, bash) or path to executable (~/.nvm/versions/node/v14.17.1/bin/node).
  • runtime_windows (optional) - windows specific symlink or path to executable.
  • runtime_options (optional) - Array of cli options to be passed to command hooks specific to runtime.

Managing third-party dependencies

Packages from external package managers like npm can be used in command hooks scripts. In this example, you'll install axios as a dependency for your Node.js hooks.

First, go to the hooks folder and install the axios dependency.

1cd amplify/hooks
2npm init
3npm install axios

Note: If you use command hooks with Amplify Hosting CI/CD pipelines, you also need to have a preBuild step configured to install the hook dependencies:

1backend:
2 phases:
3 preBuild:
4 commands:
5 - cd amplify/hooks
6 - npm install
7frontend:
8...

Dependency directories and files, such as node_modules, should be added to ignore in hooks-config.json.

1{
2 "ignore": ["node_modules", "build"]
3}

Note: All entries in ignore should follow the .gitignore specification.

You can now use axios in your hook scripts placed in the amplify/hooks directory.

Executing different logic based on environment

When using multi-environment setup you can customize command hooks logic based on data.amplify.environment.envName parameter.

1/**
2 * @param data { { amplify: { environment: { envName: string, projectPath: string, defaultEditor: string }, command: string, subCommand: string, argv: string[] } } }
3 * @param error { { message: string, stack: string } }
4 */
5const hookHandler = async (data, error) => {
6 if (data.amplify.environment.envName === 'prod') {
7 console.log('Executing pre-add-auth hook for prod environment');
8 } else if (data.amplify.environment.envName === 'dev') {
9 console.log('Executing pre-add-auth hook for dev environment');
10 }
11};
12
13const getParameters = async () => {
14 const fs = require("fs");
15 return JSON.parse(fs.readFileSync(0, { encoding: "utf8" }));
16};
17
18getParameters()
19 .then((event) => hookHandler(event.data, event.error))
20 .catch((err) => {
21 console.error(err);
22 process.exitCode = 1;
23 });

Using command hooks in Amplify's CI/CD pipeline

Command hooks are executed when CI/CD builds are triggered on Amplify Hosting. To execute hook scripts in the Amplify Hosting, add the hook scripts to the amplify/hooks directory and commit them to your source control.

By default only pre-push and post-push hooks will be executed on builds in Amplify Hosting.

To use scripting runtimes other than Node.js and Bash, see Adding a custom scripting runtime and also update the Build Settings in Amplify Hosting to include the runtime executable.

In this example, you'll add a python hook script running in the Amplify Hosting's CI/CD pipeline:

  1. Add the python hook script along with hooks-config.json to the hooks directory.

    1touch amplify/hooks/hooks-config.json
  2. Navigate to your app in the Amplify Hosting and select App settings > Build settings to update the preBuild phase to install python.

    1...
    2backend:
    3phases:
    4 preBuild:
    5 commands:
    6 - yum install -y python3
    7frontend:
    8...
  3. Add python3 to hooks-config.json and push the change to your source control to trigger the Amplify Hosting build.

    1{
    2 "extensions": {
    3 "py": { "runtime": "python3" }
    4 }
    5}
  4. You’re all set! The python command hooks will be executed in new CI/CD builds.

Command hook limitations with Amplify Studio

Command Hooks are not executed when updating a backend via Amplify Studio.