Your first plugin¶
In this tutorial, we’ll step through the fundamental concepts for building a bare minimum “hello napari” plugin from scratch.
At the end, we’ll point you to a “cookiecutter” template repository that helps automate the creation of new plugins, and adds a number of conveniences for testing, maintaining, and deploying your plugin.
new plugin format!
This page describes the creation of a plugin targeting
npe2, the second
generation plugin engine.
Before you start¶
We assume you’ve set up a Python virtual environment (using a virtual environment instead of a global python installation is highly recommended). If you are new to virtual environments, we recommend installing miniconda and creating a new environment with python.
Even though plugins don’t necessarily need to list
napari as a direct dependency, and
should not depend on a specific Qt backend,
you will need a working installation of napari in your active Python
environment to use and test your plugin.
See the installation guide if this is your first time
What is a plugin?¶
Napari plugins are just Python packages. Minimally, they must:
1. Create a new directory¶
Let’s create a new folder called
napari-hello for your plugin files,
and navigate into it.
mkdir napari-hello cd napari-hello
2. Add standard Python package metadata files¶
In your root
napari-hello folder, create a
then create a
napari_hello directory with a single
__init__.py file inside of it.
mkdir napari_hello touch napari_hello/__init__.py napari_hello/napari.yaml pyproject.toml setup.cfg
mkdir napari_hello copy /b napari_hello\__init__.py +,, copy /b napari_hello\napari.yaml +,, copy /b pyproject.toml +,, copy /b setup.cfg +,,
Your project should now look like this:
~/napari-hello/ ├── napari_hello/ │ ├── __init__.py │ └── napari.yaml ├── pyproject.toml ├── setup.cfg
napari-hello vs napari_hello
You might notice that we used a dash in our top level folder, and an
underscore in the inner folder. This is the Python convention:
distribution packages use dashes, while Python files and modules use
underscores. Our package is named
napari-hello, and it includes a
single top-level module, called
You would install this package with
python -m pip install napari-hello
… and import it with …
Next, we will populate
pyproject.toml is a standard file (introduced in
PEP518, May 2016) that tells
the Python package installer pip how to
build your package. For more background, see
Clarifying PEP 518 and
What the heck is pyproject.toml?.
Here, we declare we want to use setuptools
for packaging our plugin. Paste the following text into
[build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta"
This file is where setuptools looks for package metadata. Here, we provide the bare minimum package metadata (name and version), along with a PyPI classifier that identifies the package as a napari plugin.
Paste the following text into
[metadata] name = napari-hello version = 0.0.1 classifiers = Framework :: napari [options] packages = find:
There is a lot more than can go in the package metadata. See the setuptools quickstart for more.
3. Implement the plugin¶
So far, we’ve done nothing napari-specific. Let’s create the actual plugin and add some Python code. We’re going to add a Widget contribution with a single button that shows a “Hello, world!” message when clicked.
Add plugin functionality to
Copy and paste the following text into the file at
It just uses the napari notifications API to show a message:
from napari.utils.notifications import show_info def show_hello_message(): show_info('Hello, world!')
(It doesn’t look like a widget yet! We’re going to use napari’s widget autogeneration capabilities to turn this function into a widget)
If you haven’t already, create an empty plugin manifest file at
We will use this file to tell napari:
That our plugin contributes a command (we give the command an ID of
napari-hello.say_hi. It must start with our plugin name, and be unique).
The location of the function that executes the command (the
python_name, pointing to the
show_hello_messagefunction in the
That our plugin contributes a widget, and that we’d like napari to autogenerate the widget from the command signature (so we don’t need to deal with any GUI code).
Add the following text to
name: napari-hello contributions: commands: - id: napari-hello.say_hi title: Say hello, world! python_name: napari_hello:show_hello_message widgets: - command: napari-hello.say_hi # note, same as command.id above display_name: Hello World autogenerate: true
We could have put the
show_hello_message function anywhere, it didn’t
need to go in the top
__init__.py file. Just make sure that the
of the corresponding
command in the manifest points to the correct
Lastly, let’s make a few small changes to
Because we are directly using the
napari.utils.notificationsAPI in our,
show_hello_messagefunction, we need to add
naparito our package
install_requires. (You should add all of your package dependencies here. Assume nothing about your user’s environment! Not even napari.)
We need to instruct setuptools to include that
napari.yamlfile when it bundles our package for distribution, by adding
include_package_data = Trueto the
In order for napari to find our plugin when it’s installed in the environment, we need to add a
napari.manifestentry to our
[options.entry_points]that points to the
napari.yamlfile we added to the
Entry points are a standard Python mechanism for an installed distribution to advertise components it provides to be discovered and used by other code.
See the Entry points specification for details.
With the above changes, your final
setup.cfg file should look like this:
[metadata] name = napari-hello version = 0.0.1 classifiers = Framework :: napari [options] packages = find: include_package_data = True install_requires = napari [options.entry_points] napari.manifest = napari-hello = napari_hello:napari.yaml
4. Install your plugin and try it out!¶
With that, we’re ready to go. Let’s install our package in the environment
and then run napari. Note: we’re using
python -m pip install -e . here to install our
package (in the current working directory) in “editable” mode.
This means that changes we make to our package during development will be
detected when we re-run napari, without having to run
python -m pip install again.
python -m pip install -e . napari
Once napari starts, select
napari-hello: Hello World from the
Plugins menu, then click the
Run button to see the message.
Plugins can do a lot more than just say hi! You can see the complete list of available contributions and their fields in the Contributions Reference, and learn more about each specific contribution type in the Guides.