web-ext is a command line tool designed to speed up various parts of the extension development process, making development faster and easier. This article explains how to install and use web-ext.


web-ext is a node-based application that you can install with the nodejs/npm tool. Install web-ext using the following command:

npm install --global web-ext

web-ext requires the current LTS (long term support) version of NodeJS.

You can test whether your installation worked by running the following command, which lists the installed web-ext version number:

web-ext --version

Using web-ext

Once you've installed it, you can test web-ext out. At this point, it is a good idea to have a sample extension to try it out on — if you don't have one of your own, you can clone our webextensions-examples repo.

Testing out an extension

You can test an extension in Firefox by cd'ing into your extension's root directory and entering the following command:

web-ext run

This will start up Firefox and load the extension temporarily in the browser, just like you could on the about:debugging page.

See the run reference guide to learn about all available options.

Automatic extension reloading

The run command will watch your source files and tell Firefox to reload the extension after you edit and save a file. For example, if you changed the name property in your manifest.json file, Firefox would display the new name. This makes it easy to try out new features and see them immediately. The automatic reloading feature is active by default so you can use it like this:

web-ext run

You can also press the r key from the web-ext terminal to trigger an extension reload manually.

If you experience unexpected behavior with the reloading feature, please file a bug. You can also disable reloading like this:

web-ext run --no-reload

Extension reloading is only supported in Firefox 49 or higher.

Testing in different versions of Firefox

To run your extension in a version of Firefox Desktop other than the default, use the --firefox option to specify a full path to the binary file. Here is an example on Mac OS:

web-ext run --firefox=/Applications/FirefoxNightly.app/Contents/MacOS/firefox-bin

On Windows, the path needs to include the firefox.exe part, for example:

web-ext run --firefox="C:\Program Files\Mozilla Firefox\firefox.exe"

See the run command reference for all available options.

Testing in Firefox 48

Firefox 48 was the first stable version to use the WebExtension platform but it doesn't allow web-ext to install an extension remotely. You need to run your extension in Firefox 48 with a different installation option:

web-ext run --pre-install

Testing in Firefox for Android

To run your extension in Firefox for Android, install Firefox on your device, set up the device for development and make sure it's connected to the computer you're running web-ext from.

Run this basic command to get started:

web-ext run --target=firefox-android

This will prompt you to select your Android device and it will provide a list of connected devices. If you don't see a list of devices, make sure you had set up the device for development as explained above.

Once you know the device ID, add it to the command:

web-ext run --target=firefox-android --android-device=<device ID>

If you have multiple versions of Firefox installed, you may need to choose a specific version. Example:

web-ext run --target=firefox-android ... --firefox-apk=org.mozilla.firefox

The first time you run this command, you may also need to grant Android permissions for the APK. Specifically, the command needs read / write access to device storage so that Firefox for Android can run on a temporary profile. The web-ext output will guide you in how to grant these permissions.

The web-ext command will not alter any of your existing Firefox for Android preferences or data. If you'd like to see more information about how web-ext is interacting with your device, run the command with --verbose.

See the run command reference for all available options.

Debugging in Firefox for Android

While using web-ext run to test an extension on Firefox for Android, you'll notice a message like this in the console output:

You can connect to this Android device on TCP port 51499 

This is a remote debugger port that you can connect to with Firefox's developer tools. In this case, you'd connect to host localhost on port 51499.

See this guide for more information about debugging an extension on Firefox for Android.

Testing unsigned extensions

When you execute web-ext run, the extension gets installed temporarily until you close Firefox. This does not violate any signing restrictions. If instead you create a zip file with web-ext build and try to install it into Firefox, you will see an error telling you that the add-on is not signed. You will need to use an unbranded build or use a development build to install unsigned extensions.

Using a custom profile

By default, the run command will create a temporary Firefox profile. You can run your extension with a specific profile using the --firefox-profile option, like this:

web-ext run --firefox-profile=your-custom-profile

This option accepts a string containing the name of your profile or an absolute path to the profile directory. This may be helpful if you want to manually configure some settings that will always available to the run command.

Keeping profile changes

The run command will not save any changes made to the custom profile specified by --firefox-profile. To keep changes, add this option:

web-ext run --keep-profile-changes --firefox-profile=your-custom-profile

This may be helpful if your extension has many different run states.

This option makes the profile specified by --firefox-profile completely insecure for daily usage. It turns off auto-updates and allows silent remote connections, among other things. Specifically, it will make destructive changes to the profile that are required for web-ext to operate.

Packaging your extension

Once you've tested your extension and verified that it's working, you can turn it into a package for submitting to addons.mozilla.org using the following command:

web-ext build

This will output a full path to the generated .zip file that can be loaded into a browser.

The generated .zip file doesn't work on Firefox without signing it or adding applications.gecko.id key into manifest.json.  For more information, please refer WebExtensions and the Add-on ID page.

web-ext build is designed to automatically ignore files that are commonly unwanted in packages, such as .git, node_modules, and other artifacts.

