Skip to content
Hydra Engine

Protocol and command reference

Lookup reference for the Hydra Engine daemon. The JSON-lines wire format, every command and its fields, error codes, launcher commands and configuration keys.

On this page

Protocol version 2. Every command has its own anchor, for example #decompile. Fields marked ? are optional; = gives the default. Commands marked on main · 12.3-hydra.2 are on main and not yet in a release.

Wire format

One JSON object per line, UTF-8, ending in \n, at most 64 MiB per line. On a socket, the first request must be hello with the endpoint's token.

Requests

{"id": 7, "cmd": "decompile", "program": "p1:/target.exe", "address": "rva:0x1000", "wait": 10000}
FieldMeaning
idAny JSON value, echoed in the response. Unique among the client's unanswered requests.
cmdThe command.
waitMilliseconds the request may wait for a scheduler slot or a lock before it fails with busy. Default 10,000.
paralleltrue runs the request at once on its own thread. Without it, one client's requests run in the order sent.
client, harnessLabels for this request alone (strings up to 128 characters). They replace the connection's names in holder fields, status, the import queue and the scope of cancel. on main · 12.3-hydra.2

Responses

{"id": 7, "ok": true, "result": {...}, "ms": 12}
{"id": 7, "ok": false, "error": {"code": "busy", "message": "...", "details": {...}}, "ms": 500}

A response may also carry stale (read-only views whose project another process saved) and refreshed (projects another client refreshed since this client last heard). See Projects and revisions.

Events

Events carry no ok. Long commands send throttled progress events with the request's id. On stdio the first line is ready, or fatal and exit code 2.

{"event": "progress", "id": 9, "message": "Analyzing...", "progress": 120, "maximum": 400}

Addresses

0x140001000, va:0x140001000, rva:0x1000 (from the image base), or space:offset. Results print addresses as 0x... in the default space.

Projects, programs and keys

open_project returns a project id (p1, p2, ...) and makes it the client's active project. A program's key is <project id>:<path in the project>, such as p1:/libs/version.dll. open_program makes the program active. The project field selects a project by id or path; program selects a program by key, or by path or unique name in the selected project. Without them, a command uses the active one.

Commands: session

hello

Fields: client, harness, clientVersion, token (on a socket). Names the client; on a socket it must come first. Answers the session's identity (protocol, minClient, hydraVersion, ghidraVersion, installId, startedAt, pid) and what status lists.

ping

Answers {"pong": true}.

status

The session's identity, launch info, memory, projects, programs (mode, owner, users, who holds each lock), clients and their unanswered requests (with progress, artifact and queue position), overlays, scheduler lanes, the import queue (imports), upgrade cache builds, and youAre, the label this request carried.

cancel

Fields: target (a request id of this client), or all: true, or cacheBuild (a build id, cache key, program key or path, or all). Cancels running or queued requests. With labels on the cancel, all reaches only that label's requests and target refuses another label's.

shutdown

Fields: force=false. Stops the session; unsaved changes are discarded. From a socket client it is refused while others are connected, unless force.

Commands: projects

projects

Open projects, which ones this client joined, and its active project.

open_project

Fields: path, writable=false, discard=false. Joins the project, opening it if needed. path is a .gpr, its folder, a .rep, or a parent folder with exactly one project at most two levels below. A writable open of a read-only view reopens it writable in place, with the same id and keys.

project

Fields: project?. The project: id, name, paths, writable, files, users, programs, revision, diskRevision, stale, generation, and fork (its sidecar) when it is a fork.

close_project

Fields: project?, discard=false. Leaves the project and closes this client's programs there. A writable project closes when its last user leaves; a read-only one after keepWarm.

refresh

on main · 12.3-hydra.2 Alias reopen. Fields: project?, force=false. Reopens a read-only view on what is saved now, for all its clients at once, under the same keys. An unchanged or writable project answers "refreshed": false with a reason.

fork_project

on main · 12.3-hydra.2 Fields: project (id or path), path, name?, writable=true, mode=auto (auto, copy-on-write, full), maxCopyMb?. Copies the project into a working copy for this client and opens it. Answers the new project id, method, cloned, bytes, files, copyMs, baseRevision and the sidecar path. See Several writers.

list

Fields: project?, folder="/", recursive=true, programsOnly=false, metadata=true, sha256?, offset, limit=1000. Folders and files, with key, sha256, language, format, executable and open (who uses it) for programs. sha256 finds a program by its hash. Paged, with truncated.

Commands: programs

open_program

Alias switch. Fields: path (path, unique name or key), project?, writable=false, share=false, overlay?, checkout=false, upgrade=false, wait. Opens the program, or joins it if open (warm ones included), and makes it active. Writable needs a writable project; a versioned file needs checkout. share: true opens it in shared mode; overlay opens this client's private overlay. "wait": true on an older-format program waits for its upgrade cache copy.

