The core is small and knows nothing about the GUI. Formats, highlighting, themes and tools attach to it through an API expressed in plain C. That single boring decision is what keeps an extension working across compilers and languages.
01 · why c abi
A C++ ABI is not stable between compilers, standard libraries or even build flags. An editor that exposed C++ classes to plugins would force every extension author to match its exact toolchain — and would break them on the next compiler upgrade.
The boundary is therefore described in C: opaque handles, plain structs and function pointers. A plugin built with MSVC loads into a build produced by Clang; a plugin written in C or Rust loads next to one written in C++.
The core stays GUI-free. A format plugin pulls in no interface dependencies, which is what makes the core testable and the editor's behaviour on large files predictable.
02 · plugin kinds
Teaches the editor a file type: how it is read, presented and written. csv (table mode) and epub (WYSIWYG) are of this kind.
Supplies a grammar and indentation rules. The bundled tree-sitter plugin is one: six languages on one runtime.
Adds a capability over the open document or the project: git, clangd, unreal.
Ships a palette and appearance parameters within the existing design directions.
03 · shape
It exports one function that returns a static description: who it is, the ABI version it was built against, what it can do, and the callbacks for that.
/* editor/PluginAPI.h — abridged */ typedef struct EditorPluginInfo { int api_version; /* must equal EDITOR_PLUGIN_API_VERSION */ const char* id; /* reverse-DNS, "com.example.format.foo" */ const char* name; const char* version; /* semver */ const char* author; /* may be NULL */ const char* description; /* may be NULL */ uint32_t capabilities; /* EDITOR_CAP_* bitmask */ EditorPluginInit initialize; EditorPluginShutdown shutdown; /* … then the callbacks of each capability */ } EditorPluginInfo; /* the only symbol the host looks for */ EDITOR_PLUGIN_EXPORT const EditorPluginInfo* editor_plugin_register(void);
04 · build
The template depends on the public headers only and produces one shared library. The core is not rebuilt and is not linked into your plugin.
# CMakeLists.txt of the template, CMake 3.27 or newer find_package(ThePluginSDK REQUIRED) the_add_format_plugin(my_format SOURCES my_format.c) $ cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/sdk $ cmake --build build # → my_format.dll · my_format.dylib
05 · install
# Windows, default install folder C:\Program Files\The\bin\plugins\my_format.dll # macOS, inside the app bundle /Applications/The.app/Contents/PlugIns/my_format.dylib
06 · compatibility
| Guarantee | What it means for you |
|---|---|
| Compiler-independent | MSVC, Clang and GCC builds interoperate; no matching of standard-library flavours. |
| Language-independent | Anything able to export C symbols works: C, C++, Rust and others. |
| Versioned boundary | The plugin declares its ABI version and the host checks it, so an incompatible plugin fails loudly instead of crashing the editor. |
| No core rebuild | A plugin attaches to a released build of The. |
07 · not yet
A third-party plugin runs in the editor's process with its privileges. A WASM sandbox is planned, without a date.
No catalogue and no licensing for extensions — installation is manual.
The boundary may still change; such changes will be listed in the changelog.
Until a sandbox exists, only run plugins whose source you have read.