Plugins
Editora can be extended with plugins, which add commands, keybindings, tool windows, editor-menu items, and status-bar segments. Browse the plugin catalog for what’s available, or write your own.
Plugins are off by default and run with full access (no sandbox). Only install plugins you trust.
Installing
- Enable plugins in Settings → Plugins (or View: Toggle Plugins,
view.togglePlugins). Plugins are off in Simple UI mode. - Browse plugins… (or the
plugins.browsecommand) installs from the official registry; Install from file… (plugins.installFromDisk) installs a local.zip. Both buttons are greyed while plugins are off. The plugin list opens in the main window: the Settings window steps aside when it appears and comes back on the Plugins page when it closes. - Read the Enable this plugin? dialog, which lists what the plugin will do (see What the consent dialog shows), and choose Enable. Nothing in your plugins folder changes before you do: if you cancel, nothing is installed.
- Restart Editora to load it.
You can also copy a plugin folder into plugins/<id>/ in your config folder
yourself, click Reload Plugins, and tick it (behind the same dialog).
Browse marks each registry entry: Install, Installed, Update
available (with the version you have), Newer version installed,
Requires Editora ≥ a version (greyed, not installable), or Deprecated
with the registry’s reason. Before downloading, Editora asks whether to
Install, Update (old → new version), Reinstall or Downgrade,
comparing versions the semver way: 1.10 is newer than 1.9, rc10 newer than
rc2, a pre-release older than its release, a leading v and +build metadata
are ignored. An entry from a registry other than the built-in one names that
registry in the question, and with Require a signed registry off, the
question says when the registry is not signed by the trusted key.
Installed plugins live in your config folder under plugins/<id>/, where the
folder name is the plugin’s id, and the enabled set is tracked in
plugins.json.
Updating and removing
An update replaces the plugin’s folder but keeps plugins/<id>/data/, where a
plugin stores its own files. If you decline an update, the version you had
stays installed, enabled if it was.
If a different plugin declares the id of one you have installed, Editora asks Replace A with B? first: it would take that plugin’s place and the data it saved.
Remove on a row deletes that row’s plugin, after asking with the plugin’s
name and, when it has saved data, saying that the data goes too. Its plugin.json is deleted
last, so a folder that cannot be fully deleted is still listed and can be
removed again.
When changes take effect
Plugins are loaded once, at startup, and every window of a session runs the plugins that loaded at launch, including windows you open later. Installing, updating, enabling, disabling or removing a plugin takes effect at the next start. A running plugin’s jar stays open, so its update or removal is applied at the next start, before anything loads.
Each row in Installed Plugins says what a restart will change, with a Restart Now button beside it:
- Restart to apply: a plugin you switched on or off.
- Version N runs after a restart: an update waiting to replace the running version.
- Removed when Editora restarts: a running plugin you removed.
- Changed since you enabled it: tick it to see what it does now: see Security. This row has no Restart Now; tick it to agree again.
The Settings page
Settings → Plugins has three parts:
- The warning that plugins run with full access, Enable plugins, and a note that changes apply after a restart.
- Installed Plugins: Reload Plugins, the plugins folder, and one row per
plugin with its checkbox, version, id, Remove, any pending restart, and
any problem. A plugin whose
plugin.jsoncannot be read is listed with the reason (and the line and column where reading stopped, when known) and cannot be ticked; the parser’s own text is in the tooltip. Rows are greyed while Enable plugins is off. - Browse & Install: Browse plugins…, Install from file…, the Registry URL, and Require a signed registry.
The result of a Browse or install started here is shown under its buttons, as well as in the status bar. Install and registry errors are sentences in your language, in a dialog titled Plugins; a plugin that fails to start, or whose main class is missing, is reported in the Message Log and on its row.
If a plugin breaks startup
Start Editora with --disable-plugins to load no plugin for
that session; nothing is saved, and Settings → Plugins and the Doctor say it is
on. Then switch the plugin off or remove it, and restart. Restart Now from
that session starts Editora without the flag.
The Doctor’s Plugins section (View: Doctor) shows how many plugins run and how many are installed, and has a row for each plugin that failed to load, failed to start, or started slowly, with a link to Settings → Plugins.
Export Configuration leaves out the data plugins saved unless you tick Include the data plugins saved (it is asked only when a plugin has saved data). A plugin’s data folder can hold tokens, keys or notes, so leave it off for an export you will share. The installer’s staging folders are never exported.
Security
Plugins are not sandboxed: an enabled plugin runs with the same access to your files and system as Editora itself. What Editora checks is where a plugin came from, and that you agreed to it.
- Signed registry. The registry’s
index.jsonis verified against an Ed25519 public key bundled with Editora. Require a signed registry (Settings → Plugins, on by default; Plugins: Toggle Require Signature,plugins.toggleRequireSignature) blocks browsing and installing from a registry whose signature is missing or does not verify. A.zipyou install from a file is not checked. A registry of your own (plugins.setRegistryUrl) cannot be signed with that key, so using one means turning the requirement off. - Checksum. A plugin downloaded from the registry must match the SHA-256
listed in the index, and must be the plugin and version its entry names. The
registry and its downloads are HTTPS-only. The Registry URL field and
Plugins: Set Registry URL… take only an
https://address: anything else is refused (the field turns red), and the registry in use stays. A.zipinstalled from a file has no checksum to match. Reading a registry index stops after a minute and reading a download after five minutes, so a server that stalls cannot hang the install; an archive over 128 MB is refused, and a picked file that large is refused before it is read. - Staged installs. An archive is unpacked into a staging folder beside the
plugins, and nothing in
plugins/changes until you have seen what it does and chosen Enable. Staging folders a crash left behind are removed at start. An install over a plugin folder that is a link to a folder elsewhere (a plugin you are developing) is refused. - Consent. Before a plugin is enabled, a dialog lists what it can do. Each plugin has its own enable switch, and a plugin whose capabilities cannot be shown stays disabled.
- Consent belongs to the folder. A plugin’s id is its folder’s name. A
folder whose
plugin.jsondeclares another id is listed with an error (“rename the folder to …”) and never loads, so a second folder cannot run under the consent given to the plugin whose id it copied. - Consent belongs to what you were shown.
plugins.jsonstores a fingerprint of the disclosure with each consent: the main class, the names of the jars, each command, and each chord, but not the name or version. A plugin whose disclosure differs from what you agreed to (an update that adds code, a command or a chord) does not load; its row says Changed since you enabled it, and ticking it shows the new disclosure. A release that only changes its version keeps your consent. Entries of plugins whose folder is gone are dropped at start, so a stale consent cannot arm whatever appears under that name later. - Agents. MCP clients cannot switch plugins on, change the signed-registry requirement, set the registry, or install or remove plugins; see MCP server.
A valid signature tells you who published the registry. It does not make a plugin safe.
What the consent dialog shows
The dialog lists:
- whether the plugin runs executable code: its main class and every jar it loads;
- each external command, with its title, its exact arguments and the folder it runs in;
- each chord it binds, in your keymap’s notation, with the command it replaces or the shortcut it removes, including chords for other keymaps;
- whether it adds snippets or file templates.
Text from the manifest is escaped (line breaks, tabs, control and bidirectional characters are shown, not obeyed) and shortened when long, the list scrolls inside a fixed-height box, and Cancel is the default button.
What a plugin can do
A plugin can:
- Register commands (they appear in the palette, with the chords bound to them) and bind keys to them.
- Add a tool window (left / right / bottom) with custom UI. Its toggle is named Tool Window: followed by the window’s title.
- Add editor right-click menu items, in their own group of the menu, and status-bar segments, which can be reached by keyboard and name their plugin in the tooltip.
- Ship snippets and file templates that merge into the built-in sets. A plugin’s entry overrides a bundled one with the same name or id, and your own overrides both.
- Run external tools (formatters, task runners) via a subprocess. What a declared command prints is shown in the status bar and the Message Log.
A plugin’s commands and tool windows are always in its own namespace: their ids
are plugin.<id>.<name>, so a plugin cannot replace a built-in command or
another plugin’s. A command registered without a title shows the plugin’s name.
A command, menu item or status segment that fails is reported with the plugin’s
name.
Your own key bindings always win over a plugin’s. A chord a plugin takes from another command is named in the status bar when the plugin loads.
Writing a plugin
A plugin is a folder with a plugin.json manifest plus, optionally, a Java jar
and snippets/ / templates/ directories. The simplest plugins are purely
declarative (commands that run a shell command, keybindings, asset folders);
richer ones implement the Plugin interface against the exported
com.editora.plugin API.
The manifest’s id, if given, must be the folder’s name. Its keymap binds
chords in every keymap; keymaps gives the chords for one keymap only
(emacs, cua, vscode, intellij or sublime), used in place of
keymap while that keymap is active:
{
"keymap": { "C-M-S-e": "insertStamp" },
"keymaps": { "emacs": { "C-c C-x s": "insertStamp" } }
}
A bare command name (insertStamp) is the plugin’s own command; a dotted id is
a built-in. Chords mean different things per keymap (C-c copies in CUA but
starts a prefix in Emacs), so one flat map rarely suits them all.
A Java plugin’s start runs on the JavaFX thread as each window opens, so it
must return quickly. Editora times it: one that takes 250 ms or more is named in
the Message Log, on its Settings row and in the Doctor. If start throws, what
it had added (commands, chords, tool windows, menu items, status segments) is
taken back and its stop is called. Plugin API calls belong on the JavaFX
thread: from another thread, a write is handed to it and a read throws.
activeEditor() returns the buffer that is active when it is called, and stays
on it: a formatter that finishes on a worker thread writes into the file it
started on, never into whichever tab is in front by then. Once that tab is
closed it reads as empty and ignores writes; ask again for the current tab.
caretLine() counts from the top of the file in a narrowed buffer too.
Start from the Example Plugin,
which exercises every extension point. The copy in Editora’s repository
(examples/example-plugin)
binds Ctrl+Alt+Shift+E and Ctrl+Alt+Shift+Y, chords that are free in every
keymap. Read the full authoring guide in
docs/plugins.md.
Publishing
The official registry is
adriandeleon/editora-plugins,
a curated index.json plus each plugin’s source and a downloadable .zip
(verified by sha-256 on install). Open a pull request there to add yours. Each
entry’s id and version must match the plugin.json inside its archive.
A registry plugin whose feature moved into Editora is retired: an installed copy
is removed at startup and its id is never listed, installed or loaded again.
The GnuPG plugin (gpg-tools) is retired, since
encrypted files are built in; its gpg path and last
recipient are kept.