TheThe1.5.0
The/SDK

Write a plugin against a plain C boundary.

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++ boundary would break your plugin on the next compiler.

1.1

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.

1.2

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++.

1.3

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

Four kinds, one boundary.

format

Teaches the editor a file type: how it is read, presented and written. csv (table mode) and epub (WYSIWYG) are of this kind.

highlight

Supplies a grammar and indentation rules. The bundled tree-sitter plugin is one: six languages on one runtime.

tool

Adds a capability over the open document or the project: git, clangd, unreal.

theme

Ships a palette and appearance parameters within the existing design directions.

03 · shape

A plugin is a shared library with one C entry point.

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

A standalone CMake project.

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

Manual, and deliberately so.

  • Place the built library into the editor's plugin directory and restart the editor.
  • The plugin appears in the Plugins panel and is switched on with a toggle.
  • The host verifies the declared ABI version on load; a mismatch means the plugin is not loaded and the reason is reported.
  • Nothing is downloaded automatically: there is no store and no auto-update for extensions.
# 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

What the C boundary guarantees.

GuaranteeWhat it means for you
Compiler-independentMSVC, Clang and GCC builds interoperate; no matching of standard-library flavours.
Language-independentAnything able to export C symbols works: C, C++, Rust and others.
Versioned boundaryThe plugin declares its ABI version and the host checks it, so an incompatible plugin fails loudly instead of crashing the editor.
No core rebuildA plugin attaches to a released build of The.

07 · not yet

Stated plainly, so nobody plans around it.

No sandbox

A third-party plugin runs in the editor's process with its privileges. A WASM sandbox is planned, without a date.

No store

No catalogue and no licensing for extensions — installation is manual.

No API stability before 1.0

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.