See the build reference guide to learn more.

Signing your extension for distribution

As an alternative to publishing your extension on addons.mozilla.org, you can self-host your package file but it needs to be signed by Mozilla first. The following command packages and signs a ZIP file, then returns it as a signed XPI file for distribution:

web-ext sign --api-key=$AMO_JWT_ISSUER --api-secret=$AMO_JWT_SECRET 

The API options are required to specify your addons.mozilla.org credentials.

  • --api-key: the API key (JWT issuer) from addons.mozilla.org needed to sign the extension. This is a string that will look something like user:12345:67.
  • --api-secret: the API secret (JWT secret) from addons.mozilla.org needed to sign the extension. This is a string that will look something like 634f34bee43611d2f3c0fd8c06220ac780cff681a578092001183ab62c04e009.

See the sign reference guide to learn about all available options.

Signing extensions without an explicit ID

web-ext fully supports signing extensions that do not declare the applications.gecko.id property in their manifest. The first time you sign an extension without an explicit ID, addons.mozilla.org will auto-generate an ID and web-ext will save it to .web-extension-id in the current working directory. You should save the ID file so that you can sign future versions of the same extension. If you lose the ID file, you will have to add back the applications.gecko.id property or use the --id option when signing future versions, for example:

web-ext sign --api-key=... --api-secret=... --id="{c23c69a7-f889-447c-9d6b-7694be8035bc}"

Signing in a restricted environment

If you are working in an environment that restricts access to certain domains, you can try using a proxy when signing:

web-ext sign --api-key=... --api-secret=... --api-proxy=https://yourproxy:6000

See the --api-proxy option to learn more.

The following domains will be used for signing and downloading files:

  • addons.mozilla.org
  • addons.cdn.mozilla.net

Checking for code "lint"

Before trying out your extension with the run command or submitting your package to addons.mozilla.org, you can use the lint command to make sure your manifest and other source files do not contain any errors. Example:

web-ext lint

This uses the addons-linter library to walk through your source code directory and report any errors, such as the declaration of an unknown permission.

See the lint reference guide to learn about all available options.

Setting option defaults in a configuration file

You can specify --config=my-config.js to set default values for any option. Here is an example with the build command:

web-ext --config=my-config.js build

The file should be a CommonJS module as understood by NodeJS and must export each configuration value. Here is how you would set the default value of --verbose to true:

module.exports = {
  verbose: true,

If you want to specify options that only apply to a specific command, you would nest the configuration under the command name. Here is an example of adding configuration for --overwrite-dest which only applies to the build command as well as --firefox which only applies to the run command:

module.exports = {
  // Global options:
  verbose: true,  
  // Command options:
  build: {
    overwriteDest: true,
  run: {
    firefox: 'nightly',

To create a configuration key for a command line option, you remove the preceding dashes and convert the name to camel case. As you can see from this example, --overwrite-dest was converted to overwriteDest.

If an option can be specified multiple times on the command line then you can define it as an array. For example, here is how to specify multiple --ignore-files patterns:

module.exports = {
  ignoreFiles: [

Automatic discovery of configuration files

For convenience, web-ext will load existing configuration files in the following order:

  • A config file named exactly .web-ext-config.js in your home directory
    • Example on Windows: C:\Users\<username>\.web-ext-config.js
    • Example on macOS: /Users/<username>/.web-ext-config.js
    • Example on Linux: /home/<username>/.web-ext-config.js
  • A config file named exactly web-ext-config.js in the current directory

If both a home directory config and a local directory config define the same option, the value from the latter file will be used.

To disable automatic loading of configuration files, set this option:

web-ext --no-config-discovery run

To diagnose an issue related to config files, re-run your command with --verbose. This will tell you which config file affected which option value.

Specifying different source and destination directories

The above commands all use default directories for the extension source and artifact creation (e.g. built .zip files). The defaults are:

  • Source: The directory you are currently inside.
  • Artifacts: A directory called ./web-ext-artifacts, created inside the current directory.

You can specify different source and destination directories using the --source-dir and --artifacts-dir options when running your commands. Their values can be relative or absolute paths, but must always be specified as strings. Here is an example of specifying both options at the same time when  building an extension:

web-ext build --source-dir=webextension-examples/notify-link-clicks-i18n --artifacts-dir=zips

Outputting verbose messages

If you want to see exactly what web-ext is doing when you run a command, you can include the --verbose option. For example:

web-ext build --verbose

Viewing all commands and options

You can list all commands and options like this:

web-ext --help

You can list options for a specific command by adding it as an argument:

web-ext --help run

Detecting temporary installation

Your extension can detect whether it was installed using web-ext run rather than as a built and signed extension downloaded from addons.mozilla.org. Listen for the runtime.onInstalled event and check the value of details.temporary.

Using web-ext from a script

You can use web-ext as a NodeJS module. Here is more information with example code.

See also

Document Tags and Contributors

 Last updated by: kumar303,