Skip to main content

Hook system — Intercept and extend launcher methods

Through the Hook system (Hook system)a plugin can inject logic before and after a launcher method runs: modify arguments, modify the return value, block execution, or replace the implementation entirely. This suits feature enhancements, performance tuning, and logic reworking (for example: injecting custom JVM arguments at launch, adding virtual versions to version scanning, intercepting downloads).

Execution model: a Koa-style onion pipeline

Each hook is a middleware function (ctx, next) => Promise<void>, executed as an onion model:
  • before: code before await next(), may modify ctx.args (arguments)
  • after: code after await next(), may modify ctx.result (return value)
  • Block: call ctx.prevent() to skip the default implementation and all later hooks
  • Replace: ctx.prevent() plus a ctx.result value replaces the implementation entirely
  • Nesting: multiple plugins run as an onion in registration order, the first registered sits outermost

Permissions and declarations

Permission

hook:register (danger level). The manifest permissions must include it, otherwise registration is rejected.

manifest declaration (optional)

The declaration documents intent and supports permission pre-checks; the actual handler is registered at runtime with registerHook.

registerHook — register a hook

  • Permission: hook:register
  • Signature: (method: string, handler: (ctx, next) => Promise<void>)
  • method is the name of a launcher method that can be hooked (see the table below)
  • Disabling a plugin unregisters all of its hooks automatically

The Context object

Hookable methods

Typical examples

Block launching a specific instance

Replace the implementation entirely

Modify launch arguments (inject JVM arguments)

Execution location and architecture

Plugin hook functions run inside the plugin iframe sandbox, while the default implementation (impl) runs in the main window. The two communicate over a two-phase bridge (before → impl → after), which preserves onion semantics across windows:

Known limitations

  • Only the frontend method layer is covered (methods exposed through the hookable() wrapper); hooks inside the Rust backend process are planned.
  • Hooks of inline-rendered plugins (render: "inline") run directly in the main window context (they share the same registry).
  • L4 WebView plugins do not yet support cross-window registerHook.