Skip to content

kit-shell

<kit-shell name="my-app">
<!-- app content -->
</kit-shell>

<kit-shell> is the root element of every Kitsune app. Exactly one shell per page. It creates a runtime, installs modules listed in its modules property, and starts the runtime when it connects to the document.

@atheory-ai/kitsune-app

import '@atheory-ai/kitsune-app'
// or import the class directly
import { KitShellElement } from '@atheory-ai/kitsune-app'
AttributeTypeDefaultNotes
namestring'app'Identifies the shell in diagnostics. Reflects to attribute.
debugbooleanfalseReserved; future versions will enable extra diagnostic logging. Reflects.
PropertyTypeNotes
runtimeKitRuntimeThe runtime instance owned by this shell. Read-only.
modulesKitModule[]Modules to install on connect. Set before the shell connects, or before connectedCallback runs.
  • connectedCallback: installs each module via runtime.install, then calls runtime.start().
  • disconnectedCallback: calls runtime.stop() (which runs each module’s stop hook in reverse order).
await customElements.whenDefined('kit-shell')
const shell = document.querySelector('kit-shell')!
shell.modules = [notificationModule(), dialogModule(), debugModule()]

The order matters for commands (last-registered wins) but not for events (all run).

shell.runtime.on('note.saved', (event) => {
console.log(event)
})

Custom elements don’t have a clean cross-tree communication channel like React Context. The shell is the well-known root: any descendant can do closest('kit-shell').runtime.

This is also how <kit-boundary> finds its shell — it queries up via closest('kit-shell') to dispatch.

You can have multiple shells on a page (each with its own runtime), but boundaries belong to the nearest shell. Don’t nest shells.

A common pattern is one shell per top-level UI region for fully isolated runtimes (e.g., a chat widget that shouldn’t share modules with the host page).

If you can’t use the custom element (e.g., outside the DOM):

import { createKitRuntime } from '@atheory-ai/kitsune-core'
const runtime = createKitRuntime()
await runtime.install(myModule)
await runtime.start()