pluginkit
A small, strictly-typed, generics-first plugin framework for Python 3.13+. Declare extension points, let plugins implement them, discover plugins via entry points - and, unlike untyped hook systems, get the right return type for every call, derived from the spec and checked by your type checker.
That strict typing applies to caller arguments and mode-correct results. Plugin implementation annotations are not statically linked to independently declared specs; registration validates their argument names at runtime.
pm.caller(spec) hands back a caller whose result type matches the dispatch mode -
list[R] for collecting, R | None for firstresult, R for pipeline - with no
hand-annotations and no drift. Zero runtime dependencies, a py.typed marker, and a
few readable files.
uv add pluginkit # or: pip install pluginkit
from pluginkit import Extension, ExtensionPoint, PluginManager
extension_point = ExtensionPoint("greeter")
extension = Extension("greeter")
class Specs:
@staticmethod
@extension_point
def greeting(name: str) -> str:
"""Return a greeting for the given name."""
class Casual:
@extension
def greeting(self, name: str) -> str:
return f"hey {name}!"
pm = PluginManager("greeter")
pm.add_extension_points(Specs)
pm.register(Casual(), name="casual")
greetings = pm.caller(Specs.greeting)(name="Ada") # typed list[str] - derived, not asserted
print(greetings) # ['hey Ada!']
What it supports
- collecting,
firstresult, and pipeline (fold/middleware) hooks; - call ordering with
tryfirst/trylast, plusoptionalandtarget; - generator wrappers that decorate results and observe exceptions safely;
- historic hooks replayed to plugins registered later;
- async dispatch via
AsyncPluginManager(awaits coroutine impls); - plugin lifecycle:
register,unregister(by name or object),set_blocked, lookup,call_extra; - registration-time validation and call-time argument checking (failures are loud);
- external plugin discovery via the stdlib
importlib.metadata(no setuptools); - attribution-preserving collection and structured entry-point diagnostics;
- thread-safe registry mutation.
Layout
src/pluginkit/ the library (pure - no demo code)
examples/ everything that uses the library (not shipped):
cookbook/ worked examples: bite-size scripts + full apps
tour/ pluginkit-tour: a guided CLI walkthrough
external-plugin/ a separate distribution discovered via entry points
docs/ mkdocs + Material documentation
tests/ library, tour, and cookbook tests
Everything that demonstrates the library lives under examples/. The cookbook
holds standalone examples (from one-mechanism snippets to complete FastAPI/Click/pytest
apps); the tour is a guided walkthrough on one host; the external-plugin shows
cross-package discovery via entry points.
Use it
make install # uv sync (library + tour + external plugin)
make test # pytest (framework, tour, examples)
make lint # ruff + mypy + pyright
make docs-serve # serve the docs at http://127.0.0.1:8000
make docs-build # build the docs (strict)
Two ways to learn it
The tour (examples/tour/) walks through one mechanism at a time on a single host:
make run # run every step
make run DEMO=wrapper # run one
uv run pluginkit-tour list
The cookbook applies the library to realistic domains and frameworks - see
examples/cookbook/:
uv run python examples/cookbook/report_builder.py
uv run python examples/cookbook/fastapi_app.py
uv run python examples/cookbook/cli_app.py --help
uv run python examples/cookbook/app_lifecycle.py
Documentation
Full docs (concepts, one page per mechanism, production/hardening notes, and a
generated API reference) live under docs/. Serve them with
make docs-serve.
Is it production ready?
It is solid - exception-safe wrappers, fail-fast validation, lifecycle management, resilient discovery, thread-safe mutation, strict typing, and a test suite. But for anything you ship, prefer pluggy itself: it is maintained and battle tested by pytest, tox, and datasette. See docs/production/vs-pluggy.md for the honest inventory of what differs.
Metadata
Release files for pluginkit 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pluginkit-0.5.1.tar.gz | 18.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pluginkit-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.7 kB
Release files / pluginkit-0.5.1.tar.gz
| Download URL | pluginkit-0.5.1.tar.gz |
|---|---|
| Size | 18.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4f08e839687c9542128ae619d8a3a68b707b40b78241b540a0be897e53cbc217
|
|
BLAKE2b-256 checksum How to use checksums |
be2b2759505c00d61edeaf585d22601291b6bc8b0403e191e5e93f1e5aa2e696
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / pluginkit-0.5.1-py3-none-any.whl
| Download URL | pluginkit-0.5.1-py3-none-any.whl |
|---|---|
| Size | 20.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c05e388db16502877a73796a1f861346cf7483670aa140140183950c94803763
|
|
BLAKE2b-256 checksum How to use checksums |
df9f243729b3e5fe17c8f388d7ff3308ff21e33cdfff23dd42ea5224a696d4c2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logSecurity for pluginkit 0.5.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pluginkit-0.5.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.