programs

This client's programs in all projects, and its active ones.

info

Fields: program?, overlay?. Key, language, compiler, image base, format, executable path, SHA-256, MD5, function count, analysed, changed, mode, owner, users, revision, projectRevision, generation, and this client's overlays.

close_program

Fields: program?, discard=false. Drops this client's use. The owner of a changed program must save first or pass discard.

save

Fields: program?, comment?. Saves the program, everyone's changes on a shared one. Owner or shared writers only. Answers revision, projectRevision and savedSeq.

Commands: reading

functions

Fields: program?, contains?, regex?, offset, limit=200 (at most 10,000), overlay?. Functions by name filter, paged.

decompile

Fields: program?, address or name, timeout=60 (seconds), maxChars=200000, overlay?. C text and signature. Decompilers are pooled per program and per overlay, so warm calls skip the decompiler's start.

Commands: changing

rename

Fields: program?, address, name, kind=auto (auto, function, label), expect?, overlay?. Renames the function at the address, or creates or renames the primary label. Owner or shared writers only, or in the client's overlay. Answers old, created and the journal seq.

comment

Fields: program?, address, text (null clears), type=eol (eol, pre, post, plate, repeatable), expect?, overlay?. Same rules as rename.

edit

on main · 12.3-hydra.2 Fields: program?, ops. Applies rename, label, comment, signature and data_type operations in one transaction, all or none, journalled. The first three take an optional expect.

journal

on main · 12.3-hydra.2 Fields: program?, since, author, limit. Who changed what in a writable program, in commit order: seq, at, client, name, harness, cmd, op, address, old, new.

discard_edits

on main · 12.3-hydra.2 Fields: program?, author. Reverts that client's unsaved renames, labels and comments, newest first. What others changed since is kept and listed in skipped.

analyze

Fields: program?, options (name: value), ranges ([[start, end], ...]), timeout (seconds). Sets analysis options, then runs auto-analysis on everything or on what the ranges trigger, the way analyzeHeadless does. Owner or shared writers only; journalled.

Commands: overlays

on main · 12.3-hydra.2 An overlay is opened with open_program and overlay. Names are 1 to 64 letters, digits, ., _, - or @, and belong to one client.

apply_overlay

Fields: program?, overlay, ops. Applies rename (address, name, kind), label (address, name), comment (address, text, type), signature (address, a C prototype) and data_type (address, type such as int, char[16] or MyStruct *), all or none, and logs them. A failure names the operation's index and answers rolledBack: true.

overlays

This client's overlays: name, program, overlayVersion, ops, sha256, revisions, stale, error.

drop_overlay

Fields: program?, overlay. Drops the overlay.

promote_overlay

Fields: program?, overlay, project or fork (the fork_project fields), path?, save=true. Replays the overlay's log into a writable copy of the program, in a project this client holds writable or in a new fork, after checking it is the same build by SHA-256. The overlay stays.

Commands: imports and scripts

import

Fields: file, project?, folder="/", name?, language?, compiler?, analyze=false, duplicate=false, timeout?. Imports into a writable project, saves, and opens the program writable for this client. A file whose SHA-256 is already there answers {"imported": false, "existing": [...]} unless duplicate. Queued imports report queue and progress; see Imports.

script

Fields: script (a name on the script path, or a path), args, program? (null: none), project?, address?, exclusive=false, save=false, timeout?, maxChars, artifact?. Runs a GhidraScript and answers its printed output (truncated), its mode (owner or contained), changed and unsaved. See Scripts and exports.

Error codes

CodeWhen
bad_requestThe request is malformed or a field has the wrong type.
unknown_commandNo such cmd.
unauthorizedThe first request on a socket was not hello with the right token.
no_projectNo project selected, or this client has not joined it.
no_programNo program selected.
not_foundThe project, program, function or overlay asked for does not exist.
read_onlyThe program or project is open read-only for this client.
not_ownerAnother client owns the program writable, or it is shared and you are not one of its writers.
busyA slot or lock did not come free within wait.
conflictThe project cannot be given to you as asked: another process's lock, a value changed since you read it, a needed upgrade not allowed, an ambiguous name, a fork that cannot start. Retrying does not help.
unsaved_changesClosing would drop unsaved changes.
cancelledCancelled, or timed out.
failedGhidra failed: its message, plus a short trace.

Holder details

busy, conflict, not_owner and read_only carry these in error.details:

