Klyx manages your extension through four lifecycle methods. Each method is a suspend function running on the plugin’s coroutine scope, so you can safely call other suspend APIs.
Lifecycle overview
onLoad()
Called when Klyx loads your extension. At this point, your plugin’s services (screens, toolbar, etc.) are available, but other plugins may not have started yet.
What to do here:
- Register screens with
ScreenRegistry
- Register toolbar actions with
ToolbarRegistry
- Register file openers with
FileOpenerRegistry
- Subscribe to events on the event bus
- Register language server providers
- Register tree-sitter language grammars
- Initialize lightweight state
onStart()
Called after all plugins have completed onLoad(). This is the right place to interact with other plugins, access shared resources, or start ongoing work.
What to do here:
- Start coroutines for background work (via
pluginScope or currentLifecycleOwner().lifecycleScope)
- Access other plugins’ registered resources
- Start long-running operations that depend on the full environment
onStop()
Called when Klyx is about to unload your extension. You should release any resources acquired in onStart().
What to do here:
- Cancel ongoing operations started in
onStart()
- Close file handles or network connections
- Save any state that needs persistence
onUnload()
Called after onStop() completes. This is your last chance to clean up before the plugin classloader is discarded.
What to do here:
- Unregister all screens
- Unregister all toolbar actions
- Unregister file openers
- Unregister language server providers
- Unregister language grammars
- Cancel all coroutines
- Unsubscribe from all event bus subscriptions
If you do not unregister screens and toolbar actions in onUnload(), they will leak. Klyx automatically cleans up registrations when a plugin crashes, but you should still unregister explicitly for a clean shutdown.
Coroutine scopes
Your plugin has two coroutine scopes available:
pluginScope — Created when the plugin loads and cancelled when it unloads. Use this for background tasks that should persist across start/stop cycles.
currentLifecycleOwner().lifecycleScope — Tied to the started/stopped lifecycle state. Coroutines are cancelled when the plugin stops.
Both scopes carry a PluginContextElement, so coroutines launched on them can access currentPluginContext() and currentLifecycleOwner().
Crash handling
If a plugin throws an unhandled exception during any lifecycle method, Klyx marks the plugin as crashed. The plugin’s scope is cancelled, its lifecycle is destroyed, and all its screen and toolbar registrations are automatically removed. A crash file is persisted so the plugin can be disabled on next startup if needed.
You can check if a plugin has crashed via the crash(t: Throwable) method on the internal PluginRuntime.