Configuration & defaults (defaults.json)
Every plugin reads a defaults.json file from its bundle at first
instantiation and uses it to seed the values shown in the host’s
parameter panel — the ComfyUI server URL, the shared-folder mount paths
for each OS, caching toggles, timeouts, and so on.
The prebuilt bundles ship with the project’s own studio defaults baked in. Those won’t work on your network — see Customizing for your studio below.
How the defaults are organised
AIFX keeps a single source of truth for the studio-wide configuration
and merges it with per-plugin overrides at build time, so every
bundle ends up with one complete defaults.json and no runtime lookup
is needed.
aifx/
├── config/
│ └── defaults-base.json ← studio-wide: server + storage + controls
├── plugins/
│ ├── depth_da3/
│ │ ├── defaults-project.json ← per-plugin: project block + overrides
│ │ └── …
│ ├── depth_crafter/
│ │ ├── defaults-project.json
│ │ └── …
│ └── …
└── tools/
└── merge-defaults.py ← simple JSON merge invoked from CMake
At build time, each plugin’s CMakeLists.txt runs a POST_BUILD step
that calls merge-defaults.py BASE PROJECT OUTPUT, producing the
final <Plugin>.ofx.bundle/Contents/Resources/config/defaults.json.
Merge rules
- Top-level keys in
defaults-project.jsonoverride the corresponding keys indefaults-base.json. - When both sides have the same key with object values, they are
shallow-merged (per-plugin entries override base entries). This lets
a plugin tweak just
controls.timeoutwithout restating the entirecontrolsblock. - Top-level keys present only in
defaults-project.json(e.g.project) are added wholesale to the output.
Where the final file lives
| Location | Path |
|---|---|
| Source — studio config | config/defaults-base.json |
| Source — per-plugin overrides | plugins/<plugin>/defaults-project.json |
| Built bundle | <Plugin>.ofx.bundle/Contents/Resources/config/defaults.json |
The merged file is only present in the built bundle; the source tree never contains a merged version.
Schema
The merged defaults.json produced for every plugin has this shape.
Values shown here are generic placeholders — the prebuilt bundles
substitute the project’s studio values, and you replace them with your
own when deploying.
{
"server": {
"serverAddress": "comfyui.example.local",
"serverPort": 8188
},
"storage": {
"serverMountPath": "\\\\HOSTNAME\\share",
"localMountPath": {
"macos": "/Volumes/comfyui-share",
"windows": "\\\\HOSTNAME\\share",
"linux": "/mnt/comfyui-share"
}
},
"controls": {
"enableProcessing": false,
"enableCache": true,
"timeout": 600,
"asyncMode": 1,
"placeholderMode": 1
},
"project": {
"workflowName": "<plugin-slug>",
"workflowFile": "resources/workflow/<plugin-slug>.json",
"outputVersion": "v001"
}
}
server block — the ComfyUI endpoint
Lives in config/defaults-base.json (shared across all plugins).
serverAddress,serverPort— where the plugin sends ComfyUI workflow jobs over HTTP.
storage block — the shared-storage mounts
Lives in config/defaults-base.json. The plugin runs inside the host
application (Flame / Nuke / Resolve / …), which may be on a different
machine than the ComfyUI server; both sides read/write the same shared
storage but mount it at different paths. So the panel exposes two mounts —
this surfaces in the Storage Mounts group of the parameter panel as
Local Storage Mount and ComfyUI Server Mount:
serverMountPath— the shared storage as mounted on the ComfyUI server: a UNC path (\\\\HOSTNAME\\share) or drive letter (Z:\\share) if ComfyUI runs on Windows, a POSIX path (/mnt/share) if it runs on Linux or macOS. This is the path written into the workflow sent to ComfyUI: itsLoadEXR/SaveEXRnodes read inputs and write outputs through it.localMountPath— the shared storage as mounted on this host, used for the plugin’s own EXR I/O. Because a plugin bundle only ever runs on the OS it was built for, this is given as an object keyed by OS (macos/windows/linux); the build for each platform seeds the Local Storage Mount default from its own entry. If you leave the field blank at runtime, the plugin falls back toserverMountPath(use this when the host reaches the storage at the same path as the server).
At submit time the plugin rewrites the local path into the server view —
swapping the local-mount prefix for the server-mount prefix — and that is
what ComfyUI receives. The separator style is taken from
serverMountPath itself: a UNC or drive-letter value yields backslashes,
anything else yields forward slashes. A Linux ComfyUI treats \ as an
ordinary filename character, so getting this wrong makes every path
unresolvable; set serverMountPath in the server’s own convention.
UNC paths use doubled backslashes in JSON (\\\\HOSTNAME\\share) —
each \ is escaped, so \\\\ in the file becomes a literal \\ on the
wire, which is a valid UNC path.
Output paths are derived, not configured. The plugin builds the output location at runtime from the storage mount plus the runtime
projectNameparameter and theworkflowName/outputVersionfrom theprojectblock (roughly{mount}/out/{projectName}/{workflowName}/{outputVersion}). It both writes the job request and reads the result back through its own mount, so there is no separate output-directory field to keep in sync.
controls block — runtime behaviour
Lives in config/defaults-base.json. Any plugin may override individual
fields via its own defaults-project.json (e.g. fast-inference
plugins override timeout to a shorter value).
enableProcessing— master switch. Defaultfalseso the plugin doesn’t start firing jobs as soon as the artist drops it on a clip. Toggled by the artist via the OFX parameter panel.enableCache— whentrue, the plugin checks the shared output folder for an existing EXR matching the workflow hash before submitting a new job. Critical for interactive scrubbing.timeout— how long the plugin waits for a single ComfyUI job before declaring it failed (seconds).asyncMode—0blocks the host thread until the result comes back (simple but freezes the UI);1queues jobs in a background thread and the host stays responsive. Always use1in production.placeholderMode— what the plugin returns while a real result is still rendering.0returns black frames;1passes the source through unmodified.1is the usual choice — the artist sees the comp evolve as results land.
project block — workflow identification
Lives in each plugin’s defaults-project.json (per-plugin only — there
is no project block in the base file).
workflowName— a tag the plugin uses for the on-disk output folder hierarchy (so multiple workflows for the same shot don’t collide).workflowFile— the workflow JSON the plugin submits. This value seeds the runtime Workflow File parameter (workflowFilePath, see Runtime path parameters below), and how it resolves depends on its form:- A
resources/…-prefixed value (e.g.resources/workflow/depth_crafter.json) is bundle-relative — the plugin resolves it against<Plugin>.ofx.bundle/Contents/Resources/. This is the usual case. - An absolute path is used as-is.
Change this to point at a custom workflow you authored — see Workflow customization.
- A
outputVersion— version suffix appended to the output folder. Bump (e.g.v001→v002) when you want a clean re-render alongside prior results.
Runtime path parameters (not in config)
Some paths the plugin uses are OFX parameters shown in the host’s
parameter panel, not keys in defaults-base.json /
defaults-project.json. They’re listed here for completeness because
they hold or build filesystem paths, even though you don’t set them in
the JSON config:
workflowFilePath(label Workflow File, typeeStringTypeFilePath) — the live path to the workflow JSON the plugin actually loads. Its default is seeded from theproject.workflowFileconfig key above, and it resolves by the same rules (resources/…→ bundle-relative; absolute → as-is). The artist can override it in the panel to point at a custom workflow. There is noworkflowFilePathconfig key — configure the default viaproject.workflowFile.projectName(label Project Name) — an artist-entered name that becomes a component of the output path the plugin reads results back from ({mountPath}/{projectName}/…). It has no config-file counterpart; it’s intentionally per-shot and set in the panel. Leaving it empty turns the project-name status indicator black as a reminder.
This is why the output location never appears in the config file (see
Why there are input directories but no output
directories):
it’s assembled at render time from mountPath (config) plus the
runtime projectName, workflowName, and outputVersion.
Status indicators (read-only runtime parameters)
The parameter panel shows two read-only fields that the plugin updates automatically as a job moves through its lifecycle — they are not config keys and the artist never edits them:
jobStatus(label Status) — a short text line describing what the plugin is doing right now (e.g.Ready,Writing 48 frame(s) to disk…,ComfyUI processing 48 frame(s) — 12s (poll 4),3 frame(s) done).jobStatusColor(label Status Color) — a colour swatch giving the same information at a glance, so you can read progress without parsing the text. It is the quickest way to see whether a clip is idle, working, finished, or errored.
The colour follows the processing lifecycle in order:
| Colour | Meaning |
|---|---|
| Gray | Idle — no jobs running (Ready). |
| Cyan | Collecting frames from the timeline (after Collect & Submit). |
| Orange | Writing the input frames (EXRs) to the shared disk. |
| Amber | Submitting the workflow to ComfyUI. |
| Yellow | ComfyUI is processing the workflow. |
| Green | All frames ready / job done. |
| Red | Error — the job failed (the Status text carries the message). |
Cyan → orange → amber → yellow trace a job from collection to completion; green means done and red means it stopped on an error. Frame-based plugins (one job per frame) skip the cyan collection step and go straight to yellow while frames render; sequence plugins (Collect & Submit a whole range at once) show the full progression.
Per-plugin override examples
Most plugins ship a minimal defaults-project.json with just the
project block — they inherit everything from the base:
// plugins/depth_crafter/defaults-project.json
{
"project": {
"workflowName": "depth_crafter",
"workflowFile": "resources/workflow/depth_crafter.json",
"outputVersion": "v001"
}
}
A plugin that overrides one control field — for example, a fast
per-frame plugin that doesn’t need the default 600-second timeout —
adds a partial controls block that gets shallow-merged on top of
the base:
// plugins/depth_da3/defaults-project.json
{
"project": {
"workflowName": "depth_da3",
"workflowFile": "resources/workflow/depth_da3.json",
"outputVersion": "v001"
},
"controls": {
"timeout": 300
}
}
The merged defaults.json in the bundle ends up with every base
controls field plus timeout: 300 from the override.
Customizing for your studio
You have three ways to make the plugins point at your own ComfyUI server and shared filesystem.
1. Edit the parameters in the host UI (simplest, per-clip)
Every field in defaults.json is also exposed as an OFX parameter in
the plugin’s parameter panel. The values from defaults.json are
just initial values — the artist can override any of them per clip in
the host UI, and those overrides are saved with the project file.
This is the right approach if you only need to test on a different
server occasionally or on a per-shot basis.
2. Edit defaults.json in the installed bundle (per-machine)
Each installed bundle has its own copy of defaults.json (the merged
file produced at build time). You can edit it in place:
# macOS, per-user install:
~/Library/OFX/Plugins/<Plugin>.ofx.bundle/Contents/Resources/config/defaults.json
# Linux:
~/OFX/Plugins/<Plugin>.ofx.bundle/Resources/config/defaults.json
# Windows:
%LOCALAPPDATA%\OFX\Plugins\<Plugin>.ofx.bundle\Resources\config\defaults.json
Edit in any text editor, save, restart the host. The defaults reload on the next plugin instantiation.
This is the right approach for a studio TD setting up a single
machine or rolling out a uniform config across many machines. A
central script that overwrites each installed defaults.json is a
common pattern.
3. Edit config/defaults-base.json in source and rebuild (per-build)
If you maintain a fork of AIFX, edit the single
config/defaults-base.json in your fork once and re-run
tools/build-plugin.sh (or tools/release-macos.sh for the full
suite). The merge step bakes your studio defaults into every bundle
you build, no per-plugin file changes required.
This is the right approach for shops with their own internal release pipeline.
Recommended template for a new studio
If you’re starting from scratch, replace config/defaults-base.json’s
server block with values matching your environment. Two common
shapes:
Single workstation (server runs locally on the host)
{
"server": {
"serverAddress": "127.0.0.1",
"serverPort": 8188
},
"storage": {
"serverMountPath": "/home/<you>/comfyui-share",
"localMountPath": {
"macos": "/Users/<you>/comfyui-share",
"windows": "C:\\Users\\<you>\\comfyui-share",
"linux": "/home/<you>/comfyui-share"
}
},
"controls": {
"enableProcessing": false,
"enableCache": true,
"timeout": 600,
"asyncMode": 1,
"placeholderMode": 1
}
}
When the host and the ComfyUI server are the same machine, the local
mount and the server mount are identical — you can leave Local Storage
Mount blank at runtime and it falls back to serverMountPath.
Studio with a Windows ComfyUI / storage server and macOS / Linux clients
The ComfyUI server is the Windows storage box, so serverMountPath is the
UNC path written into every submitted workflow. localMountPath carries
each client OS’s own view of the same share; the build for each platform
seeds its Local Storage Mount default from the matching entry.
{
"server": {
"serverAddress": "comfy.studio.local",
"serverPort": 8188
},
"storage": {
"serverMountPath": "\\\\HOSTNAME\\comfy-share",
"localMountPath": {
"macos": "/Volumes/comfy-share",
"windows": "\\\\HOSTNAME\\comfy-share",
"linux": "/mnt/comfy-share"
}
},
"controls": {
"enableProcessing": false,
"enableCache": true,
"timeout": 600,
"asyncMode": 1,
"placeholderMode": 1
}
}
(serverMountPath is the path ComfyUI itself uses to read inputs and
write outputs; the Local Storage Mount is what each client machine
uses for its own local I/O.)
Studio with a Linux ComfyUI / storage server
The Flare/Flame host and ComfyUI can share one Linux box (the fastest
setup — no network hop for the EXRs), or clients can reach a Linux server
over a mounted share. Either way serverMountPath is a POSIX path, and
the plugin submits forward-slash paths to ComfyUI.
{
"server": {
"serverAddress": "127.0.0.1",
"serverPort": 8188
},
"storage": {
"serverMountPath": "/mnt/comfy-share",
"localMountPath": {
"macos": "/Volumes/comfy-share",
"windows": "\\\\HOSTNAME\\comfy-share",
"linux": "/mnt/comfy-share"
}
},
"controls": {
"enableProcessing": false,
"enableCache": true,
"timeout": 600,
"asyncMode": 1,
"placeholderMode": 1
}
}
If the plugin and ComfyUI run on the same Linux machine, set the two to the same path (or leave Local Storage Mount blank).
What NOT to change
controls.asyncModeshould stay at1in production. Synchronous mode is only useful for debugging.project.workflowFileshould match an actual file under the bundle’sResources/workflow/. Pointing it at a non-existent path breaks the plugin at first invocation. If you want a custom workflow, see Workflow customization.
See also
- Installation — getting the plugins onto your machine.
- ComfyUI server setup — standing up the model server that the plugin talks to.
- Workflow customization — replacing the ComfyUI workflow JSON without changing the plugin.
- Troubleshooting — common errors related to paths, server connectivity, and timeouts.