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

# Creating an Extension

> Step-by-step guide to building a Klyx extension

This guide covers the full process of creating a Klyx extension, from project setup to advanced features like screens, toolbar actions, and file openers.

## Project structure

A well-organized extension looks like this:

```text theme={null}
my-extension/
├── app/
│   ├── build.gradle.kts
│   └── src/main/
│       ├── AndroidManifest.xml
│       └── java/com/myext/
│           ├── MyExtension.kt        # Plugin entry class
│           └── ui/
│               ├── MainScreen.kt     # Custom screens
│               └── DetailScreen.kt
├── build.gradle.kts
├── settings.gradle.kts
├── gradle/libs.versions.toml
└── plugin.json                       # Plugin manifest
```

## The entry class

Your extension's entry point is a class that implements `KlyxPlugin`. Klyx discovers this class through the `entryClass` field in `plugin.json` and loads it reflectively.

```kotlin MyExtension.kt lines theme={null}
class MyExtension : KlyxPlugin {

    private val screens: ScreenRegistry by plugin()
    private val toolbar: ToolbarRegistry by plugin()
    private val navigator: Navigator by plugin()
    private val info: PluginInfo by runtime()

    override suspend fun onLoad() {
        // Register screens and toolbar actions
        screens.register(this, Screen(ScreenId("myext.main")) {
            MainScreen(navigator)
        })
        toolbar.register(this, ToolbarAction(
            id = "myext.show_main",
            label = "My Extension",
            icon = ToolbarIcon(Icons.Default.Extension),
            category = ToolbarCategory("My Plugin"),
            priority = 100,
            onClick = { navigator.navigateTo(NavDestination.Custom(ScreenId("myext.main"))) }
        ))
    }

    override suspend fun onStart() {
        // All plugins loaded — safe to interact
    }

    override suspend fun onStop() {
        // Release resources acquired in onStart
    }

    override suspend fun onUnload() {
        // Cleanup — unregister everything
        screens.unregister(ScreenId("myext.main"))
        toolbar.unregister("myext.show_main")
    }
}
```

## Registering resources

### Screens

Register screens during `onLoad()` using `ScreenRegistry`. Each screen gets a unique `ScreenId` and a composable lambda.

```kotlin theme={null}
screens.register(this, Screen(ScreenId("myext.detail")) {
    DetailScreen()
})
```

### Toolbar actions

Add actions to Klyx's toolbar. Each action has an ID, label, icon, category, priority, and click handler. Higher priority values place the action first.

```kotlin theme={null}
toolbar.register(this, ToolbarAction(
    id = "myext.action1",
    label = "Do Something",
    icon = ToolbarIcon.Resource("action.png"),
    category = ToolbarCategory("My Plugin"),
    priority = 100,
    onClick = { /* handle action */ }
))
```

### File openers

Register a `FileOpener` to handle custom file types. The opener returns a `WorkspaceTab` if it can handle the file, or `null` to let other openers try.

```kotlin theme={null}
openers.register(object : FileOpener {
    override val id = "myext.opener"
    override val priority = 50
    override suspend fun open(request: FileOpenRequest): WorkspaceTab? {
        if (request.extension != "svg") return null
        return WorkspaceTab.Custom(
            title = request.fileName,
            content = { SvgViewer(request.uri) }
        )
    }
})
```

## Responding to events

Use the event bus to react to app events. Subscribe in `onLoad()` and unsubscribe in `onUnload()`.

```kotlin theme={null}
override suspend fun onLoad() {
    val bus = currentPluginContext().eventBus
    job = pluginScope.launch {
        bus.subscribe(FileOpenedEvent::class) { event ->
            showToast("File opened: ${event.fileName}")
        }
    }
}

override suspend fun onUnload() {
    job?.cancel()
}
```

See [Events](/extensions/api-reference/events) for all available event types.

## Navigation

Use the `Navigator` service to navigate users to different destinations:

```kotlin theme={null}
navigator.navigateTo(NavDestination.Home)
navigator.navigateTo(NavDestination.Settings)
navigator.navigateTo(NavDestination.Terminal)
navigator.navigateTo(NavDestination.Custom(ScreenId("myext.main")))
navigator.navigateBack()
```

## Best practices

* **Keep `onLoad()` fast**: Defer heavy work to `onStart()` or launch a coroutine
* **Unregister everything**: Always clean up screens, toolbar actions, and subscribers in `onUnload()`
* **Handle file openers gracefully**: Return `null` from `open()` if you can't handle the file
* **Use `pluginScope`**: Launch long-running coroutines on `pluginScope` so they're properly cancelled
