Skip to content

Latest commit

 

History

History
139 lines (114 loc) · 3.56 KB

File metadata and controls

139 lines (114 loc) · 3.56 KB

BOSS Plugin Platform

Host-side plugin platform (SDK + loader/runtime) that lets BOSS load and run plugins. This directory holds the infrastructure, not the plugins themselves - shippable plugins live in the separate boss_plugins repo.

Architecture

plugin-platform/
├── plugin-api/              # Core plugin interfaces and contracts
├── plugin-ui/               # Shared UI components (colors, themes)
├── plugin-scrollbar/        # Scrollbar utilities
├── plugin-git-types/        # Git data types
├── plugin-bookmark-types/   # Bookmark data types
├── plugin-workspace-types/  # Workspace data types
├── plugin-window/           # Window state management
│
├── plugin-panel-*/          # Panel plugins
│   ├── plugin-panel-git-log/
│   ├── plugin-panel-git-status/
│   ├── plugin-panel-console/
│   ├── plugin-panel-performance/
│   ├── plugin-panel-bookmarks/
│   ├── plugin-panel-codebase/
│   ├── plugin-panel-terminal/
│   ├── plugin-panel-topofmind/
│   ├── plugin-panel-fluck/
│   ├── plugin-panel-secret-manager/
│   ├── plugin-panel-downloads/
│   └── ...
│
└── plugin-tab-*/            # Tab type plugins
    ├── plugin-tab-fluck/
    ├── plugin-tab-code-editor/
    └── plugin-tab-terminal/

Creating a Plugin

1. Create Plugin Module

Add to settings.gradle.kts:

include(":plugin-platform:plugin-panel-myplugin")

Create build.gradle.kts:

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.composeMultiplatform)
    alias(libs.plugins.composeCompiler)
}

kotlin {
    jvm("desktop")
    sourceSets {
        commonMain.dependencies {
            api(projects.pluginPlatform.pluginApi)
            implementation(compose.runtime)
            implementation(compose.material)
        }
    }
}

2. Define Panel Info

object MyPanelInfo : PanelInfo {
    override val id = PanelId("my-panel", 50)
    override val displayName = "My Panel"
    override val icon = FeatherIcons.Star
    override val defaultSlotPosition = Panel.left.top
}

3. Create Component

class MyPanelComponent(
    ctx: ComponentContext,
    override val panelInfo: PanelInfo
) : PanelComponentWithUI, ComponentContext by ctx {

    @Composable
    override fun Content() {
        // Your UI here
    }
}

4. Create Plugin Object

object MyPanelPlugin : Plugin {
    override val pluginId = "ai.rever.boss.plugin.my-panel"
    override val displayName = "My Panel"

    override fun register(context: PluginContext) {
        context.panelRegistry.registerPanel(MyPanelInfo) { ctx, panelInfo ->
            MyPanelComponent(ctx, panelInfo)
        }
    }
}

5. Register in DefaultPlugin

// In DefaultPlugin.kt init block
MyPanelPlugin.register(this)

Plugin Types

Static Plugins

Always registered when the app starts.

Dynamic Plugins

Registered/unregistered based on conditions:

  • Auth-based: SecretManager (admin only)
  • Project-based: Git panels (git repos only)

Lifecycle

  1. DefaultPlugin is created with registries
  2. Plugins call register(context)
  3. Panels/tabs are registered with factories
  4. On dispose, pluginScope is cancelled
  5. Dynamic plugins unregister when conditions change

Best Practices

  • Use pluginScope for coroutines
  • Implement dispose() for cleanup
  • Use data provider interfaces, not direct dependencies
  • Keep UI in commonMain, platform code in platform sources