Skip to content

plugin-api/CommandRegistry#

normalizeKeybinding()#

function normalizeKeybinding(binding): string;

Normalise a keybinding string so Mod+Shift+K and mod+shift+k collide.

Parameters#

Parameter Type
binding string

Returns#

string


resolveCommandLabel()#

function resolveCommandLabel(def): string;

The enforced display name: "{scope}: {command}".

Parameters#

Parameter Type
def CommandDef

Returns#

string


resolveCommandScope()#

function resolveCommandScope(def): string;

The qualifier alone.

Parameters#

Parameter Type
def CommandDef

Returns#

string


resolveCommandTitle()#

function resolveCommandTitle(def): string;

The command part alone, with any accidental scope prefix removed. Thunks are re-evaluated on every read, so a late registerPluginTranslations is picked up without re-registering.

Parameters#

Parameter Type
def CommandDef

Returns#

string


useCommands()#

function useCommands(hasCapability?): CommandDef[];

React hook returning the currently-visible commands, re-rendering on any registry change. Live subscription matters: plugins load sequentially and late (after the backend handshake), so commands can register while the palette is already open.

Parameters#

Parameter Type
hasCapability? (capability) => boolean

Returns#

CommandDef[]


commandsRegistry#

const commandsRegistry: CommandRegistry;

Deliberately not named commandRegistry — that identifier belongs to the DOM scraper in utils/commandRegistry.ts and they are different things.


CommandDef#

Properties#

capability?#

optional capability?: string;

Device capability gate, mirroring TuneOperationDef.

category?#

optional category?: string;

icon?#

optional icon?: ComponentType;

id#

id: string;

nuclei.<area>.<verb> for core, plugin:<shortId>.<verb> for plugins.

isEnabled?#

optional isEnabled?: () => boolean;

Display-time predicate — shown greyed out and not invocable.

Returns#

boolean

isVisible?#

optional isVisible?: () => boolean;

Display-time predicate — hidden rows are not listed and cannot be run by key.

Returns#

boolean

keybinding?#

optional keybinding?: string;

e.g. mod+shift+r. Dispatched from one listener so conflicts are detectable.

keywords?#

optional keywords?: string[];

order?#

optional order?: number;

run#

run: () => void | Promise<void>;
Returns#

void | Promise<void>

scope#

scope: string | (() => string);

The qualifier in "{scope}: {command}" — the localized page title for page-bound built-ins, the plugin's display name for plugin commands (injected by the bundle loader's proxy, so a plugin cannot spoof another plugin's scope), or one explicit word for genuinely global commands.

Resolved at DISPLAY time, hence the thunk: page titles are localized and plugin translations can land after the command registers.

title#

title: string | (() => string);

The command part ONLY — "Save as…", never "Reports: Save as…". The "{scope}: {command}" display name is composed by the registry, so authors cannot get the format wrong and cannot skip the scope.

Lazy thunk or plain string. A thunk is required whenever the title comes from i18n: plugin translations register into plugin:${shortId} and can land after the command does, and core titles must re-resolve on a language change. Same pattern as TuneOperationDef.label.


KeybindingConflict#

Properties#

commandIds#

commandIds: string[];

keybinding#

keybinding: string;