FieldMeaning
holderOne line, such as client 4 (agent-a, claude-code) analyze.
holderInfoclient, name, harness, label, command, heldMs. For another process: user, host, since, os and live from Ghidra's lock file.
holdersIn a fork_project conflict: every client writing the source.
project, gpr, program, path, sha256What the answer is about.
suggestretry, fork_project, open_read_only, open_program writable, share or reread.
suggestionWith fork_project: a ready request. The path is only a proposal.
alternatives, overlaySuggestionOn not_owner: ["overlay", "fork_project"] and a ready open_program request for an overlay.

Launcher commands

python ghidra_session.py <command>. Each command is its own client: a project opened by one call is not open for the next.

CommandDoes
ensureStarts the daemon if it is not running; prints its endpoint without the token.
statusThe running daemon's status.
call CMD key=value ...One request; values are parsed as JSON when they parse (writable=true).
stop [--force]Asks the daemon to shut down; refused while other clients are connected unless --force.
killKills the daemon's JVM without a shutdown.
versionThis client's version, protocol and release; needs no daemon.
serveRuns the daemon in the foreground, for a service manager.
stdio [ARGS...]A private session on stdin and stdout: no daemon, no socket.
aot [--project P] [--program X]Builds the AOT cache (JDK 25 or later).
command [ARGS...]Prints the Java command line it would run.
configPrints the effective configuration, the JDK and the install.

Global options: --ghidra, --state, --instance, --java, --max-heap, --gc, --mode, --tmpdir.

Exit codes: 2 a launch error, 3 a session error (the daemon refused the request), 4 an incompatible daemon.

Configuration

Lowest to highest: defaults, <state>/config.json, environment, command-line options. config prints the result.

config.jsonEnvironmentDefaultMeaning
javaGHIDRA_SESSION_JAVA_HOMEdiscoveredThe JDK home.
maxHeapGHIDRA_SESSION_MAXMEMa quarter of RAM, 2 to 31 GiB-Xmx.
minHeap512m-Xms.
gcGHIDRA_SESSION_GCg1g1, zgc, parallel or default.
vmargsGHIDRA_SESSION_VMARGS[]Extra JVM options, last.
tmpdirGHIDRA_SESSION_TMPDIRthe JVM'sWhere Ghidra keeps unsaved database buffers. A fast disk with room; on ReFS writing them is slower than on NTFS.
modeGHIDRA_SESSION_MODEfastfast builds the classpath itself and allows the AOT cache; standard is Ghidra's own launch.
aotGHIDRA_SESSION_AOTautoUse the AOT cache when one exists, or off.
classCachetrueReuse Ghidra's class search result while no jar changed.
idleTimeoutGHIDRA_SESSION_IDLE_TIMEOUT0Seconds without clients before the daemon exits; 0 stays up.
keepWarmGHIDRA_SESSION_KEEP_WARM3600Seconds an unused read-only program or project stays open.
maxQuickCPU countConcurrent quick requests.
maxLongCPUs / 4, at least 2Concurrent long requests.
maxImportsCPUs / 4, 1 to 4Concurrent imports.
scriptPath[]Extra GhidraScript directories.
log<state>/<instance>.logThe daemon's log, rotated at 32 MiB.
upgradeCacheGHIDRA_SESSION_UPGRADE_CACHEtrueServe older-format programs from an upgraded copy.
upgradeCacheDirGHIDRA_SESSION_UPGRADE_CACHE_DIR<state>/upgrade-cacheBest on the same volume as the projects.
forkCopyLimitMbGHIDRA_SESSION_FORK_COPY_LIMIT_MB2048Largest full copy fork_project makes in auto mode.

State directory

--state, else GHIDRA_SESSION_HOME, else %LOCALAPPDATA%\GhidraSession on Windows, ~/Library/Application Support/GhidraSession on macOS, and $XDG_STATE_HOME/ghidra-session or ~/.local/state/ghidra-session on Linux.

FilePurpose
<instance>.jsonThe endpoint: protocol, pid, host, port, token, versions. Written once the daemon listens; removed at a clean exit. Owner-only.
<instance>.lockHeld by the daemon for its whole life. A second daemon of the instance exits at once with code 3.
<instance>.start.lockHeld while a launcher starts the daemon, so two launchers start one.
<instance>.logThe daemon's log.

Identity fields

What hello, status and the endpoint file report about the engine:

FieldMeaning
protocolThe wire protocol, an integer (2). Must match on both sides.
minClientThe oldest client version this engine accepts, major.minor.patch.
hydraVersionThe release, such as 12.3-hydra.2; 12.3-hydra.dev for a build from the source tree.
ghidraVersionThe Ghidra version it is built on.
installId16 hex digits, stable for one installation.
startedAt, pidWhen this daemon started, and its process.

Checked against the engine on 2026-10-26. Every detail is in the README on GitHub.