ZenTrainer
LoRA training and inference apps for ComfyUI: open /zentrainer/ after installing.
Nodes (5)
The captioning node you never actually configure
Your instruction and your photo, wired the way the LoRA was trained
One wire, one input, and MOSS Image finally reads your photo
Click a face, get a training mask
Your whole LoRA run hides behind one text field

Train LoRAs inside ComfyUI, and watch them learn. ZenTrainer trains on ComfyUI's own model code, with the models and GPU it already has.
- Characters, styles and video: MOSS Image, Krea 2, FLUX 3, FLUX.2 Klein, Qwen Image 2.1, Z-Image, Anima, Fibo 2.0, SDXL (and its finetunes) and MiniMax H3 video, each trained end to end here; more are listed as untested
- Straight into ComfyUI: trained LoRAs show up in its LoRA loaders
- Simple or Advanced: a recipe sets everything, or set every option yourself
Quick start
- Install ZenTrainer from ComfyUI Manager, restart ComfyUI and click the lotus in its top bar.
- New run → Simple: pick a recipe, add 15–40 photos, name it. Missing models are downloaded and the photos captioned for you.
- Watch it train. The LoRA lands in
output/zentrainer/loras/.
Training you can watch
Each run is one page: the newest samples beside the loss, each sample denoising as it renders, and the numbers in a rail on the right.
- Pause, sample, save or change the learning rate mid-run
- Resume from any checkpoint
- Validation loss on a fixed set, and a likeness score for character LoRAs
- Try a prompt on any checkpoint
- Progression: every prompt across every step (←/→ steps, ↑/↓ prompts)
- A queue: line runs up and they train one after another

Datasets
Any folder in ComfyUI's input/ is a dataset: browse it as a grid or a table, edit captions in place.
- Auto-caption with Qwen-VL or Gemma, through ComfyUI
- Caption sets: long and short side by side; train on either, or a mix
- Bulk edits: prefix, suffix, find and replace
- Masks: SAM3 finds the subject, or paint one; it trains only where the mask is white

Set up a run
Pick a model and its files are filled in (base, text encoder, VAE), each installed or one click from downloading. Start from a recipe, ours or one you saved, and the form flags the usual mistakes: no trigger word, a learning rate the optimizer won't like, too few epochs.
- Trigger word, and
[trigger]in captions and prompts - Optimizers: AdamW, Prodigy, Lion, CAME, schedule-free, 8-bit and more
- LoRA or LoKr, masked training, caption dropout
- Class preservation: "a woman" stays a woman, not your character
- Preview on a turbo build while training the base

Simple mode
Pick a recipe, add photos, name it, train. See each preview land, and try your own prompt at any step. Switch to Advanced in Settings for every option.

Apps (experimental)
Test LoRA renders checkpoints × strengths × prompts on a fixed seed; Generate is plain txt2img with your LoRAs. Turn them on in Settings → Experimental pages. → Writing apps
Install
As a node pack: install ZenTrainer from ComfyUI Manager (or clone it into
ComfyUI/custom_nodes/), restart ComfyUI and click the lotus, or open /zentrainer/ on its port.
Needs ComfyUI 0.41 or newer. Extra optimizers: pip install -r requirements-optional.txt.
With its own pinned ComfyUI: training stays apart from your main install, so updating it or its custom nodes can't break a run. It reads your models where they are.
# Linux
git clone https://github.com/Nynxz/ZenTrainer && cd ZenTrainer && ./start-linux.sh
On Windows, install Git for Windows, clone the repository and
double-click start-windows.bat.
The first run installs uv, asks where your models are, picks the PyTorch build for your GPU (CUDA or ROCm) and starts; after that it opens a menu. macOS isn't supported yet.
On a rented GPU: a Docker image with the app behind a password. On Runpod it's one click (a referral link: it supports ZenTrainer at no cost to you). Elsewhere → docker/README.md
<a href="https://console.runpod.io/hub/template/2amo4895gj?ref=oe5l65t0"><img src="docs/images/badge-runpod.webp" height="32" alt="Deploy on Runpod"></a>
Run it (zt)
zt is the command line behind the start scripts. From a clone it's scripts/zt; for zt
anywhere, uv tool install --editable ./cli.
zt # the menu: setup, updates, start, monitor
zt setup --models-from /path/to/your/ComfyUI # pinned ComfyUI, reading your models
zt start --open # http://127.0.0.1:8189/zentrainer/
zt monitor # live dashboard: queue, runs, loss, memory
zt doctor # what's installed, where models come from
zt update # pull ZenTrainer, re-sync ComfyUI and the web app
Headless: zt new > spec.json, zt check spec.json, zt train spec.json --follow. zt --help
lists the rest. Guides: docs/cli.md, docs/api.md (the HTTP API) and
docs/spec.md (every setting).
--models-fromtakes a ComfyUI install or a models folder;--extra-model-pathstakes a yamlzt attach /path/to/ComfyUIlinks the engine into a ComfyUI you already have instead- Your work lives in
comfyui/input/(datasets),comfyui/output/zentrainer/loras/andcomfyui/user/zentrainer/(runs): reinstall withzt update, not by deletingcomfyui/ - Compiled blocks (off unless turned on, in Memory → Compile blocks): the first run at a new
resolution builds its kernels, a few minutes on Linux with NVIDIA and 10–25 on ROCm or Windows.
They're cached in
~/.triton, so later runs start fast
How it works

