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
- Wire format
- Requests
- Responses
- Events
- Addresses
- Projects, programs and keys
- Commands: session
- hello
- ping
- status
- cancel
- shutdown
- Commands: projects
- projects
- open_project
- project
- close_project
- refresh
- fork_project
- list
- Commands: programs
- open_program
- programs
- info
- close_program
- save
- Commands: reading
- functions
- decompile
- Commands: changing
- rename
- comment
- edit
- journal
- discard_edits
- analyze
- Commands: overlays
- apply_overlay
- overlays
- drop_overlay
- promote_overlay
- Commands: imports and scripts
- import
- script
- Error codes
- Holder details
- Launcher commands
- Configuration
- State directory
- Identity fields
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}| Field | Meaning |
|---|---|
id | Any JSON value, echoed in the response. Unique among the client's unanswered requests. |
cmd | The command. |
wait | Milliseconds the request may wait for a scheduler slot or a lock before it fails with busy. Default 10,000. |
parallel | true runs the request at once on its own thread. Without it, one client's requests run in the order sent. |
client, harness | Labels 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
| Code | When |
|---|---|
bad_request | The request is malformed or a field has the wrong type. |
unknown_command | No such cmd. |
unauthorized | The first request on a socket was not hello with the right token. |
no_project | No project selected, or this client has not joined it. |
no_program | No program selected. |
not_found | The project, program, function or overlay asked for does not exist. |
read_only | The program or project is open read-only for this client. |
not_owner | Another client owns the program writable, or it is shared and you are not one of its writers. |
busy | A slot or lock did not come free within wait. |
conflict | The 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_changes | Closing would drop unsaved changes. |
cancelled | Cancelled, or timed out. |
failed | Ghidra failed: its message, plus a short trace. |
Holder details
busy, conflict, not_owner and read_only carry these in error.details:
| Field | Meaning |
|---|---|
holder | One line, such as client 4 (agent-a, claude-code) analyze. |
holderInfo | client, name, harness, label, command, heldMs. For another process: user, host, since, os and live from Ghidra's lock file. |
holders | In a fork_project conflict: every client writing the source. |
project, gpr, program, path, sha256 | What the answer is about. |
suggest | retry, fork_project, open_read_only, open_program writable, share or reread. |
suggestion | With fork_project: a ready request. The path is only a proposal. |
alternatives, overlaySuggestion | On 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.
| Command | Does |
|---|---|
ensure | Starts the daemon if it is not running; prints its endpoint without the token. |
status | The 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. |
kill | Kills the daemon's JVM without a shutdown. |
version | This client's version, protocol and release; needs no daemon. |
serve | Runs 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. |
config | Prints 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.json | Environment | Default | Meaning |
|---|---|---|---|
java | GHIDRA_SESSION_JAVA_HOME | discovered | The JDK home. |
maxHeap | GHIDRA_SESSION_MAXMEM | a quarter of RAM, 2 to 31 GiB | -Xmx. |
minHeap | 512m | -Xms. | |
gc | GHIDRA_SESSION_GC | g1 | g1, zgc, parallel or default. |
vmargs | GHIDRA_SESSION_VMARGS | [] | Extra JVM options, last. |
tmpdir | GHIDRA_SESSION_TMPDIR | the JVM's | Where Ghidra keeps unsaved database buffers. A fast disk with room; on ReFS writing them is slower than on NTFS. |
mode | GHIDRA_SESSION_MODE | fast | fast builds the classpath itself and allows the AOT cache; standard is Ghidra's own launch. |
aot | GHIDRA_SESSION_AOT | auto | Use the AOT cache when one exists, or off. |
classCache | true | Reuse Ghidra's class search result while no jar changed. | |
idleTimeout | GHIDRA_SESSION_IDLE_TIMEOUT | 0 | Seconds without clients before the daemon exits; 0 stays up. |
keepWarm | GHIDRA_SESSION_KEEP_WARM | 3600 | Seconds an unused read-only program or project stays open. |
maxQuick | CPU count | Concurrent quick requests. | |
maxLong | CPUs / 4, at least 2 | Concurrent long requests. | |
maxImports | CPUs / 4, 1 to 4 | Concurrent imports. | |
scriptPath | [] | Extra GhidraScript directories. | |
log | <state>/<instance>.log | The daemon's log, rotated at 32 MiB. | |
upgradeCache | GHIDRA_SESSION_UPGRADE_CACHE | true | Serve older-format programs from an upgraded copy. |
upgradeCacheDir | GHIDRA_SESSION_UPGRADE_CACHE_DIR | <state>/upgrade-cache | Best on the same volume as the projects. |
forkCopyLimitMb | GHIDRA_SESSION_FORK_COPY_LIMIT_MB | 2048 | Largest 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.
| File | Purpose |
|---|---|
<instance>.json | The endpoint: protocol, pid, host, port, token, versions. Written once the daemon listens; removed at a clean exit. Owner-only. |
<instance>.lock | Held by the daemon for its whole life. A second daemon of the instance exits at once with code 3. |
<instance>.start.lock | Held while a launcher starts the daemon, so two launchers start one. |
<instance>.log | The daemon's log. |
Identity fields
What hello, status and the endpoint file report about the engine:
| Field | Meaning |
|---|---|
protocol | The wire protocol, an integer (2). Must match on both sides. |
minClient | The oldest client version this engine accepts, major.minor.patch. |
hydraVersion | The release, such as 12.3-hydra.2; 12.3-hydra.dev for a build from the source tree. |
ghidraVersion | The Ghidra version it is built on. |
installId | 16 hex digits, stable for one installation. |
startedAt, pid | When this daemon started, and its process. |
Checked against the engine on 2026-10-26. Every detail is in the README on GitHub.