QGIS Plugin Builder is a Python-based tool that helps developers quickly scaffold fully structured QGIS plugins. It generates clean boilerplate code, reusable templates, and a best-practice project layout—so you can focus on building geospatial functionality instead of setup. Whether you're new to QGIS plugin development or an experienced GIS developer, this tool streamlines the process of creating plugins with a consistent architecture, reducing development time and improving maintainability.
Key Features
- Fast plugin scaffolding with minimal setup
- Pre-built boilerplate following QGIS best practices
- Template-driven structure for easy customization
- Built for Python and the QGIS API
- Ideal for GIS developers, teams, and plugin prototyping
1. Install Plugin Builder
Open QGIS and go to Plugins → Manage and Install Plugins. Search for Plugin Builder and install it.
2. Open Plugin Builder
Go to Plugins → Plugin Builder → Plugin Builder. The wizard opens.
3. Fill in the required fields
On the first page enter:
- Class name — CamelCase Python class name (e.g.
MyPlugin) - Module name — snake_case file name (e.g.
my_plugin) - Plugin name — human-readable title shown in QGIS menus
- Description — one-line summary of what the plugin does
- Version — starting version number (e.g.
0.1) - Minimum QGIS version — minimum compatible version (required; defaults to
4.0) - Maximum QGIS version — maximum compatible version (required; defaults to
4.99) - Author and Email
On the second page enter a longer About description.
4. Choose a template
On the template page select one of:
- Tool button with dialog — toolbar button that opens a modal dialog
- Tool button with dock widget — toolbar button that opens a dock panel
- Processing provider — adds an algorithm to the Processing toolbox
5. Set publication info (optional)
Enter URLs for your bug tracker, home page, and repository. Add tags to help users find the plugin on the QGIS Plugin Repository.
6. Choose additional components
Check the components you want included:
- Internationalization — stub i18n setup for adding translated strings
- Help — a Sphinx documentation project in
help/ - Unit tests — a pytest test suite wired to
pytest-qgis; tests use plainassertand are excluded from the packaged plugin via.gitattributesso they never reach QGIS's upload scanner - Helper scripts — scripts for publishing to plugins.qgis.org and managing translations
- Makefile — a GNU Makefile for building and deploying
- pb_tool — a
pb_tool.cfgfor thepb_toolcommand-line deploy tool
7. Generate the plugin
Click Generate, choose an output directory, and click Generate again. Plugin Builder writes all the files into a new directory named after your module.
Resource file compilation is optional. It is best practice to reference
resources such as icons and images using os.path rather than Qt's resource
system:
icon_path = os.path.join(os.path.dirname(__file__), 'icon.png') icon = QIcon(icon_path)
This avoids the need to run rcc at build time and keeps your assets visible
as ordinary files. If you do use a .qrc file, compile it with:
rcc -g python resources.qrc -o resources.py
8. Deploy and test
Use pb_tool to deploy the generated plugin to your QGIS plugin directory:
cd my_plugin pip install pb_tool pb_tool deploy
Then open QGIS, enable the plugin in Plugins → Manage and Install Plugins, and run it to confirm it loads correctly.
9. Running the generated tests
If you included the "Unit tests" component, the plugin ships with a
pytest/pytest-qgis suite in test/. These tests import the real
qgis Python bindings, so they must run against a Python environment that
can see your QGIS install:
- Create a virtual environment that inherits the system's site-packages so it
picks up the
qgisbindings, e.g.python3 -m venv --system-site-packages .venv(oruv venv --system-site-packages), then activate it. - Set
QGIS_PREFIX_PATHsopytest-qgiscan locate your QGIS installation:export QGIS_PREFIX_PATH=/usron most Linux systems,/usr/localon macOS with Homebrew, or the QGIS install directory on Windows. - Install the test dependencies:
pip install -r requirements-dev.txt(oruv add --dev -r requirements-dev.txt). - Run the suite with
pytestormake testfrom the plugin directory. - Editors backed by Pyright/Pylance (VS Code) or PyCharm may flag imports like
photo_linker.photo_linker_dialogas unresolved, because they don't add the plugin's parent directory to the import path automatically. Fix it by adding"python.analysis.extraPaths": [".."]to.vscode/settings.json(VS Code), or by marking the plugin's parent directory as a Sources Root in PyCharm. Jedi-backed editors (e.g. jedi-language-server, python-lsp-server) resolve this automatically and don't need either fix.
Before publishing
The QGIS Plugins website runs Bandit on every upload as a part of security
scanning and treats any B101 (assert_used) finding as critical,
blocking the upload outright.
Generated tests use the pytest best-practice assert. The
plugin's .gitattributes excludes test/ via export-ignore, so any
packaging that goes through git archive (what qgis-plugin-ci
and the generated GitHub/GitLab release workflows use) never includes the
test suite in the uploaded zip.
This protection only holds if you package through git. If you zip the
plugin directory by hand, use a custom build script, or remove/edit
.gitattributes, the test/ directory (with its assert statements)
can end up in the zip and get your upload rejected. Before uploading
anywhere other than through the generated release workflow, confirm
test/ isn't included.
10. Start developing
The generated plugin is a working stub. Open the source files in your editor,
implement your logic, and use pb_tool deploy -q to redeploy quickly as you
iterate.
See the help documentation for full details on each wizard field and deployment option.
New plugin templates can be added by creating a subdirectory below plugin_templates and registering the template in plugin_templates/__init__.py
The pluginbuilder4 package is type-checked with mypy
in strict mode (configured in mypy.ini). To run it:
Create a virtual environment that inherits the system's site-packages so it picks up the
qgisbindings, e.g.python3 -m venv --system-site-packages .venv, then activate it.Install mypy and the type stubs:
pip install "mypy>=2.4" "qgis-stubs==1.0.0.dev0" types-defusedxml
qgis-stubs1.x targets QGIS 4 / Qt6 and is currently a pre-release, so it is pinned to an exact version; the 0.x releases target QGIS 3 / Qt5 and won't work. mypy 2.4 or newer is needed to read thePyQt6-stubsit depends on.Run
make typecheckfrom the repository root. The same check runs as apre-commithook, which installs its own copies of mypy and the stubs.
qgis-stubs doesn't cover the qgis.PyQt imports, so the stubs/
directory provides small local stubs that re-export the PyQt6 types for
qgis.PyQt.QtCore, QtGui, QtWidgets and uic. They are only used
by mypy and are not packaged with the plugin.
