Kunkun
Concepts

How Extensions Run

kkrpc, the HostAPI proxy, boot info, and the worker-view render cycle.

When you call Clipboard.readText() from an extension, nothing happens in your sandbox — the call is forwarded to the host, executed there under a permission check, and the result is returned. This page explains the machinery.

kkrpc: typed bidirectional RPC

Kunkun uses kkrpc, a type-safe RPC layer, for host↔extension communication. It replaces stringly-typed channels with compile-time-checked method names, arguments, and return types, and it works over any transport (Electron IPC, WebSocket, stdio, Worker postMessage).

Every SDK method is an async proxy call:

If the permission check fails, the promise rejects with a typed error instead of returning a value — you never silently get partial access.

The HostAPI proxy: getHostAPI()

The SDK resolves the host connection through a single global singleton:

import { getHostAPI } from "@kunkunsh/sdk/runtime";
const host = getHostAPI(); // typed KunkunHostAPI proxy; throws if not connected yet

Two design points make this robust:

  • Single instance across bundles. The connection is stored on globalThis.__kunkun_host_api__, so even if several copies of @kunkunsh/sdk end up bundled together (host + plugin), they share one host connection.
  • Errors survive transport. Typed errors like DbError are re-instantiated on the plugin side after crossing kkrpc, so error instanceof DbError and error.code still work.

You rarely call getHostAPI() directly — the friendly wrappers (Clipboard, fs, db, showToast, …) do it for you.

Boot info: window.__kunkun__

Before your code runs, the host injects runtime metadata:

interface KunkunPluginBoot {
  pluginId: string
  installationId: string
  extensionIdentifier: string
  commandName: string
  runtimeKind: "custom-view" | "worker-view" | "node-view"
  apiVersion: string
  mode: "development" | "production"
  permissionScope: PermissionScope
  // ...
}

window.__kunkun__ is information, not authorization. The host doesn't trust it to grant access — it constructs your HostAPI from its own trusted state and enforces permissions there. It's safe to read for your own metadata (e.g. commandName), but you can't escalate by editing it.

Custom-view: static SPA over a custom protocol

Custom-view extensions load into an isolated BrowserWindow via the kunkun-ext:// protocol:

  • Origin isolation. Each extension gets a unique origin (kunkun-ext://{pluginId}), so Chromium enforces same-origin separation automatically.
  • Path safety. The protocol handler rejects symlink escapes and path traversal, and falls back to index.html for SPA routes.
  • Preload channel allowlist. Plugin windows use a preload that permits only the exact kkrpc channel injected for that window — the trusted app's main channel is blocked. Even if that filter were bypassed, kkrpc's sender check drops cross-window messages.

Worker-view: React in a Web Worker, host renders the UI

Worker-view (and node-view) extensions don't touch the DOM. You write React; a custom reconciler (Uniview) serializes your component tree to JSON; the host maps each node to a native Svelte component and renders it. Event handlers become ids that are called back into the worker.

This is why worker-view components import primitives from @kunkunsh/sdk/ui (Button, List, Form, …) instead of using raw HTML: those primitives are what the host knows how to render. It's also why your build must bundle to a single file with dedupeReact() — two React copies would break the reconciler.

Node-view uses the exact same UI model, but the worker is a Node.js/Deno process instead of a Web Worker, so you additionally get fs, shell, native modules, and full network access (subject to permissions).

Where each mode runs

ModeRuntimeDOM?Node APIs?
custom-viewBrowserWindow (kunkun-ext://)FullNo
worker-viewWeb WorkerNoNo
node-viewNode.js / Deno processNoYes
worker-headlessWeb WorkerNoNo
node-headlessNode.js / Deno processNoYes

See Extension Types to choose, and Permissions for how each runtime is sandboxed.

On this page