> ## Documentation Index
> Fetch the complete documentation index at: https://klyx.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugin Lifecycle

> Understanding the Klyx plugin lifecycle — load, start, stop, and unload

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

```
Load → onLoad() → onStart() → (running) → onStop() → onUnload() → Unloaded
```

| Phase | Method       | Purpose                                                        |
| ----- | ------------ | -------------------------------------------------------------- |
| 1     | `onLoad()`   | Register resources, subscribe to events, set up infrastructure |
| 2     | `onStart()`  | Begin operations that depend on other plugins                  |
| 3     | onStop       | (Triggerable by user or system)                                |
| 4     | `onStop()`   | Pause or release start-time resources                          |
| 5     | `onUnload()` | Full cleanup — unregister everything                           |
| 6     | Unloaded     | Plugin removed from memory                                     |

## 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

```kotlin theme={null}
override suspend fun onLoad() {
    val bus = currentPluginContext().eventBus

    screens.register(Screen(ScreenId("myext.main")) { MainScreen() })

    toolbar.register(ToolbarAction(
        id = "myext.action",
        label = "My Action",
        category = ToolbarCategory("My Plugin"),
        priority = 100,
        onClick = { /* ... */ }
    ) {})

    // Subscribe to events
    bus.subscribe<FileOpenedEvent> { event ->
        showToast("Opened: ${event.fileName}")
    }
}
```

## 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

```kotlin theme={null}
override suspend fun onStart() {
    pluginScope.launch {
        // Background work tied to the plugin's lifetime
        val result = command("git", "status").output()
        showToast(result.stdoutText)
    }
}
```

## 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

```kotlin theme={null}
override suspend fun onStop() {
    showToast("Stopping...")
}
```

## 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

```kotlin theme={null}
override suspend fun onUnload() {
    screens.unregister(ScreenId("myext.main"))
    toolbar.unregister("myext.action")
    busSubscription?.cancel()
    fileOpenerRegistration?.unregister()
}
```

<Warning>
  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.
</Warning>

## 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()`.

```kotlin theme={null}
override suspend fun onLoad() {
    // Tied to plugin load/unload lifecycle
    pluginScope.launch {
        // This runs even when the plugin is stopped
    }

    val owner = currentLifecycleOwner()
    // Tied to start/stop lifecycle
    owner.lifecycleScope.launch {
        // This is cancelled when onStop() is called
    }
}
```

## 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`.
