# ImHex Admin & Developer Guide

This guide is the deep reference for people who build, package, extend, deploy,
or operate ImHex: system architects, plugin developers, packagers, and power
users. It documents ImHex's architecture, the `libimhex` SDK and `ContentRegistry`
extension surface, the event system, the build and compile pipeline,
configuration, security posture, operations, and a code-quality and improvement
analysis.

End-user installation and feature usage live in the companion **User Guide**;
this document assumes that material and focuses on internals.

> [!NOTE]
> ImHex is GPLv2-licensed overall, with two components under **LGPLv2.1** to
> permit proprietary plugins: `lib/libimhex` (the plugin interface library) and
> `plugins/ui` (shared UI elements). This split is deliberate — see
> [§9 Security & Licensing](#9-security-licensing).

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [Architecture Overview](#2-architecture-overview)
3. [Repository Structure](#3-repository-structure)
4. [Process Model & Startup](#4-process-model--startup)
5. [The libimhex SDK](#5-the-libimhex-sdk)
6. [The ContentRegistry: Extension Surface](#6-the-contentregistry-extension-surface)
7. [The Event System](#7-the-event-system)
8. [Plugins Inventory](#8-plugins-inventory)
9. [Security & Licensing](#9-security--licensing)
10. [Building & Compiling](#10-building--compiling)
11. [Plugin Development](#11-plugin-development)
12. [Scripting (C# / .NET and C)](#12-scripting-c--net-and-c)
13. [The MCP Server](#13-the-mcp-server)
14. [Configuration Reference](#14-configuration-reference)
15. [Filesystem & Path Resolution](#15-filesystem--path-resolution)
16. [Operations](#16-operations)
17. [Code Quality & Conventions](#17-code-quality--conventions)
18. [Testing](#18-testing)
19. [Potential Improvements & Tech Debt](#19-potential-improvements--tech-debt)
20. [Quick Reference](#20-quick-reference)

---

## 1. Executive Summary

ImHex is a cross-platform **hex editor and binary-analysis platform** written in
modern **C++ (C++23)**. Architecturally it is not a monolith but a small native
core (`main`) plus a **plugin runtime** (`libimhex`) that loads feature plugins
as shared libraries at startup. Almost every user-facing capability — the hex
editor view, the Pattern Language integration, hashing, diffing, disassembly,
YARA, visualizers, the script loader, OS integrations — lives in a plugin that
registers itself through a central **ContentRegistry** and communicates via a
decoupled **EventManager**.

Key design properties:

| Property | How it's realized |
|----------|-------------------|
| **Extensibility** | Plugins are shared libs discovered at runtime; everything user-facing is registered through `ContentRegistry` |
| **Decoupling** | Components never call each other directly — they post/subscribe to typed events via `EventManager` |
| **Provider abstraction** | All features operate on a `prv::Provider` byte source (file, disk, memory, GDB, remote…) |
| **Portability** | One codebase targets Windows, macOS, Linux, FreeBSD, and WebAssembly (Emscripten) |
| **Resilience** | Crash handlers capture stack traces, save a crash-backup project, and run cleanup hooks |
| **GUI** | Dear ImGui (immediate-mode) rendered via OpenGL 3.0+ |

The codebase analyzed here is commit `8a6be85` (2026-05-30): ~796 files,
~1.05 M characters of source, 474 code files, organized into a core library, a
GUI host, an updater, a Windows forwarder, and ~13 plugins.

---

## 2. Architecture Overview

```
                        ┌─────────────────────────────────────────────┐
                        │                  Executables                 │
                        │                                              │
  Explorer / Terminal ─▶│  imhex.exe (forwarder, Windows only)         │
                        │      └─ launches ──▶ imhex-gui (main host)   │
                        │  imhex-updater  (standalone updater)         │
                        └───────────────────────┬──────────────────────┘
                                                 │
                  ┌──────────────────────────────▼───────────────────────────┐
                  │                  main/gui  (host process)                  │
                  │  • main(): locale, TaskManager, crash handlers, native    │
                  │    init, messaging, CLI dispatch, then runImHex()          │
                  │  • Window: GLFW + OpenGL + Dear ImGui render loop          │
                  └──────────────────────────────┬───────────────────────────┘
                                                 │ links
                  ┌──────────────────────────────▼───────────────────────────┐
                  │              lib/libimhex  (the SDK / runtime)             │
                  │                                                            │
                  │   PluginManager   ContentRegistry   EventManager          │
                  │   TaskManager     ImHexApi          ShortcutManager        │
                  │   ThemeManager    LayoutManager     WorkspaceManager       │
                  │   LocalizationMgr AchievementMgr    TutorialManager        │
                  │   ProjectFile     prv::Provider     MCP server             │
                  └───┬───────────┬───────────┬───────────┬───────────┬────────┘
                      │ loads     │ loads      │ loads      │ loads     │ loads
                  ┌───▼───┐  ┌────▼────┐  ┌────▼────┐  ┌────▼────┐  ┌───▼─────┐
                  │builtin│  │ hashes  │  │disassem.│  │  yara   │  │ ...etc  │
                  │plugin │  │ plugin  │  │ plugin  │  │ plugin  │  │ plugins │
                  └───────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘
```

The flow at runtime:

1. The **host** (`main/gui`) starts, sets up the `TaskManager`, crash handlers,
   and native window, then asks `PluginManager` to load libraries and plugins.
2. Each **plugin**, on init, **registers content** (views, tools, data inspector
   rows, hashes, providers, menu items, settings, pattern functions, …) into the
   `ContentRegistry`, and **subscribes to events** it cares about.
3. The **render loop** draws registered views with Dear ImGui every frame,
   dispatches shortcuts, and posts frame events.
4. Features interact only through **events** (`EventManager`) and the shared
   **provider** byte source — never by direct cross-plugin calls.

> [!NOTE]
> This is a classic **registry + event-bus** plugin architecture. Adding a
> feature means writing a plugin that registers entries and subscribes to events
> — no core changes required. That is the single most important fact for anyone
> extending ImHex.

---

## 3. Repository Structure

| Path | Purpose |
|------|---------|
| `main/gui/` | The GUI host executable: `main()`, window/render loop, init tasks, crash handlers, messaging, CLI entry |
| `main/forwarder/` | Windows-only launcher that manages the console window and forwards stdio to `imhex-gui` |
| `main/updater/` | Standalone cross-platform updater executable |
| `lib/libimhex/` | The SDK: public headers (`include/hex/...`) + implementation (`source/...`). The LGPL plugin interface |
| `lib/trace/` | Stack-trace / exception-tracing helper library |
| `plugins/builtin/` | The default plugin — most core ImHex functionality (views, tools, providers, CLI) |
| `plugins/ui/` | Shared UI widgets and the pattern text editor (LGPL, so plugins can reuse it) |
| `plugins/hashes/` | Hashing algorithms and the Hashes view |
| `plugins/disassembler/` | Capstone-based disassembler and views |
| `plugins/yara_rules/` | YARA scanning integration |
| `plugins/diffing/` | Data diffing algorithms and view |
| `plugins/decompress/` | Decompression support for the data processor |
| `plugins/visualizers/` | Pattern Language visualizers (images, audio, 3D, …) |
| `plugins/remote/` | Remote (SSH/SFTP) and network providers |
| `plugins/fonts/` | Font loading and management |
| `plugins/windows/` | Windows-specific integrations |
| `plugins/script_loader/` | Loads .NET (C#) and C scripts as content |
| `cmake/` | Build modules, the plugin SDK template, toolchain helpers |
| `dist/` | Packaging, dependency installer scripts, compiling guides, vcpkg manifest |
| `resources/` | Logos, banners, sample projects |
| `tests/` | Unit/integration tests (`common`, `helpers`, `algorithms`, `plugins`) |

Each plugin follows the same internal shape: `source/` (implementation),
`include/` (its own headers), and `romfs/` (embedded resources: localization
`lang/`, themes, shaders, MCP tool definitions, etc.) baked into the binary via a
ROM-filesystem mechanism.

---

## 4. Process Model & Startup

### Executables

ImHex ships **three** executables:

- **`imhex-gui`** — the real application (the host + plugins).
- **`imhex`** (Windows forwarder) — works around a Windows limitation: a GUI app
  launched from Explorer would otherwise get a stray console window, while a
  console app would always allocate one. The forwarder calls `FreeConsole()`
  when launched from Explorer (hiding the console) and enables ANSI escape
  sequences when launched from a terminal, then spawns `imhex-gui.exe`, wiring
  stdio through pipes and a Job Object so the child dies with the parent. It sets
  `__IMHEX_FORWARD_CONSOLE__=1` to tell the GUI to forward its console output.
- **`imhex-updater`** — downloads and installs updates (see [§16](#16-operations)).

> [!NOTE]
> The forwarder exists purely because Windows lacks a "console-like GUI app"
> subsystem. On macOS/Linux a single executable behaves correctly, so there is
> no forwarder there.

### `main()` sequence (host)

From `main/gui/source/main.cpp`, startup runs in this order:

1. `setlocale(LC_ALL, "en_US.utf8")`.
2. `TaskManager::setMainThreadId(...)` and name the main thread (`"ImHex 🔍"`).
3. `crash::setupCrashHandlers()` — install signal/exception handlers **first**,
   to catch early crashes.
4. `trace::enableExceptionCaptureForCurrentThread()`.
5. `Window::initNative()` — platform window init.
6. `messaging::setupMessaging()` — single-instance / inter-instance messaging.
7. If `argc > 1`: disable the crash callback and run `init::runCommandLine()`.
8. Log version, commit, and OS/arch info (so user-submitted logs are useful).
9. `init::runImHex()` — enter the render loop.

### CLI dispatch

`runCommandLine()` (in `main/gui/source/init/run/cli.cpp`) loads plugin
**libraries** and plugins (without initializing them), then calls
`hex::subcommands::processArguments(args)`. Subcommands are matched against the
`--long` / `-short` names registered by each plugin via `IMHEX_PLUGIN_SUBCOMMANDS`.
On Windows the raw UTF-16 command line is re-parsed with `CommandLineToArgvW` and
converted to UTF-8. Plugins are intentionally **not** unloaded after CLI handling
— some CLI commands configure plugin state and then let ImHex start normally.

### Crash handling

`main/gui/source/crash_handlers.cpp` installs handlers for `SIGSEGV`, `SIGILL`,
`SIGABRT`, `SIGFPE` (and `SIGINT`, `SIGBUS` where present); on Windows it uses
`SetUnhandledExceptionFilter` mapping structured exceptions to the same path. On
a crash it:

- Posts `EventAbnormalTermination` so plugins can clean up.
- Exports the current workspace and, if any provider is open, writes a
  `crash_backup.hexproj` to a writable config path.
- Writes `crash.json` (pointing at the log file and the backup project).
- Prints a demangled stack trace and runs exit tasks, then terminates.

The crash callback starts as a native message box (for very early failures) and
is swapped to the file-saving handler once `EventImHexStartupFinished` fires.

---

## 5. The libimhex SDK

`lib/libimhex` is the LGPL library that both the host and every plugin link
against. Public headers live under `include/hex/`. The major managers (all static
"manager" classes, deliberately non-instantiable) are:

| Class / namespace | Responsibility |
|-------------------|----------------|
| `PluginManager` | Discover, load (`load`/`loadLibraries`), initialize, enable/disable, and unload plugins; expose plugin metadata and subcommands |
| `ContentRegistry` | The registration surface for all extensible content (see [§6](#6-the-contentregistry-extension-surface)) |
| `EventManager` | Typed publish/subscribe event bus (see [§7](#7-the-event-system)) |
| `TaskManager` | Async/background/blocking task scheduling, deferred (`doLater`) calls, thread naming |
| `ImHexApi` | Runtime facade: `System`, `Provider`, `HexEditor`, `Bookmarks`, etc. |
| `ShortcutManager` | Global and view-local keyboard shortcuts, remapping, macOS mode |
| `ThemeManager` | Load/apply themes, color & style handlers, accent color, export |
| `LayoutManager` | Save/load/lock window layouts (ImGui docking state) |
| `WorkspaceManager` | Create/switch/import/export workspaces |
| `LocalizationManager` (`Lang`/`UnlocalizedString`) | Translation lookup; compile-time `"..."_lang` hashing |
| `AchievementManager` | Achievement graph (requirements/visibility), progress persistence |
| `TutorialManager` | Interactive tutorials (steps, highlights, message boxes) |
| `ProjectFile` | Load/store `.hexproj` projects; per-provider and global handlers |
| `prv::Provider` | Abstract byte source interface every feature reads/writes |

### Localization & `UnlocalizedString`

A recurring pattern: APIs take **`UnlocalizedString`** keys, not display text.
ImHex resolves them through `LocalizationManager` at draw time. The `_lang`
user-defined literal computes a hash at compile time for fast lookup. This is why
plugin code is full of identifiers like `hex.builtin.view.hex_editor.name` — the
human-readable strings live in each plugin's `romfs/lang/*.json`.

### TaskManager

Tasks come in three flavors: **foreground** (shown in the footer task list),
**background** (hidden), and **blocking** (modal). `Task` objects support
progress (`update`/`setMaxValue`), cooperative interruption
(`interrupt`/`shouldInterrupt`), and exception capture. `doLater` and
`doLaterOnce` defer work to the start of the next frame on the main thread —
essential because the GUI is immediate-mode and most state must be touched on the
main thread.

> [!IMPORTANT]
> When extending ImHex, never block the render thread. Long operations belong in
> `TaskManager::createTask(...)`; UI mutations from worker threads must be routed
> back via `TaskManager::doLater(...)`.

---

## 6. The ContentRegistry: Extension Surface

`ContentRegistry` (implemented in `lib/libimhex/source/api/content_registry.cpp`)
is the single namespace through which plugins add functionality. Each
sub-namespace owns a registry of entries plus `add(...)` functions. The full set:

| Namespace | Registers… |
|-----------|------------|
| `Settings` | Setting categories, sub-categories, and widgets; `onChange`/`onSave` hooks; persistence to `settings.json` |
| `CommandPalette` | Command-palette entries and handlers |
| `PatternLanguage` | Pattern Language functions, dangerous functions, types, pragmas, and (inline) visualizers; owns the per-provider runtime |
| `Views` | Dockable windows (the UI views), plus the fullscreen view slot |
| `Tools` | Entries in the Tools panel |
| `DataInspector` | Data Inspector row types (generator + optional editor) |
| `DataProcessor` | Node types for the node graph |
| `UserInterface` | Main-menu items, toolbar items, sidebar items, footer items, welcome-screen entries, title-bar buttons, taskbar menu items |
| `Provider` | Data-source provider types (creation functions + names) |
| `DataFormatter` | "Copy as / export as" formatters and find-result exporters |
| `FileTypeHandler` | Handlers keyed by file extension |
| `HexEditor` | Data visualizers and minimap visualizers for the hex grid |
| `Diffing` | Diff algorithms |
| `Hashes` | Hash algorithm implementations |
| `BackgroundServices` | Long-running background services |
| `CommunicationInterface` | External communication endpoints |
| `DataInformation` | Data Information analyzers (entropy, distribution, …) |
| `Disassemblers` | Disassembler backends |
| `Experiments` | Experimental, opt-in features |
| `Reports` | Report generators |

Registration is uniform: a plugin calls e.g.
`ContentRegistry::Hashes::add(std::make_unique<MyHash>())` or
`ContentRegistry::Views::add(...)` during its init function. Many `add` calls
`log::debug(...)` the registration, so running with `--verbose` prints a complete
inventory of what each plugin contributed — invaluable for debugging missing
content.

### Settings widgets

The settings system ships reusable widget types: `Checkbox`, `SliderInteger`,
`SliderFloat`, `SliderDataSize`, `ColorPicker`, `DropDown`, `TextBox`,
`FilePicker`, `Label`, and `Spacer`. Each implements `draw`/`load`/`store`
against `nlohmann::json`. Settings persist to `settings.json` in a config path;
on the Web build they persist to browser `localStorage` instead.

### The Pattern Language runtime

`ContentRegistry::PatternLanguage` owns a **per-provider** `pl::PatternLanguage`
runtime. On creation it wires the runtime's data source to the provider's
read/write, sets include paths from the `includes`/`patterns` data folders,
registers all plugin-contributed functions/types/pragmas, and defines `__IMHEX__`
and `__IMHEX_VERSION__`. "Dangerous" functions (those with side effects beyond
reading) are registered separately and gated.

> [!CAUTION]
> Pattern Language **dangerous functions** can perform side-effectful operations.
> They are registered via `addDangerousFunction` and treated distinctly from pure
> functions. Be deliberate about which capabilities a plugin exposes to
> user-supplied pattern code.

---

## 7. The Event System

`EventManager` is a typed publish/subscribe bus. Events are declared with the
`EVENT_DEF(Name, ParamTypes...)` macro (or `EVENT_DEF_NO_LOG` for high-frequency
events like per-frame ticks), which generates a struct with static
`subscribe`/`unsubscribe`/`post` methods. Event identity is a compile-time FNV
hash of the event name; handlers are stored in a `multimap` keyed by that id.

Conventions:

- Events live in category headers under `include/hex/api/events/`
  (`events_gui.hpp`, `events_lifecycle.hpp`, `events_provider.hpp`,
  `events_interaction.hpp`) — never declared inline elsewhere.
- **Events** (`EventXxx`) broadcast that something happened; **Requests**
  (`RequestXxx`) ask something to happen.
- Subscriptions can be **token-based** (pass a `void*` owner token) so a plugin
  can unsubscribe all its handlers at unload.
- In release builds, event callbacks are wrapped in try/catch and log the
  exception (then rethrow); in debug builds they run unguarded for easier
  debugging.

Representative events (non-exhaustive):

| Category | Examples |
|----------|----------|
| Lifecycle | `EventImHexStartupFinished`, `EventImHexClosing`, `EventFirstLaunch`, `EventImHexUpdated`, `EventAbnormalTermination`, `EventCrashRecovered` |
| Provider | `EventProviderCreated`, `EventProviderOpened`, `EventProviderChanged`, `EventProviderClosed`, `EventProviderDataModified`, `EventProviderDirtied` |
| Interaction | `EventDataChanged`, `EventRegionSelected`, `EventBookmarkCreated`, `EventPatchCreated`, `EventPatternExecuted`, `EventFileDropped` |
| GUI | `EventViewOpened`, `EventDPIChanged`, `EventWindowClosing`, `EventFrameBegin`/`EventFrameEnd`, `EventThemeChanged` |
| Requests | `RequestOpenFile`, `RequestOpenWindow`, `RequestCreateProvider`, `RequestHexEditorSelectionChange`, `RequestSetPatternLanguageCode`, `RequestCloseImHex`, `RequestRestartImHex` |

> [!NOTE]
> The in-source documentation candidly flags several events as unused
> (`FIXME: this event is unused and should be scrapped`). Treat the
> `events_*.hpp` headers as the source of truth, but don't assume every declared
> event has a live publisher.

### Example: how a feature wires up

The introduction tutorial (`plugins/builtin/.../tutorials/introduction.cpp`)
illustrates the idioms: it builds a `TutorialManager` tutorial with steps that
highlight named UI elements (by their localized window names), and advances steps
by subscribing to events like `EventProviderOpened` and `EventViewOpened`. UI
elements are addressed by stable string IDs, and pattern code is injected with
`RequestSetPatternLanguageCode::post(...)` followed by
`RequestTriggerPatternEvaluation::post()`.

---

## 8. Plugins Inventory

| Plugin | Role | Notes |
|--------|------|-------|
| `builtin` | The bulk of ImHex: hex editor view, data inspector, find/replace, bookmarks, patches, providers, the CLI subcommands, settings, tutorials | Largest plugin; author WerWolv |
| `ui` | Shared UI widgets + pattern text editor | **LGPL** so other (incl. proprietary) plugins can reuse it |
| `hashes` | All hash algorithms + Hashes view | See User Guide for the full algorithm list |
| `disassembler` | Capstone disassembler + views | Pluggable architectures |
| `yara_rules` | YARA scanning | Rules from `yara/` data folder + Content Store |
| `diffing` | Data diffing (edit-distance based) | Table + highlight diff views |
| `decompress` | Decompression nodes | Feeds the data processor |
| `visualizers` | Pattern visualizers | Images, audio, 3D models, coordinates, shaders |
| `remote` | Remote/network providers | SSH/SFTP, UDP, etc. |
| `fonts` | Font loading | Bundled and custom fonts |
| `windows` | Windows-only integrations | Taskbar progress, etc. |
| `script_loader` | Load C# (.NET) and C scripts as content | See [§12](#12-scripting-c--net-and-c) |

Plugins are distinguished as **library plugins** (shared infrastructure like
`ui`, loaded via `loadLibraries`) versus **feature plugins** (loaded via `load`).
A plugin exports a fixed set of C functions (`getPluginName`, `initializePlugin`,
`getSubCommands`, `getFeatures`, `getCompatibleVersion`, …) that `PluginManager`
resolves by symbol — defined for you by the `IMHEX_PLUGIN_SETUP` macros.

---

## 9. Security & Licensing

### Licensing

| Component | License | Why |
|-----------|---------|-----|
| ImHex (most of it) | **GPLv2-only** | Copyleft for the application |
| `lib/libimhex` | **LGPLv2.1** | Lets proprietary plugins link the SDK |
| `plugins/ui` | **LGPLv2.1** | Lets proprietary plugins reuse UI elements |
| `plugins/ui/.../text_editor` | **MIT** (BalazsJako) | Vendored ImGuiColorTextEdit |

### Code signing

Windows builds are signed via **SignPath.io** (certificate by the SignPath
Foundation). ImHex's stated policy: it "will not transfer any information to
other networked systems unless specifically requested by the user or the person
installing or operating it." Push access to the repository is limited to a small
named set of maintainers.

### Network behavior

ImHex only reaches the network on explicit user action. Network touchpoints to be
aware of when assessing or sandboxing it:

- **Updater** — fetches release metadata from the GitHub API and downloads
  artifacts.
- **Content Store** — downloads patterns/magic/rules/themes from the
  ImHex-Patterns repo.
- **Remote providers** — SSH/SFTP, UDP, GDB, process memory.
- **Tools** — the HTTP Requests and TCP Client/Server tools, the Wikipedia tool,
  and the `--save-editor gist` command (GitHub Gist API).

> [!WARNING]
> ImHex is a **reverse-engineering tool routinely pointed at untrusted binaries
> and malware**. Run it in an isolated VM when analyzing hostile samples.
> Note these capability surfaces:
> - **Pattern Language dangerous functions** and **scripts** (C#/.NET, C) can
>   execute side-effectful logic — only run patterns/scripts you trust.
>   YARA-style sources can be embedded in downloadable content.
> - **Process Memory / GDB / Raw Disk** providers touch live system state and
>   may need elevated privileges.
> - The **updater** runs platform installers with elevated privileges
>   (`msiexec`, `sudo`, `zenity` password prompts) and on macOS uses AppleScript
>   `with administrator privileges`. Prefer OS package managers in managed
>   environments and pin the update channel.

### MCP exposure

The MCP server binds an **internal loopback port (`19743`)** for a local stdio
bridge (`imhex --mcp`), not a remote service. Still, treat it as a control
channel: anything able to drive that bridge can drive ImHex.

---

## 10. Building & Compiling

### Toolchain requirements

| Requirement | Detail |
|-------------|--------|
| Compiler | **GCC or Clang with C++23 support** (latest GCC for Windows/Linux, latest LLVM Clang for macOS) |
| CMake | **≥ 3.20** |
| Generator | **Ninja** (default in presets) |
| Submodules | Many deps are bundled as git submodules |

> [!IMPORTANT]
> **MSVC and AppleClang are NOT supported** — both lack C++23 features ImHex
> relies on. Use GCC/LLVM Clang even on Windows/macOS. Clone with
> `--recurse-submodules`; non-bundled dependencies install via the scripts in
> `/dist`.

### CMake presets

`CMakePresets.json` defines configure presets (CMake ≥ 3.20, Ninja, Debug by
default):

| Preset | Purpose |
|--------|---------|
| `base` | Hidden base: GCC/G++, `IMHEX_PATTERNS_PULL_MASTER=ON`, `USE_SYSTEM_CAPSTONE=ON`, `IMHEX_USE_DEFAULT_BUILD_SETTINGS=ON`, install prefix `./install` |
| `x86_64` | Standard x86-64 build (inherits `base`) |
| `xcode` | macOS Xcode generator with Clang overrides |
| `vs2022` / `vs2022-x86` | Visual Studio environments using the **vcpkg** toolchain (`VCPKG_MANIFEST_DIR=dist`) |

A typical Linux/macOS build:

```bash
git clone --recurse-submodules https://github.com/WerWolv/ImHex
cd ImHex
cmake --preset x86_64
cmake --build build/x86_64 --target imhex_all
```

The `imhex_all` build target is wired in the `x86_64` build preset. Per-platform
instructions live in `dist/compiling/{windows,linux,macos}.md`.

### Notable CMake options

| Option | Effect |
|--------|--------|
| `IMHEX_BUNDLE_PLUGIN_SDK=ON` | Install the plugin SDK (for out-of-tree plugin dev) |
| `USE_SYSTEM_CAPSTONE=ON` | Link the system Capstone instead of bundled |
| `IMHEX_PATTERNS_PULL_MASTER=ON` | Pull the latest patterns database during build |
| `IMHEX_USE_DEFAULT_BUILD_SETTINGS=ON` | Apply the project's standard build flags |

---

## 11. Plugin Development

ImHex is built to be extended out-of-tree. The workflow:

1. Start from the **[ImHex Plugin Template](https://github.com/WerWolv/ImHex-Plugin-Template)**.
2. **Get the SDK.** Build ImHex with the SDK bundled and install it:
   ```bash
   cmake -G Ninja -DIMHEX_BUNDLE_PLUGIN_SDK=ON -B build
   cd build
   DESTDIR=install ninja install
   ```
   The SDK lands at `install/usr/local/share/imhex/sdk`. Point the
   `IMHEX_SDK_PATH` variable at that absolute path.
3. In CI, use the [imhex-download-sdk action](https://github.com/WerWolv/imhex-download-sdk)
   to fetch a matching SDK automatically.
4. In your plugin's init, **register content** via `ContentRegistry::*::add(...)`
   and **subscribe to events** via `EventXxx::subscribe(...)`.
5. **Validate** the built plugin before shipping:
   ```bash
   imhex --validate-plugin /path/to/your_plugin.hexplug
   ```
   This checks the plugin loads, has a valid setup block, and initializes.

> [!IMPORTANT]
> A plugin must be built against the **same ImHex version's SDK**. The
> `getCompatibleVersion` export lets `PluginManager` reject mismatched plugins —
> which is exactly what `--validate-plugin` surfaces ("make sure the plugin was
> built using the SDK of this ImHex version"). A plugin missing its
> `IMHEX_PLUGIN_SETUP`/`IMHEX_LIBRARY_SETUP` block is reported as invalid.

Plugins live in the `plugins` data/plugin folder at runtime; `--plugins <path>`
adds extra load paths, and `--plugins` with no argument lists what's loaded.

---

## 12. Scripting (C# / .NET and C)

The `script_loader` plugin lets you add content using compiled scripts instead of
full C++ plugins:

- **.NET / C#** — `plugins/script_loader/support/dotnet` builds an
  `AssemblyLoader` and a managed `ImHexLibrary`; CMake compiles the C# projects
  (`dotnet build ... -c Release`) into DLLs installed alongside the plugins.
  Project templates live in `plugins/script_loader/templates/CSharp`
  (`ImHexLibrary`, `ImHexScript`).
- **C** — `plugins/script_loader/support/c` exposes a versioned C script API
  (`script_api/v1`: `bookmarks`, `logger`, `mem`, `ui`) compiled into a `c_api`
  object library linked against `libimhex` and `ui`.

This is the lighter-weight extension path: write a script in C# or C against the
provided API rather than maintaining a native plugin and SDK build.

> [!CAUTION]
> Scripts execute as native/managed code inside the ImHex process — they are not
> sandboxed. Only load scripts from sources you trust, exactly as you would a
> plugin.

---

## 13. The MCP Server

ImHex exposes a **Model Context Protocol** server so AI assistants can drive it.

### Topology

- The **server** lives in `libimhex` (`lib/libimhex/source/mcp/server.cpp`,
  header `include/hex/mcp/server.hpp`) and runs inside ImHex on the internal
  loopback port **`19743`** (`Server::McpInternalPort`).
- The **client/bridge** is launched by `imhex --mcp` (handled by the builtin
  plugin's `handleMCPCommand`), which runs an `mcp::Client` over `std::cin`/
  `std::cout` — the stdio transport AI hosts expect — relaying to the internal
  server.

### Protocol

The server speaks **JSON-RPC 2.0** and implements MCP protocol version
`2025-06-18`. The `JsonRpc` class parses single and **batched** requests,
validates the envelope (`jsonrpc == "2.0"`, string `method`), and maps standard
JSON-RPC error codes (`ParseError -32700`, `InvalidRequest -32600`,
`MethodNotFound -32601`, `InvalidParams -32602`, `InternalError -32603`).

`initialize` returns server info (`ImHex` + the running version) and advertises a
`tools` capability. Methods are dispatched by suffix:

- `notifications/*` → notification handlers (e.g. `initialized` marks connected).
- `*/list` → enumerate registered primitives of a type and their capabilities.
- `*/call` → invoke a named primitive (a "tool") with `arguments`.

Tools (primitives) are registered with `Server::addPrimitive(type, capabilities,
function)`, where `capabilities` is a JSON description carrying the tool's `name`.
The builtin plugin ships MCP tool definitions under
`plugins/builtin/romfs/mcp/tools`.

> [!NOTE]
> Because tools are registered the same way other content is, plugins can add MCP
> tools. The response framing appends a `0x00` terminator byte per message over
> the socket transport — relevant if you implement a custom bridge.

---

## 14. Configuration Reference

### Settings store

Settings are a single JSON document persisted to `settings.json` in a config path
(or browser `localStorage` on the Web build). Internally each setting is
addressed by `category / name` (both unlocalized keys). Plugins register settings
with `ContentRegistry::Settings::add(category, subCategory, name, widget)` and
react with `onChange`/`onSave` callbacks. Defaults are materialized lazily when a
setting is first read.

### Setting categories

The builtin plugin registers these top-level categories (display names from
localization):

| Key | Display name |
|-----|--------------|
| `hex.builtin.setting.general` | General |
| `hex.builtin.setting.interface` | Interface |
| `hex.builtin.setting.hex_editor` | Hex Editor |
| `hex.builtin.setting.pattern_editor` | Pattern Editor |
| `hex.builtin.setting.folders` | Folders |
| `hex.builtin.setting.proxy` | Proxy |
| `hex.builtin.setting.toolbar` | Toolbar |
| `hex.builtin.setting.shortcuts` | Shortcuts |
| `hex.builtin.setting.plugins` | Plugins |
| `hex.builtin.setting.loaded_plugins` | Plugins to be loaded |
| `hex.builtin.setting.experiments` | Experiments |
| `hex.builtin.setting.imhex` | ImHex (internal/meta) |

> [!NOTE]
> Reading a setting in code: `ContentRegistry::Settings::read<T>(category, name,
> default)`. For example, the builtin plugin reads
> `hex.builtin.setting.general / hex.builtin.setting.general.debug_mode_enabled`
> at startup to decide whether to enable debug mode (always on in DEBUG builds).

### Reset

`imhex --reset-settings` clears and re-stores settings (requires typing
`YES I AM ABSOLUTELY SURE`). Deleting `settings.json` has the same effect.

---

## 15. Filesystem & Path Resolution

ImHex resolves directories through `hex::paths` (`default_paths.{hpp,cpp}`). Three
path classes exist:

- **`ConfigPath`** — config-home-rooted (`config`, `recent`, `updates`).
- **`DataPath`** — data-home-rooted, can include system folders
  (patterns, magic, themes, scripts, …).
- **`PluginPath`** — plugin/library directories.

Each exposes `all()`, `read()` (existing dirs only), and `write()` (existing &
writable). The base directories per platform:

| Platform | Config | Data |
|----------|--------|------|
| Windows (installed) | `%LOCALAPPDATA%\imhex` | `%LOCALAPPDATA%\imhex` |
| Windows (portable) | next to the executable | next to the executable |
| macOS | `~/Library/Application Support/imhex` | same (+ executable dir as system folder) |
| Linux/Web | `$XDG_CONFIG_HOME/imhex` | `$XDG_DATA_HOME/imhex` + `$XDG_DATA_DIRS` |

Resolution rules worth knowing for packaging:

- **Portable Windows** deliberately skips `%LOCALAPPDATA%` and uses only the
  executable directory.
- **Linux AppImage** restricts plugin loading to inside the AppImage
  (`$APPDIR/usr/lib/imhex`).
- A compile-time `SYSTEM_PLUGINS_LOCATION` adds a system plugin dir on Linux.
- The directory of a loaded **project file** and any **additional folders**
  configured by the user are added to the data search path.

Named subfolders (postfixes) are listed in the User Guide; the canonical list is
the 22-entry `hex::paths::All` array (`Config`, `Recent`, `Updates`, `Libraries`,
`Plugins`, `Patterns`, `PatternsInclude`, `Magic`, `Yara`,
`YaraAdvancedAnalysis`, `Backups`, `Resources`, `Constants`, `Encodings`, `Logs`,
`Scripts`, `Inspectors`, `Themes`, `Nodes`, `Layouts`, `Workspaces`,
`Disassemblers`).

> [!TIP]
> Because most data paths are **multi-rooted** (user dir + system dirs), packagers
> can ship read-only content (patterns, magic, themes) in a system data dir while
> users add their own in the writable home dir. `read()` merges them; `write()`
> only ever targets writable locations.

---

## 16. Operations

### Logging

Logs are written to the `logs` data folder and the console. `--verbose` / `-v`
enables debug logging (which, among other things, prints every `ContentRegistry`
registration and posted event). `--debug-mode` enables additional debugging
features. Debug builds enable debug mode automatically and show a warning banner
(suppressible with `NO_DEBUG_BANNER`).

> [!CAUTION]
> A known data race exists in `log::debug()` when debug logging is disabled
> (reported upstream). If you build tooling around ImHex logs under heavy
> multithreaded load, be aware of it.

### Updates (the updater executable)

`imhex-updater <stable|nightly>` is invoked by ImHex to self-update. It:

1. Queries the GitHub releases API and selects the release matching the channel
   (stable releases have `target_commitish` starting `releases/v`; nightly is
   tagged `nightly`).
2. Picks the artifact for the current OS+arch by filename suffix — e.g.
   `Windows-x86_64.msi`, `macOS-arm64.dmg`, `Ubuntu-24.04-x86_64.deb`,
   `Fedora-42-x86_64.rpm`, `ArchLinux-x86_64.pkg.tar.zst`, `x86_64.AppImage`,
   `x86_64.flatpak`, `x86_64.snap`.
3. Downloads to a writable `updates` path and runs the platform installer.

Install commands by type:

| Artifact | Command |
|----------|---------|
| `.msi` | `msiexec /i "<file>" /qb` |
| `.dmg` | mounts, copies the `.app` to `/Applications` via AppleScript admin |
| `.deb` | `sudo apt install --fix-broken` (via `zenity` password) |
| `.rpm` | `sudo rpm -i` |
| `.pkg.tar.zst` | `sudo pacman -U` |
| `.AppImage` / `.flatpak` / `.snap` | copy / `flatpak install` / `snap install --dangerous` |

If the install type can't be auto-updated, the updater opens the latest release
page in a browser for a manual update. Portable Windows is intentionally not
auto-updated via `.msi`.

### Backup & recovery

- **Crash backup**: `crash_backup.hexproj` + `crash.json` written to a config
  path on crash. After a crash, reopen the backup project to recover work.
- **Backups folder**: the `backups` data path holds additional backups.
- **Workspaces** are exported on crash so the layout survives.

### Single-instance messaging

`messaging::setupMessaging()` enables sending commands (e.g. "open this file") to
an already-running ImHex instance rather than spawning a new one. Cross-instance
payloads arrive as `EventNativeMessageReceived`.

---

## 17. Code Quality & Conventions

Observed patterns across the codebase:

- **Modern C++23** throughout — concepts, ranges, `std::optional`, `<=>`,
  `consteval` literals, `std::source_location`, designated initializers.
- **`AutoReset<T>`** wrappers hold global registry state so it can be cleanly
  reset (important for the Web build and for plugin reloads).
- **Static "manager" classes** with deleted constructors as the API style;
  internal state lives in `impl` namespaces exposed through accessor functions.
- **`PerProvider<T>`** binds state to the active provider (e.g. the Pattern
  Language runtime is per-provider).
- **Strict separation of display text from logic** via `UnlocalizedString`.
- **Defensive event dispatch** (try/catch + log in release) and **cooperative
  task interruption** rather than thread cancellation.
- **ROM-FS embedded resources** (`romfs::get(...)`) keep assets in the binary.
- **Honest in-source TODOs/FIXMEs** — many event docs flag dead code for removal,
  which is good signal for contributors.
- **Heavy use of `[[nodiscard]]`** on getters.

Naming: `hex::` root namespace; plugins under `hex::plugin::<name>`; providers
under `hex::prv`; pattern-language types under `pl::`; the bundled `wolv::`
utility library (io/fs/utils/net/types) is used pervasively.

---

## 18. Testing

Tests live under `tests/` and are wired through CMake:

| Suite | Path | Focus |
|-------|------|-------|
| Common | `tests/common` | Shared test harness / entry point |
| Helpers | `tests/helpers` | Helper-function tests |
| Algorithms | `tests/algorithms` | Algorithmic correctness |
| Plugins | `tests/plugins` | Plugin-level tests |

The harness (`tests/common/source/main.cpp`) runs a single named test, supports
**expected-failure** tests (`shouldFail` inverts the result), and tears down via
`TaskManager::exit()`, `EventImHexClosing`, `EventManager::clear()`, and
`PluginManager::unload()`. Tests are declared with the `TEST_SEQUENCE(name)`
macro and assert with `TEST_ASSERT` / `TEST_SUCCESS`.

Example — the builtin provider read/write test
(`plugins/builtin/tests/source/main.cpp`) initializes the Built-in plugin, creates
a `mem_file` provider, and asserts resize/read/write/zero-fill semantics, plus an
expected-failure test that resizing to `-1` returns false. New plugin tests are
added to the `AVAILABLE_TESTS` list in `plugins/builtin/tests/CMakeLists.txt` and
registered as CTest cases.

```cmake
set(AVAILABLE_TESTS
    Providers/ReadWrite
    Providers/InvalidResize
)
```

---

## 19. Potential Improvements & Tech Debt

Drawn directly from in-source `FIXME`/`TODO` markers and community-reported
issues at this commit.

### Flagged in source

- **Dead events** — several events are documented as unused and slated for
  removal: `EventFileLoaded`, `EventPatternEditorChanged`,
  `EventStoreContentDownloaded`, `EventStoreContentRemoved`, `EventAnySettingChanged`,
  `RequestAddExitTask`. Cleaning these would reduce API surface confusion.
- **Naming inconsistencies** — `MovePerProviderData` lacks the `Request` prefix
  its siblings use; `EventProviderClosing` behaves like a request (it carries a
  mutable `bool*`) and is noted as belonging in the requests section.
- **`EventImHexUpdated`** is flagged as misleadingly named (it fires every
  startup with previous/current versions, not only on update).

### Community-reported (open issues at this commit)

| Area | Issue |
|------|-------|
| Pattern editor | Selection desync / skipping after edits (#2748, #2749) |
| Pattern eval | Crash on pattern with pointer-to-struct (#2744) |
| Hashing | CRC16 broken after restart (#2739) |
| CLI | Opening a file from the command line yields an empty layout (#2742, #2715) |
| Visualizers | Bitmap visualizer retains stale section data (#2743) |
| Logging | Data race in `log::debug()` when debug logging is off (#2751) |
| Endianness | Big-endian DOS date/time broken (#2723) |
| Paths | Default paths not created if missing (#2726) |
| I/O | GVFS SMB shares truncate files to zero bytes (#2660) |

### Architectural opportunities

- The `builtin` plugin is very large and mixes many concerns; splitting cohesive
  feature groups (CLI, providers, views) into focused plugins would improve
  modularity and build times.
- The dual GPU/NoGPU and native/Web/WASM matrix means OS-conditional code is
  spread across modules; consolidating platform shims behind the `wolv`/`paths`
  abstractions would reduce `#if defined(OS_*)` density.
- Settings are untyped JSON addressed by string keys; a typed settings schema
  would catch key typos at compile time.

---

## 20. Quick Reference

### Build

```bash
git clone --recurse-submodules https://github.com/WerWolv/ImHex
cd ImHex
cmake --preset x86_64          # Ninja, GCC, Debug, USE_SYSTEM_CAPSTONE=ON
cmake --build build/x86_64 --target imhex_all
```

### Plugin SDK

```bash
cmake -G Ninja -DIMHEX_BUNDLE_PLUGIN_SDK=ON -B build
cd build && DESTDIR=install ninja install
# SDK at install/usr/local/share/imhex/sdk  → set IMHEX_SDK_PATH
imhex --validate-plugin your_plugin.hexplug
```

### Key facts

| Item | Value |
|------|-------|
| Language / standard | C++23 |
| Supported compilers | GCC, LLVM Clang (**not** MSVC/AppleClang) |
| Build system | CMake ≥ 3.20 + Ninja |
| GUI | Dear ImGui over OpenGL 3.0+ |
| Disassembly engine | Capstone |
| MCP internal port | `19743` (loopback), JSON-RPC 2.0, protocol `2025-06-18` |
| Crash backup | `crash_backup.hexproj` + `crash.json` in config dir |
| Overall license | GPLv2 (libimhex + ui: LGPLv2.1) |
| Maintainer | WerWolv (+ small core team) |

### Core managers (libimhex)

`PluginManager` · `ContentRegistry` · `EventManager` · `TaskManager` ·
`ImHexApi` · `ShortcutManager` · `ThemeManager` · `LayoutManager` ·
`WorkspaceManager` · `LocalizationManager` · `AchievementManager` ·
`TutorialManager` · `ProjectFile` · `prv::Provider`

### Key dependencies

Dear ImGui (UI) · ImPlot (plots) · ImNodes (data processor) ·
ImGuiColorTextEdit (pattern editor) · nlohmann/json · fmt · Capstone
(disassembly) · YARA · edlib (diffing) · HashLibPlus (hashing) · miniaudio
(audio) · nativefiledialog-extended · microtar · xdgpp · the `wolv` utility
library · the standalone Pattern Language runtime.

### Links

- Repo: <https://github.com/WerWolv/ImHex>
- Docs: <https://docs.werwolv.net>
- Pattern Language: <https://github.com/WerWolv/PatternLanguage>
- Patterns DB: <https://github.com/WerWolv/ImHex-Patterns>
- Plugin template: <https://github.com/WerWolv/ImHex-Plugin-Template>
- SDK download action: <https://github.com/WerWolv/imhex-download-sdk>

---

_Generated June 2026 from WerWolv/ImHex at 8a6be85. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