The training loop is ZenTrainer's own, with ComfyUI as a library rather than workflows. While a run trains it holds ComfyUI's queue, so nothing else lands on the GPU mid-step. More in docs/ARCHITECTURE.md.
engine/ ComfyUI node pack: training harness (ComfyUI as a library), run API, session node
web/ Vue app (zenkit-ui, ZenKit themes), served by ComfyUI at /zentrainer/
tests/ harness tests that need no ComfyUI
scripts/ zt (setup, start, dev, …); devrun.py runs a spec through the harness without the server
docker/ the container image for cloud GPUs (Runpod, …)
docs/ architecture, apps, guides; banner/ holds the README pictures' sources
Develop
zt dev runs ComfyUI and the web app with hot reload at http://localhost:5173/zentrainer/;
engine edits need zt restart. comfy.lock pins the ComfyUI commit and torch build it's tested
against: move it with zt update --ref <commit|tag>.
# tests (no GPU)
CUDA_VISIBLE_DEVICES= uv run --no-project --with pytest --with torch --with pillow --with numpy \
--with aiohttp --with safetensors --with av python -m pytest tests
# a spec straight through the harness (see examples/)
comfyui/.venv/bin/python scripts/devrun.py examples/sdxl-quick.json --comfy comfyui
# README pictures: the app's panels (from an install holding only demo content), then the images
uv run --with playwright --with pillow --no-project python docs/banner/shots.py --url http://127.0.0.1:8188 --run <id> --dataset <folder>
uv run --with playwright --with pillow --no-project python docs/banner/render.py
Credits
Code ZenTrainer carries from other projects, and its licences, is listed in THIRD_PARTY_NOTICES.md.
- Faces: InsightFace's models (non-commercial use only), or for commercial use fal's AuraFace with OpenCV's YuNet. The face pipeline follows InsightFace's and OpenCV's.
- ai-toolkit by Ostris: the Automagic v3 and v4
optimizers, the weighted timestep table and the training adapters. Also ideas: sigmoid
timesteps, the content/style bias,
[trigger]in captions and MOSS Image Edit's picture layout. - Fizgig by Peter Neill: ideas, likeness scoring of samples among them; the measurements behind EMA 0.98, MiniMax H3's adapter blocks 20-49 and the sharpest-frame clip stills; and the W8A16 int8 backward kernel by mabseyuk.
- VGL by Bria: Fibo 2.0's caption schema and prompts.
- OneTrainer by Nerogar: ideas ZenTrainer follows:
compiling the repeated transformer block, the int8 backward on int8 tensor cores, and reading
its
-masklabelmask files. - @0xDELUXA: AMD support's start: the ROCm PyTorch setup and whole-card VRAM on Windows (#1).
- @aksugat: the RDNA3 int8 tile set, swept on an RX 7800 XT.