Skip to content
Hydra Engine
12.3-hydra.1 · Windows x64

One Ghidra,
many heads.

Hydra Engine is a headless reverse-engineering engine for AI agents. One long-lived daemon holds Ghidra, its projects, its analysed programs and its warm decompilers, and serves every agent harness, MCP server and script on the machine at once.

Derived from NSA's Ghidra (Apache-2.0). Not affiliated with or endorsed by the NSA or the Ghidra project, and not affiliated with Marvel.

An ASCII hydra: heads labelled with client names attach to one daemon body one by one; one head is cut off (a killed client: its locks are freed and its edits dropped), the body keeps working, and two new heads grow.

From the engine's README

measured
launch until the daemon is ready
348 ms
open a 243,855-function program
847 ms
launch until the first decompile
1.52 s
a warm decompile
6.7–7.1 ms

Medians of 9 rounds on Ghidra master (12.3 DEV) with the session module, Windows 11, JDK 25.0.4, 24 threads; a 66.7 MB x64 executable with 243,855 functions, opened read-only, AOT and class search caches on. README, Performance

An agent session

What an agent session looks like

The first client starts the daemon; every later one joins it through a per-user endpoint file and finds the project, the program and the decompilers already warm. Name yourself with client and harness, and every status and busy answer says who is doing what.

  • Read-only by default. A project opens without a lock file, so a Ghidra window can read it too.
  • Imports once. The same file is refused by SHA-256.
  • Any language. JSON lines over an authenticated loopback socket; Python ships a stdlib-only client.

>>> import ghidra_session as gs, 2.2 ms

>>> s = gs.connect(client='demo', harness='readme'), 643.3 ms

>>> s.call('open_project', path='demo.gpr', writable=True)['id'], 145.3 ms. Output: 'p1'

>>> s.call('import', file='hydra_demo.exe', analyze=True)['imported'], 15.52 s. Output: True

>>> s.call('import', file='hydra_demo.exe')['imported'] # same SHA-256: never twice, 4.2 ms. Output: False

>>> {k: s.call('info')[k] for k in ('format', 'language', 'functions')}, 2 ms. Output: {'format': 'Portable Executable (PE)', 'language': 'x86:LE:64:default', 'functions': 574}

>>> print(s.call('decompile', name='grow_heads')['c']), 248.2 ms. Output: int __cdecl grow_heads(int param_1,int param_2) { int iVar1; iVar1 = 0; if (0 < param_2) { do { if (param_1 == 0) { return 0; } param_1 = param_1 + 1; iVar1 = iVar1 + 1; } while (iVar1 < param_2); } return param_1; }

>>> s.call('decompile', name='grow_heads')['signature'], 3 ms. Output: 'int __cdecl grow_heads(int param_1,int param_2);'

Each tab is labelled with its source. Times are measured; nothing on this terminal is simulated.

One body, many heads

The heads come and go. The body stays.

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. When one is cut off, its locks are freed and its unsaved edits dropped, and the others never notice.

HEADS: clients>_agent harnessclient=triage>_agent harnessclient=renamer>_MCP serverparallel=true>_MCP serverone per agent label>_your scriptconnect()>_killed clientlocks freed, edits dropped✂BODY: one daemon per userHydra Engine daemonone JVM · loopback + tokenquick lanedecompile · functions · listlong laneanalyze · import · script● round-robin by client● 1 writer, many readers / program● per-client cancel● warm decompilers, shared● dead client: locks freedPROJECTS: opened in placefirmware.gprread-only view, no lockserver.exelibcrypto.dlltools.gprwritable, one ownerpatcher.exework.gprimports, dedup by SHA-256new.bin
Cut off one head and the body keeps going. Others connect.

What it does

Built for many agents on one machine

Inside, it is Ghidra: the same packages, modules and paths, so Ghidra scripts and extensions work unchanged. What Hydra Engine adds is one module, a shared session daemon, and a headless-only build. Features marked on main are in the repository but not yet in a release.

