A Python package for developing plugins for Ghidra without requiring Java development
- Quick Start — Write your first plugin in 5 minutes
- Plugin Development Guide — Full API reference and examples
- Architecture & Comparison — Why Decaf exists and how it compares to PyGhidra
- Projects using pyghidra-decaf — Real-world consumers you can study
- Contributing — How to submit patches
- Security — How to report vulnerabilities
You'll need:
- Ghidra 11.0 or later with PyGhidra bundled (PyGhidra is included in the Ghidra distribution by default)
- Python 3.10+
Decaf wraps PyGhidra and provides Python-native plugin development. See PyGhidra installation docs for setup details.
Ghidra discovers plugins at JVM startup by scanning the classpath for .class files annotated with @PluginInfo. This bytecode-level scan happens before any Python code runs, so PyGhidra's JPype proxies—which are pure Python objects with no compiled form on disk—are invisible to Ghidra's plugin system. You can use PyGhidra to script Ghidra, but you cannot register Python code as a plugin, service, or analyzer without hand-written Java boilerplate.
Decaf solves this by generating minimal Java stub classes from your Python metadata at setup time, making your Python plugins discoverable by Ghidra's bytecode scanner. At runtime, Decaf binds those stubs to your Python code via JPype reflection. The result: full plugin lifecycle (init, dispose, events, service registration, state persistence) with zero Java development.
uv pip install pyghidra_decafmkdir my-ghidra-plugin && cd my-ghidra-plugin
mkdir -p src/my_plugin
touch src/my_plugin/__init__.pyfrom importlib.metadata import version
from pyghidra_decaf.launch import (
DecafExtensionInfo, DecafPluginInfo, PluginType, PluginStatus
)
def decaf_init(launcher):
return DecafExtensionInfo(
name="My Plugin",
description="My first Ghidra plugin",
author="You",
version=version("my-plugin"),
plugins=[
DecafPluginInfo(
type=PluginType.ProgramPlugin,
qualname="MyPlugin",
class_name="MyPlugin",
status=PluginStatus.STABLE,
module_name="my_plugin.plugin",
category="Analysis",
shortDescription="My first plugin",
description="My first Ghidra plugin in pure Python",
)
],
java_package="",
)from typing import List, Tuple, Type
from pyghidra_decaf.decaf.plugin import DecafProgramPlugin
class MyPlugin(DecafProgramPlugin):
def init(self):
self.tool.setStatusInfo("MyPlugin loaded!")
def decaf_load() -> List[Tuple[str, Type[DecafProgramPlugin]]]:
return [("my_plugin.plugin.MyPlugin", MyPlugin)][build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-plugin"
version = "0.1.0"
description = "My first Ghidra plugin"
[project.entry-points."decaf.init"]
my_plugin = "my_plugin.decaf_init:decaf_init"
[project.entry-points."decaf.load"]
my_plugin = "my_plugin.plugin:decaf_load"pip install -e .
pyghidra_decaf_bootstrappyghidra --gui --install-dir ~/ghidra/ghidra_11_3_2_PUBLICWhen prompted, enable "My Plugin" in File → Install Extensions. You'll see "MyPlugin loaded!" in Ghidra's status bar.
For a complete walkthrough, see Plugin Development Guide. For a full real-world example, see mcpyghidra — a published Decaf plugin in active use.
- mcpyghidra — A Model Context Protocol (MCP) server exposing Ghidra reverse-engineering tools to LLM clients.
Built something with pyghidra-decaf? Open a PR adding it here.
This project uses uv for Python environment and package management.
# Install uv if you haven't already
curl -sSf https://astral.sh/uv/install.sh | bash
# Create a virtual environment and install dev dependencies
uv venv
uv pip install -e ".[dev]"uv run pytestuv run mypyuv run ruff check src tests
uv run ruff format src testsuv buildDecaf currently supports Plugin and ProgramPlugin extension points, enabling you to write:
- Dockable UI panels (via
ComponentProviderinterface) - Plugin lifecycle hooks (init, dispose, events, state persistence)
- Service registration and event subscriptions
Not yet supported (patches welcome):
Analyzer(auto-analysis participation)Loader(file format support)Exporter(custom export formats)FieldFactory(custom Listing columns)- Custom
PluginEventsubclasses
For use cases outside these scope, consider hand-written Java plugins or vanilla PyGhidra scripting. See the Architecture Guide for detailed feature comparison.
Apache-2.0 — see LICENSE for details.
Copyright © 2026 Nightwing Group, LLC.