Local Ghidra
By default GINE ships a headless Ghidra container (ghidra-mcp) and talks to it
through a sidecar bridge. If you already run Ghidra on your machine with the
ghidra-mcp extension installed,
you can point GINE at that instance instead: same stack, your project, your
annotations, live in your CodeBrowser.
This is a Linux-only workflow.
1. Install the plugin (once)
Follow the upstream Quickstart through installing and enabling the extension
(ghidra-mcp v7.0.0, matching your Ghidra — e.g. 12.1.4). Then, in Ghidra:
- Open the project window (not a CodeBrowser) and enable the plugin from Tools > GhidraMCP > Server Status. The plugin runs while the project window is open.
- Leave the HTTP server on its defaults (loopback). GINE does not need it exposed.
You don't install the GINE bridge yourself — GINE runs it for you (step 3).
2. Lock the socket location
The plugin always also serves a Unix domain socket at:
$XDG_RUNTIME_DIR/ghidra-mcp/ghidra-<pid>.sock
GINE reaches the plugin through this socket (the plugin's TCP port is bound to
127.0.0.1 only, so containers can't use it). Launch Ghidra from a session where
XDG_RUNTIME_DIR is set (on a desktop it is, e.g. /run/user/1000); otherwise
the plugin falls back to /tmp/ghidra-mcp-<user>, which the GINE overlay does
not mount. You can check the socket exists:
ls "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/ghidra-mcp"/*.sock
3. Start GINE against your Ghidra
make local-ghidra
This runs the normal stack with the compose.local-ghidra.yml overlay. It
defaults the socket directory to ${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/ghidra-mcp;
override it with GHIDRA_SOCKET_DIR if yours is elsewhere:
GHIDRA_SOCKET_DIR=/run/user/1000/ghidra-mcp make local-ghidra
What the overlay changes:
- the bundled
ghidra-mcpdoes not run a headless Ghidra (an idle container is kept only because the bridge shares its network namespace); ghidra-bridgeignores TCP and auto-discovers the plugin over the Unix socket, mounting the host socket directory read-only;- the orchestrator's REST client (
GhidraClient) also uses the socket (GHIDRA_SOCKET_DIR).
4. Verify
docker compose exec orchestrator python -c "
import asyncio
from app.ghidra_client import GhidraClient
print(asyncio.run(GhidraClient().check_connection()))
"
Expect {'status': 'ok', 'server_kind': 'gui', 'version': '7.0.0'}. The bridge
log should show Auto-connecting via UDS to <your project>.
Notes and limitations
- One instance, one user. The agent drives your live Ghidra: renames and decompilation appear in your CodeBrowser, and the plugin's "current program" is global. Don't point a shared/multi-user GINE deployment at a single analyst's Ghidra.
- Host PID namespace. The bridge liveness-checks the PID embedded in the
socket name, so
compose.local-ghidra.ymlruns it withpid: host. - Sandbox and binary downloads are limited. GINE has no local copy of the
binary (it lives on your machine), so
sandbox_run_scriptand the.gzf/.gardownload flows are not available for programs opened this way. - Version mismatch. Opening a program whose language/compiler spec was built by a different Ghidra version can open it read-only.