In the 12.3-hydra.1 release

  • in 12.3-hydra.1

    One shared daemon, fair lanes

    One JVM per user holds Ghidra, its projects, programs and warm decompilers. Quick requests and long ones (analyze, import, script, save) run in separate lanes, admitted round-robin by client, so one agent's whole-program analysis never stalls another's 10 ms query.

    Read more about One shared daemon, fair lanes
  • in 12.3-hydra.1

    Read-only views without a lock

    A project opens the way File > View Project does: no lock file, nothing written. Any number of clients, and a Ghidra window, can read it at the same time, without copying it first.

    Read more about Read-only views without a lock
  • in 12.3-hydra.1

    Upgrade cache: answers first

    A program saved by an older Ghidra opens at once, upgraded in memory, while an upgraded copy is built in the background, in the long lane and only when no client waits. Later opens read the copy; the project is never touched.

    Read more about Upgrade cache: answers first
  • in 12.3-hydra.1

    Imports once

    Any format a Ghidra loader accepts. A file whose SHA-256 is already in the project is never imported twice: the second import answers in milliseconds with the existing program.

    Read more about Imports once
  • in 12.3-hydra.1

    Scripts, contained

    Any GhidraScript, Java or Python, with arguments. On a program you do not own it runs inside a transaction that is always rolled back, so it cannot change what others see.

    Read more about Scripts, contained
  • in 12.3-hydra.1

    A dead client costs nobody else

    When a client disconnects or its process dies, its requests are cancelled, its unsaved changes discarded and logged, and its programs go back to read-only for the others.

    Read more about A dead client costs nobody else
  • in 12.3-hydra.1

    A headless build

    gradle buildHeadless leaves out the window-only modules, help, javadoc and Python stubs: a 639 MB install against 862 MB for the full build with the GUI, with byte-identical decompiled C on the binaries tested.

    Read more about A headless build
  • in 12.3-hydra.1

    Release assets with checksums

    Each release publishes the Windows x64 headless install as a zip, with a SHA256SUMS file built and tested by the release workflow on the unzipped install.

    Read more about Release assets with checksums

On main, for the next release

  • on main · next release

    Forks: copy-on-write working copies

    fork_project copies a project into a working copy while its source and read-only views stay open and in use: a block clone on ReFS (measured 204-225 ms for a 1.49 GB project), a full copy elsewhere.

    Read more about Forks: copy-on-write working copies
  • on main · next release

    Overlays: private hypotheses

    A client's own annotation view of a shared program: renames, labels, comments, signatures and types that nobody else sees and nothing saves, until promote_overlay replays them into a fork.

    Read more about Overlays: private hypotheses
  • on main · next release

    Shared writing

    Several clients write one program at once: each change its own transaction, journalled with its author; expect turns a lost update into a conflict that names the last editor.

    Read more about Shared writing
  • on main · next release

    Revision tokens and refresh

    Every project and program carries a revision. Answers flag a read-only view whose project another process saved (stale), and refresh reopens it for all its clients at once, under the same keys.

    Read more about Revision tokens and refresh
  • on main · next release

    A versioned client and the hello check

    hello and status report protocol, minClient, hydraVersion, ghidraVersion and installId; the client refuses an engine it does not fit, and releases ship it as hydra-client-<version>.zip.

    Read more about A versioned client and the hello check
  • on main · next release

    Per-request client and harness labels

    One MCP server serving several agents labels each request; busy and conflict answers, status and cancel then name the agent, not just the connection.

    Read more about Per-request client and harness labels
  • on main · next release

    Parallel imports, a visible queue

    Up to maxImports imports (default one per four CPUs, 1 to 4) load at once, into one project or several; the rest queue first-come, first-served, say who they wait behind with an estimate, and cancel cleanly.

    Read more about Parallel imports, a visible queue

Quick start

Running in a minute

You need a JDK 25 and Python 3.10 or later. Releases ship the headless install for Windows x64; on Linux and macOS, build it from source for now.

  1. 1. Download, check the SHA-256, unzip, start the daemon

    PowerShell
    Get-FileHash hydra-engine-12.3-hydra.1-win_x86_64.zip     # compare with SHA256SUMS
    Expand-Archive hydra-engine-12.3-hydra.1-win_x86_64.zip C:\tools
    $GS = "C:\tools\ghidra_12.3_DEV\Ghidra\Features\HeadlessSession\support\ghidra_session.py"
    python $GS ensure                                   # starts the daemon if it is not running
  2. 2. Ask it something

    PowerShell
    python $GS call open_project path=/re/MyProject     # read-only view, no lock
    python $GS call open_program path=target.exe
    python $GS call decompile address=rva:0x1000
    python $GS status                                   # projects, programs, clients, lanes, memory
  3. 3. Or connect from your harness

    Python
    import ghidra_session as gs
    
    with gs.connect(client="my-tool", harness="my-harness") as s:   # joins the daemon, or starts it
        s.call("open_project", path="/re/MyProject")                  # read-only, no lock
        s.call("open_program", path="target.exe")
        print(s.call("decompile", name="main")["c"])