ai-toolkit-trainer
Train custom LoRAs with ostris AI-Toolkit. Covers WAN 2.2/2.1 (people, styles, video motion) and Z-Image (Turbo & Base, low-VRAM image LoRAs). Use when the…
Authoring ComfyUI v2 frontend extensions with @comfyorg/extension-api, covering defineNode/defineExtension/defineWidget, shell UI (sidebar tabs, commands, hotkeys), typed events, and handles. Use when writing or editing ComfyUI web-UI extension code (custom node JS, sidebar
$ npx -y skills add artokun/comfyui-mcp --skill comfyui-frontend-extensions --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/comfyui-frontend-extensionsContext preview
The summary Claude sees to decide when to auto-load this skill.
Authoring ComfyUI v2 frontend extensions with @comfyorg/extension-api, covering defineNode/defineExtension/defineWidget, shell UI (sidebar tabs, commands, hotkeys), typed events, and handles. Use when writing or editing ComfyUI web-UI extension code (custom node JS, sidebar
name: comfyui-frontend-extensions description: Authoring ComfyUI v2 frontend extensions with @comfyorg/extension-api, covering defineNode/defineExtension/defineWidget, shell UI (sidebar tabs, commands, hotkeys), typed events, and handles. Use when writing or editing ComfyUI web-UI extension code (custom node JS, sidebar panels, widgets).
The v2 extension API is the published npm package `@comfyorg/extension-api`. It replaces the legacy `app.registerExtension()` / `nodeType.prototype` monkey-patching model with a typed, tree-shakeable, import-based API.
> If you are converting an existing v1 extension, read > [`references/migrate-v1-to-v2.md`](references/migrate-v1-to-v2.md) for a > pattern-by-pattern mapping.
| v1 (legacy) | v2 (`@comfyorg/extension-api`) | |-------------|-------------------------------| | One giant `app.registerExtension({...})` call | One `defineX` per concern, each independently disposable | | `window.app` / `app.*` globals | Direct `import` from the package; no `window.app` at module-eval time | | `nodeType.prototype.onExecuted = ...` patching | `node.on('executed', fn)` on a `NodeHandle` | | Mutate `widget.value`, assign `widget.callback` | `widget.setValue(v)` / `widget.on('valueChange', fn)` | | `api.addEventListener('execution_start', fn)` | `execution.on('start', fn)` (typed namespaces) | | Manual `removeEventListener` bookkeeping | Every subscription returns `Unsubscribe`; every `defineX` returns `DisposableHandle` |
Core principles baked into the API:
All imported from `@comfyorg/extension-api`:
| Function | Purpose | Returns | |----------|---------|---------| | `defineNode(opts)` | **Primary entry** — react to node lifecycle (replaces prototype patching) | `NodeExtensionOptions` | | `defineExtension(opts)` | App-scoped lifecycle (`init`/`setup`) + shell UI host | `ExtensionOptions` | | `defineWidget(opts)` | Register a custom widget type (DOM via `mount`) | `WidgetExtensionOptions` | | `defineSidebarTab(opts)` | Add a left-sidebar tab (Vue or custom) | `DisposableHandle` | | `defineBottomPanelTab(opts)` | Add a bottom-panel tab | `DisposableHandle` | | `defineToolbarButton(opts)` | Add an action-bar button | `DisposableHandle` | | `defineCommand(opts)` | Register an invokable command | `DisposableHandle` | | `defineHotkey(opts)` | Bind a key combo to a command id | `DisposableHandle` | | `defineSetting(opts)` | Add a settings-menu entry | `DisposableHandle` | | `defineAboutBadge(opts)` | Add a badge to the About page | `DisposableHandle` |
Imperative carve-outs (fire-and-forget, not `defineX`, no handle): `toast`, `notify`.
A single extension file typically exports a default `defineExtension`/`defineNode` result and calls the shell-UI `defineX` functions inside `setup()` or at module scope. They queue safely before the app boots.
Reacts to node lifecycle. `nodeCreated` fires once per node instance (typed in, pasted, duplicated, or loaded without an existing workflow). `loadedGraphNode` fires once when a node is restored from a saved workflow (widget values already populated). Exactly one of them fires per node entity, never both.
import { defineNode, onNodeMounted, onNodeRemoved } from '@comfyorg/extension-api'
export default defineNode({
name: 'my-org.executed-logger',
// Filter to specific comfyClass names. Omit to receive every node type.
nodeTypes: ['KSampler', 'KSamplerAdvanced'],
// MUST be synchronous. Runs inside a Vue EffectScope; everything registered
// here (subscriptions, onNodeMounted) auto-disposes when the node is removed.
nodeCreated(node) {
// Read-only invariants
console.log(node.type, node.comfyClass, node.id)
// Subscribe to backend execution completion (replaces onExecuted patching)
node.on('executed', (e) => {
console.log('output:', e.output) // Record<string, unknown>
})
// Lifecycle hooks — call SYNCHRONOUSLY (never after an await)
onNodeMounted(() => {
// Node fully mounted; DOM/canvas ready.
})
onNodeRemoved(() => {
// Cleanup: abort fetches, close sockets. Does NOT fire on subgraph promotion.
})
},
loadedGraphNode(node) {
// Node restored from a saved workflow; widget values are already set.
}
})| Member | Kind | Notes | |--------|------|-------| | `id: string` | readonly | Opaque token. Compare with `node.equals(other)`, never by slicing. | | `equals(other)` | method | Canonical identity comparison. | | `type: string` | readonly | LiteGraph node type. | | `comfyClass: string` | readonly | Backend class name. | | `getProperty<T>(key)` / `getProperties()` / `setProperty(key, v)` | methods | Per-instance props (migration shim — prefer widget values). | | `getInputs()` / `getOutputs()` | methods | `ReadonlyArray<Readonly<SlotInfo>>` — frozen views. | | `on('executed', fn)` | method | Execution complete → `NodeExecutedEvent { output }`. | | `on('removed', fn)` | method | Node deleted (not subgraph promotion). | | `on('configured', fn)` | method | Loaded from saved workflow (after widget values restored). | | `on('beforeSerialize', fn)` | method | **Deprecated** — use widget-level `before
This project is no longer maintained. ComfyUI now ships official agent and MCP tooling — Comfy Agent and Comfy MCP — built and supported by the Comfy-Org team with deeper integration than a community project can match.
Repo: artokun/comfyui-mcp
Train custom LoRAs with ostris AI-Toolkit. Covers WAN 2.2/2.1 (people, styles, video motion) and Z-Image (Turbo & Base, low-VRAM image LoRAs). Use when the…
Anime/illustration text-to-image (ANIMA 1.0, ~2B Cosmos DiT). Use for anime, manga, illustrated characters; accepts Danbooru tags + natural language;…
Train a custom anime LoRA on the ANIMA base model with Citron's local Gradio trainer (kohya sd-scripts), <6GB VRAM, character/style LoRAs; covers setup,…
Discover Civitai models with the BUILT-IN download_model action:"search_civitai" and install/generate them locally. Find a checkpoint/LoRA/embedding on…
Diagnose and fix video/image color OBJECTIVELY with the get_image (action:"analyze_color") tool (scopes/stats such as black/white points, contrast, saturation,…
Core ComfyUI knowledge covering workflow format, node types, pipeline patterns, and MCP tool usage