- Python 38.8%
- Jinja 33.4%
- Shell 25.7%
- C++ 1.3%
- CMake 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Rename the bundled skill library from .claude/skills to .agents/skills so it is agent-agnostic rather than tied to one assistant, updating every reference (Makefile validate target, Forgejo CI step, ruff extend-exclude and codespell skip, and the READMEs). Add the human-review skill (maintainer-grade change review with complexity/duplication/comment analysers and an optional pre-push hook) to the library so generated plugins ship with it. Assisted-by: Agent (claude) <ai@blobfish.icu> |
||
| template | ||
| copier.yml | ||
| README.md | ||
copier-qgis-plugin
A Copier template for python-first QGIS plugins with an optional SIP-generated C++ extension, a Qt Designer UI, translations, a full lint / type / format toolchain, and a signed, auditable commit workflow.
Most existing QGIS plugin templates (Plugin Builder, pb_tool, older
cookiecutters) are unmaintained or predate uv, ruff, and modern typing.
This template targets the current ecosystem: uv for dependencies,
qgis-plugin-ci for packaging
and release, and Forgejo Actions for CI.
Repository layout
This repo follows the canonical Copier layout: the template content lives under
template/ (Copier's _subdirectory), and only copier.yml and this README
sit at the root.
copier.yml template questions and engine config
template/ the rendered plugin tree (.jinja files are templated)
README.md this file
Everything a generated project needs -- signing scripts, TAGS.md/SCOPES.md,
pre-commit config, CI, docs -- is shipped inside template/, so generated
plugins are self-governing.
What you get
A generated plugin includes:
- a
uv-managedpyproject.toml, ruff-formatted and mypy-clean out of the box; - a proper plugin package (
classFactory, main class,metadata.txt) following the current PyQGIS structure; - a Qt Designer dialog (
dialog_base.ui) loaded viauic.loadUi; - translation plumbing (
i18n/*.ts,self.tr(...),pylupdate5/lreleaseMake targets, aQTranslatorloaded at startup); - an optional QGIS Processing provider with a sample algorithm;
- an on-demand runtime dependency loader (
dependencies.py+requirements-runtime.txt) that installs missing pure-python libraries viapipon first load, adapting the qgis-easy-dependencies pattern to a PEP 508 requirement list (headless-testable helpers); - an optional C++ extension wired through SIP + CMake, exporting
compile_commands.jsonfor clangd, clang-tidy, and clang-format; - pre-commit hooks (ruff, mypy, codespell, clang-format) and a
commit-msghook enforcing Conventional Commits with a mandatory scope; - README badges and a "Publishing to the QGIS Plugin Repository" guide;
- an agent-agnostic
.agents/skills/library —qgis-validate(offline plugins.qgis.org pre-flight, also wired intomake validateand CI),qgis-smoke-test(headless load in a real QGIS),qgis-run(deploy + run with the actual QGIS binary), andhuman-review(maintainer-grade change review with complexity/duplication analysers); - Forgejo Actions CI that lints, type-checks, tests, validates, and packages.
Requirements
copier and uv (and git). Building the optional C++ extension additionally
needs a C++17 compiler, CMake, and the clang tools; translations need Qt 5's
pylupdate5 / lrelease.
Quick start
uvx copier copy gh:youruser/copier-qgis-plugin path/to/new-plugin
cd path/to/new-plugin
uv sync --all-extras
uv run pre-commit install --install-hooks --hook-type commit-msg --hook-type pre-push
make deploy # symlink into the active QGIS profile for live testing
Update a generated plugin when the template changes:
uvx copier update
Template questions
See copier.yml. Key choices: plugin_name, plugin_package,
qgis_minimum_version, use_processing_provider, and use_cpp_extension
(which toggles the entire SIP/CMake/clang chain).
Commit & signing workflow
The generated project bakes in two conventions so autonomous (agent) changes are attributable and verifiable; humans commit normally.
Agent commits go through scripts/git-agent-commit (exposed as
git agent-commit): it sets the agent author/committer identity, signs the
commit, and runs the normal hook path. Messages must be Conventional Commits
with a mandatory scope (types in TAGS.md, scopes in SCOPES.md), enforced
by the commit-msg hook.
Signing has two paths, auto-detected by the wrapper:
scripts/setup-signing-key.sh-- registers a short-lived ed25519 key to a Forgejo/Gitea account (needs~/.config/forgejo-agent/envfrom your chezmoi state) so commits show a verified badge;scripts/setup-local-signing.sh-- the same key without a forge, for sandboxes or before that env is deployed (signed, but no forge badge).
Put the wrapper on PATH once:
ln -s "$PWD/scripts/git-agent-commit" ~/.local/bin/git-agent-commit.
Developing the template
Render with an answers file and run the generated project's own checks:
uvx copier copy --trust --data-file answers.yml --defaults . /tmp/out
cd /tmp/out && uv sync --all-extras && make check
License
MIT. Generated plugins default to GPL-3.0-or-later because they link the GPL QGIS API; choose another license at generation time if that does not apply.