Install any skill in seconds. Free to start, no credit card required.
Get Started Free →artokun/comfyui-frontend-extensions
Authoring ComfyUI v2 frontend extensions with @comfyorg/extension-api — defineNode/defineExtension/defineWidget, shell UI (sidebar tabs, commands, hotkeys), typed events, and handles.
Passed 22 of 22 test cases with the skill, and 6 of 22 without it.
and 28 more in the full report
16 fixed6 passed either way0 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 16 test cases the skill fixed. Same model, same prompt, with and without the skill.
I want to add a boolean toggle setting titled 'Enable auto-save' to the ComfyUI settings dialog from a modern TypeScript extension. What API function should be used?
| Checked | Without skill | With skill |
|---|---|---|
| Registers the settings entry using defineSetting. | Missed | Passed |
| Specifies setting configuration properties including id, name, and defaultValue. | Passed | Passed |
The instructions your model reads when the skill loads.
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.mdfor 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:
import { defineNode } from '@comfyorg/extension-api'. No window.app dependency at module evaluation time.getValue() reads; setValue() dispatches an undo-able, serializable command. Read-only invariants (set at construction) are readonly accessors (node.type, widget.name).on(...) subscriptions. Each returns an Unsubscribe cleanup function. No Vue refs/signals are ever exposed; Vue reactivity is the internal engine only.defineX returns a DisposableHandle with an idempotent, synchronous dispose().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 |
test cases passed, vs 6 / 22 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.