Filesmith uses three kinds of AI model. None of them is baked into the app, so you can add your own.
| Kind | Used by | Where the files live |
|---|---|---|
| Real-ESRGAN (ncnn) | Upscale | Bundled, plus %APPDATA%\Filesmith\models\realesrgan |
| ComfyUI upscale models | Upscale (NVIDIA) | Your ComfyUI models\upscale_models, read in place |
| Image generation models | Generate | Your ComfyUI models\checkpoints, diffusion_models, unet |
All of Filesmith's own data lives in %APPDATA%\Filesmith. Your ComfyUI folder is only read, except
for one case: Download required files on Generate writes text encoders and VAEs into it.
Generate and the Upscale AI models both read one remembered ComfyUI folder. Filesmith guesses common
locations (your profile, Documents, OneDrive, drive roots, names like ComfyUI,
ComfyUI_windows_portable, StabilityMatrix, plus ComfyUI Desktop's settings in
%APPDATA%\ComfyUI). If the guess misses, set it yourself. Any of these works:
- Settings > Tools > ComfyUI folder > Choose folder (or Change folder).
- Generate, with no model found: Choose ComfyUI folder.
- Generate > Your models > Change ComfyUI folder.
- Generate, when ComfyUI was not found: Locate my ComfyUI folder.
- Upscale > AI models > ComfyUI models: Locate my ComfyUI folder or Browse to ComfyUI folder (Change ComfyUI folder or Change folder once one is set).
- CLI:
filesmith setup comfy --folder "D:\ComfyUI".
You can pick the ComfyUI root, its models folder or its upscale_models folder. The choice is stored
in %APPDATA%\Filesmith\comfy-upscalers.json. One pick fixes Generate, Upscale and the companion
downloads at once.
The Model picker on Upscale lists the Real-ESRGAN models on disk, then AI models when an NVIDIA GPU that can run CUDA is present. If a GPU is too old for it, the picker says why.
- Upscale > Add your own model, or Settings > Tools > Upscale models > Open folder. Both open
%APPDATA%\Filesmith\models\realesrgan. - Drop in an ncnn model pair:
name.paramandname.bin. A.paramwithout its.binis ignored. - Reopen the Upscale picker. Your model shows as
Name, added by you. A bundled model with the same name wins.
Filesmith loads the ESRGAN-family files in ComfyUI's upscale_models (4x-UltraSharp, Remacri, NMKD,
AnimeSharp, RealESRGAN and similar) with spandrel, the loader ComfyUI itself uses. ComfyUI does not
need to be running and no workflow is involved. Files are referenced in place, never copied.
- Upscale > Model > AI models. The ComfyUI models card appears below.
- If the card says Set up upscale engine, the engine needs Python with torch and spandrel:
- If your ComfyUI's own Python already has both, nothing is downloaded. Use Locate my ComfyUI folder so Filesmith can find it.
- Otherwise Set up upscale engine builds a shared env in
%APPDATA%\Filesmith\pid, about 3 GB. PiD uses the same env, so if PiD is installed setup is quick.
- Choose Browse to ComfyUI folder (or Change folder). Filesmith scans:
upscale_modelsunder the folder you picked, at the usual nesting depths,- extra
upscale_modelspaths fromextra_model_paths.yaml, if present.
- Pick a model in the second AI model list. Each shows its native scale, for example
4x-UltraSharp, 4×. Use Rescan after adding or removing files.
The scan opens .pth, .safetensors and .ckpt. It skips .pt, because spandrel loads .pt without
the restricted unpickler, and a scan touches every file in the folder.
Each file gets a badge:
- Verified: spandrel read a known architecture (ESRGAN, RealESRGAN, SPAN, DAT, HAT, SwinIR, Compact, PLKSR and others), or the name matches a well-known model.
- Experimental: spandrel loaded it but the architecture is not on the list. Still fully usable; the
picker adds
, experimentalto the label. - Unsupported: spandrel could not load it (diffusion checkpoints, LoRAs, VAEs, unknown formats). These are listed under "N files not usable" with the reason.
Upscaling is tiled, so any image size fits in VRAM. Alpha is restored after the RGB pass. A model you remove from disk drops out of the picker on the next check.
PiD (a separate diffusion upscaler) also sits under AI models. It is offered once installed, or when its weights are found in your ComfyUI and can be reused.
Generate runs text-to-image through ComfyUI over its HTTP API. Filesmith connects to a running ComfyUI
(FILESMITH_COMFY_URL, a stored server URL, then http://127.0.0.1:8188), or launches your ComfyUI
headless on a free port with its own Python. Filesmith never installs ComfyUI.
Filesmith scans every ComfyUI models folder it knows:
checkpoints: single-file checkpoints (.safetensors,.ckpt,.sft).diffusion_modelsandunet: bare diffusion models (.safetensors,.sft,.gguf).
Each file's header is read (not the weights) to find its family. Built-in families: SDXL and single-file checkpoints, Flux 1, Flux 2 [klein], Z-Image Turbo and Krea 2. Video, 3D and audio models are dropped. An unrecognized image model is shown with a reason and a Try anyway button, which runs it through a generic graph.
If the scan finds nothing, the Model section shows No image model yet with two buttons:
- Choose ComfyUI folder: point Filesmith at a ComfyUI that has models.
- Add a model: import a registry entry or a ComfyUI workflow (see below).
A model that needs files you do not have shows Required files, with each file and its size.
Download required files fetches them into the same ComfyUI models tree the model lives in
(text_encoders, vae and so on). Disk space is checked first. Downloads are sha256-checked when the
registry has a hash. The CLI equivalent is filesmith setup generate --model <name>.
What a model family is (how to recognize it, which files it needs, which ComfyUI graph runs it) is data in JSON files, so a new family needs no app release.
Three layers, merged by id. Later layers win field by field.
| Layer | Path | Written by |
|---|---|---|
| 1. Built-in | <install>\resources\registry\*.json |
the installer, read-only |
| 2. Channel | %APPDATA%\Filesmith\registry\channel |
signed network updates (off today) |
| 3. Yours | %APPDATA%\Filesmith\registry\user |
you |
- An app update replaces layer 1 only. Your layer 3 files survive every update.
- Layer 1 ships in the installer, so an offline install has the full catalog.
- Open your folder from Settings > Tools > Model registry > Open folder, or Generate > Your models > Open folder. Edits are picked up the next time Generate checks, no restart needed.
If a model already works in ComfyUI:
- In ComfyUI, export the workflow in API format (Workflow > Export (API)).
- In Filesmith, Generate > Add a model and pick that
.json.
Filesmith turns it into a registry entry named after the file. It wires these inputs to placeholders:
the model loader (UNETLoader, UnetLoaderGGUF or CheckpointLoaderSimple), VAELoader,
CLIPLoader/DualCLIPLoader, the first CLIPTextEncode (prompt) and the second (negative),
EmptyLatentImage/EmptySD3LatentImage (size, batch), KSampler seed and steps, and SaveImage.
Sampler defaults are copied from the exported KSampler. A note tells you what it could not wire.
The file is saved in your user layer under a new name; an existing file is never replaced.
Add a model also accepts a registry entry or a pack ({ "schemaVersion": 1, "entries": [...] }).
When a Hugging Face repo moves, override just that field. Save this as
%APPDATA%\Filesmith\registry\user\fix-flux2.json:
{
"schemaVersion": 1,
"entries": [
{
"id": "flux2",
"kind": "generate",
"label": "Flux 2 [klein]",
"provenance": { "source": "user" },
"companionSets": [
{
"id": "4b",
"companions": [
{
"role": "clip",
"label": "Qwen3-4B text encoder",
"subdir": "text_encoders",
"identify": { "nameHint": "qwen_3_4b" },
"download": {
"filename": "qwen_3_4b.safetensors",
"approxSize": "8 GB",
"urls": ["https://huggingface.co/<new-location>/qwen_3_4b.safetensors"]
}
}
]
}
]
}
]
}Everything else about flux2 (graph, sampler, required nodes) comes from the built-in entry.
Start from a copy of an entry in resources\registry\gen-archs.json. A generate entry has:
-
detect: how to recognize the file from its contents, used only for files the built-in classifier could not place."detect": { "tensorKeys": { "all": ["cap_embedder", "noise_refiner"], "none": ["double_blocks"] }, "metaArch": ["z-image", "zimage"], "sizeBytesRange": [4000000000, 14000000000], "nameHint": "z.?image" }
Tensor keys match as substrings in the safetensors header.
allmust all be present,anyneeds one,nonerejects.nameHintscores far below content and never outvotes it. -
capabilities:{ "task": "text-to-image", "minDim": 256, "maxDim": 2048, "dimStep": 8 }. -
sampler: the defaults the UI fills in. A distilled or turbo model needs"cfg": 1."sampler": { "name": "res_multistep", "scheduler": "simple", "steps": 8, "cfg": 1, "guidance": 0, "hasGuidance": false }
-
requires: ComfyUI nodes, checked against the live server before anything is queued, so a missing node gives a clear message."requires": { "nodes": ["CLIPTextEncode", "KSampler", "VAEDecode", "SaveImage"], "clipLoader": { "node": "CLIPLoader", "type": "lumina2" }, "minComfyNote": "This needs ComfyUI v0.6.0 or newer." }
-
companionsorcompanionSets: the encoder and VAE files, with download URLs. -
workflow: a ComfyUI API-format graph,{ "format": "comfy-api-v1", "template": { ... } }. Useworkflowfor a bare diffusion model,checkpointWorkflowfor a single-file checkpoint andggufWorkflowfor a GGUF. An entry can have several.
Placeholders:
${unet} ${clip} ${clip2} ${vae} ${model} ${prompt} ${negative} ${seed} ${steps}
${cfg} ${guidance} ${sampler} ${scheduler} ${width} ${height} ${batch} ${prefix}
A value that is exactly one placeholder gets the raw value, so "seed": "${seed}" becomes a number.
Entries are validated at load. A bad entry is skipped with a warning and the rest keeps working.
subdirmust be one oftext_encoders,clip,vae,checkpoints,diffusion_models,unet,upscale_models. It is joined onto your ComfyUI models folder, so anything else is a path risk.filenamemay only use letters, digits,.,_and-.- Download URLs must be
https:. - A workflow must be
{class_type, inputs}nodes and use only the placeholders above. - Workflows are data: parsed as JSON, never run as code, and only sent to a local ComfyUI.
- An entry with a newer
schemaVersionthan your Filesmith is skipped with a note to update.
To see registry warnings, run filesmith doctor.
Every download in resources\registry\gen-archs.json has a sha256 and a URL pinned to a commit, with
the resolve/main URL after it as a fallback. Hugging Face LFS object ids are the sha256 of the file.
node scripts/registry-hashes.mjs # refresh hashes and pins from upstream
node scripts/registry-hashes.mjs --check # fails if the pack is stale (for CI)
The hash is not enforced against the fallback URL, because the branch copy may legitimately differ. A fallback uses trust-on-first-use. A gated or renamed repo is left as is and reported.
The channel lets a signed pack fix dead URLs on every install without a release. It is off until a
signing key exists: CHANNEL_PUBLIC_KEY_B64 in src\main\registry\channel.ts is empty.
To turn it on, once:
node scripts/registry-channel.mjs keygen
This writes channel-private.pem (gitignored; back it up, losing it means no install accepts another
update) and prints the public key for CHANNEL_PUBLIC_KEY_B64. Then, whenever something moves:
node scripts/registry-hashes.mjs
node scripts/registry-channel.mjs sign resources/registry/gen-archs.json
node scripts/registry-channel.mjs verify channel.json <publicKeyB64>
Publish channel.json at the URL in FILESMITH_CHANNEL_URL (a GitHub Pages file is enough). Installs
check at most once a day in the background. A bad signature, a malformed pack or no network keeps the
previous cache.