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.
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/
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)
}
}
}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
}class MyPanelComponent(
ctx: ComponentContext,
override val panelInfo: PanelInfo
) : PanelComponentWithUI, ComponentContext by ctx {
@Composable
override fun Content() {
// Your UI here
}
}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)
}
}
}// In DefaultPlugin.kt init block
MyPanelPlugin.register(this)Always registered when the app starts.
Registered/unregistered based on conditions:
- Auth-based: SecretManager (admin only)
- Project-based: Git panels (git repos only)
DefaultPluginis created with registries- Plugins call
register(context) - Panels/tabs are registered with factories
- On dispose,
pluginScopeis cancelled - Dynamic plugins unregister when conditions change
- Use
pluginScopefor coroutines - Implement
dispose()for cleanup - Use data provider interfaces, not direct dependencies
- Keep UI in commonMain, platform code in platform sources