Hydra Engine

Architecture

One body, many heads.

In the myth, the Hydra has one body and many heads. Here the body is one long-lived JVM holding Ghidra, its open projects, its analysed programs and its warm decompilers. The heads are the clients: agent harnesses, MCP servers, scripts. They come and go; the body stays.

The whole picture

one user, one daemon
  heads                       body                            projects  -----                       ----                            --------  Claude Code ----.     +---------------------------+     .-> /re/Game        (read-only view)  Codex ----------+     |  hello + token            |     |     game.exe  OpenCode -------+---->|  quick lane | long lane   |-----+     engine.dll  Hydralysis -----+     |  per-program locks        |     |  your script ----'     |  warm decompiler pools    |     '-> /work/agent-a   (working copy)                        +---------------------------+

Clients speak JSON lines over a loopback socket. Requests take a slot in one of two lanes, then a lock on the program they touch. Programs stay open, and warm, between clients.

One daemon per user

The first client to connect starts the daemon; everyone after it finds the running one through an endpoint file in the per-user state directory. Its files there:

FilePurpose
default.jsonThe endpoint: port, token, install, versions. Written once the daemon listens, removed when it exits cleanly.
default.lockHeld by the JVM for its whole life. Proves it's alive, and stops a second daemon of the same instance.
default.start.lockHeld while starting, so two clients that find no daemon at the same moment start only one.
default.logThe daemon's log, rotated at 32 MiB.

default is the instance name. Pass --instance to run a second, independent daemon, for example from another install.

Security

  • The socket binds to loopback only; other addresses are refused.
  • The first request must be hello with the endpoint file's 256-bit token, compared in constant time.
  • The endpoint file is readable by its owner only.

Anyone who can read your state directory can drive the daemon with your rights, just as anyone who can run your Python can. A script is Java running inside the daemon, not a sandbox.

Two lanes

Quick requests (decompile, functions, list, open, rename) and long ones (analyze, import, script, save) run in separate lanes with their own slots. A whole-program analysis can't take the slots a 10 ms decompile needs, and within a lane, waiting requests are admitted round-robin by client. More in Scheduling.

When a head is cut off

A client that disconnects or crashes (the OS resets its socket) is cleaned up at once:

  • its running and queued requests are cancelled;
  • a change it hadn't committed is rolled back, and nobody else's;
  • unsaved changes to programs it owned are discarded and logged;
  • those programs go back to read-only for everyone else.

Other clients never notice, except that the program they were waiting for comes free. In shared mode, a writer's committed changes survive it; see Projects.

Still Ghidra inside

Hydra Engine is upstream Ghidra master kept in sync, plus one module, Ghidra/Features/HeadlessSession, two small fixes to Ghidra classes, and a headless-only build. There are no .bat or .sh launchers for the daemon: ghidra_session.py builds the classpath and starts the JVM itself.

A legacy-12.1.4 branch carries the same module on Ghidra 12.1.4, for projects that must stay on that version.

Measured

Windows 11, JDK 25, 24 threads; a 66.7 MB x64 executable with 243,855 functions, opened read-only. Medians.

Time
No daemon running: start it and connect533 ms
Daemon start to first decompile answer1,637 ms
Warm decompile6.7-7.1 ms
The same question through stock analyzeHeadless7.0-7.8 s