West is “pluggable”: you can add your own commands to west without editing its
source code. These are called west extension commands, or just “extensions”
for short. Extensions show up in the
west --help output in a special
section for the project which defines them. This page provides general
information on west extension commands, and has a tutorial for writing your
Some commands you can run when using west with Zephyr, like the ones used to
build, flash, and debug and the
ones described here , are extensions. That’s why
help for them shows up like this in
commands from project at "zephyr": completion: display shell completion scripts boards: display information about supported boards build: compile a Zephyr application sign: sign a Zephyr binary for bootloader chain-loading flash: flash and run a binary on a board debug: flash and interactively debug a Zephyr application debugserver: connect to board and launch a debug server attach: interactively debug a board
zephyr/scripts/west-commands.yml and the
zephyr/scripts/west_commands directory for the implementation details.
Disabling Extension Commands
To disable support for extension commands, set the
configuration option to
false. To set this
globally for whenever you run west, use:
west config --global commands.allow_extensions false
If you want to, you can then re-enable them in a particular west workspace with:
west config --local commands.allow_extensions true
Note that the files containing extension commands are not imported by west unless the commands are explicitly run. See below for details.
Adding a West Extension
There are three steps to adding your own extension:
Write the code implementing the command.
Add information about it to a
Make sure the
west-commands.ymlfile is referenced in the west manifest.
Note that west ignores extension commands whose names are the same as a built-in command.
Step 1: Implement Your Command
Create a Python file to contain your command implementation (see the “Meta >
Requires” information on the west PyPI page for details on the currently
supported versions of Python). You can put it in anywhere in any project
tracked by your west manifest, or the manifest repository itself.
This file must contain a subclass of the
this class will be instantiated and used when your extension is run.
Here is a basic skeleton you can use to get started. It contains a subclass of
WestCommand, with implementations for all the abstract methods. For more
details on the west APIs you can use, see West APIs.
'''my_west_extension.py Basic example of a west extension.''' from textwrap import dedent # just for nicer code indentation from west.commands import WestCommand # your extension must subclass this from west import log # use this for user output class MyCommand(WestCommand): def __init__(self): super().__init__( 'my-command-name', # gets stored as self.name 'one-line help for what my-command-name does', # self.help # self.description: dedent(''' A multi-line description of my-command. You can split this up into multiple paragraphs and they'll get reflowed for you. You can also pass formatter_class=argparse.RawDescriptionHelpFormatter when calling parser_adder.add_parser() below if you want to keep your line endings.''')) def do_add_parser(self, parser_adder): # This is a bit of boilerplate, which allows you full control over the # type of argparse handling you want. The "parser_adder" argument is # the return value of an argparse.ArgumentParser.add_subparsers() call. parser = parser_adder.add_parser(self.name, help=self.help, description=self.description) # Add some example options using the standard argparse module API. parser.add_argument('-o', '--optional', help='an optional argument') parser.add_argument('required', help='a required argument') return parser # gets stored as self.parser def do_run(self, args, unknown_args): # This gets called when the user runs the command, e.g.: # # $ west my-command-name -o FOO BAR # --optional is FOO # required is BAR log.inf('--optional is', args.optional) log.inf('required is', args.required)
You can ignore the second argument to
unknown_args above), as
WestCommand will reject unknown arguments by default. If you want to be
passed a list of unknown arguments instead, add
Step 2: Add or Update Your
You now need to add a
west-commands.yml file to your project which
describes your extension to west.
Here is an example for the above class definition, assuming it’s in
my_west_extension.py at the project root directory:
west-commands: - file: my_west_extension.py commands: - name: my-command-name class: MyCommand help: one-line help for what my-command-name does
The top level of this YAML file is a map with a
west-commands key. The
key’s value is a sequence of “command descriptors”. Each command descriptor
gives the location of a file implementing west extensions, along with the names
of those extensions, and optionally the names of the classes which define them
(if not given, the
class value defaults to the same thing as
Some information in this file is redundant with definitions in the Python code.
This is because west won’t import
my_west_extension.py until the user
west my-command-name, since:
It allows users to run
west updatewith a manifest from an untrusted source, then use other west commands without your code being imported along the way. Since importing a Python module is shell-equivalent, this provides some peace of mind.
It’s a small optimization, since your code will only be imported if it is needed.
So, unless your command is explicitly run, west will just load the
west-commands.yml file to get the basic information it needs to display
information about your extension to the user in
west --help output, etc.
If you have multiple extensions, or want to split your extensions across
multiple files, your
west-commands.yml will look something like this:
west-commands: - file: my_west_extension.py commands: - name: my-command-name class: MyCommand help: one-line help for what my-command-name does - file: another_file.py commands: - name: command2 help: another cool west extension - name: a-third-command class: ThirdCommand help: a third command in the same file as command2
another_file.pydefines two extensions:
See the file
west-commands-schema.yml in the west repository for a
schema describing the contents of a
Step 3: Update Your Manifest
Finally, you need to specify the location of the
just edited in your west manifest. If your extension is in a project, add it
manifest: # [... other contents ...] projects: - name: your-project west-commands: path/to/west-commands.yml # [... other projects ...]
path/to/west-commands.yml is relative to the root of the project.
Note that the name
west-commands.yml, while encouraged, is just a
convention; you can name the file something else if you need to.
Alternatively, if your extension is in the manifest repository, just do the
same thing in the manifest’s
self section, like this:
manifest: # [... other contents ...] self: west-commands: path/to/west-commands.yml
That’s it; you can now run
west my-command-name. Your command’s name, help,
and the project which contains its code will now also show up in the
--help output. If you share the updated repositories with others, they’ll be
able to use it, too.