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 modifyctx.args(arguments) - after: code after
await next(), may modifyctx.result(return value) - Block: call
ctx.prevent()to skip the default implementation and all later hooks - Replace:
ctx.prevent()plus actx.resultvalue 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)
registerHook.
registerHook — register a hook
- Permission:
hook:register - Signature:
(method: string, handler: (ctx, next) => Promise<void>) methodis 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.