Remote CLIP Text Encode (Flux Klein) ⚡
Klein's Text Encoder Won't Fit on 8GB, So Let the Mac Encode the Prompt
- conditioning
The problem it's aimed at
By 2026 the text encoder stopped being a rounding error. Klein's encoder is a Qwen3 LLM - Qwen3-4B for the 4B model, Qwen3-8B for the 9B, a Qwen3-VL-4B for Flux.3 Klein - and 8GB to 18GB of weights is not unusual for that class of component. On an RTX 4060 8GB that means ComfyUI spends the gap between "you hit queue" and "sampling started" shuffling gigabytes across PCIe, and sometimes it just OOMs instead. This is the whole reason the "encoder has its own budget" argument exists: you're not fitting one model, you're fitting two.
Remote CLIP Text Encode (Flux Klein) ⚡ is the blunt fix. It replaces the normal CLIPTextEncode in a Flux.2 Klein or Flux.3 Klein graph, and instead of loading the encoder on your GPU it posts your prompt over your LAN to a Mac sitting on the same desk, where Apple Silicon's unified memory holds the encoder permanently and runs the forward pass on MPS. Local VRAM cost: zero. If you happen to own a Mac and a gaming PC, this is the most hardware-synergy thing in ComfyUI right now.
How the round trip actually works
The node is a thin client. It builds a JSON metadata blob (model_type plus your prompt), wraps it in a safetensors container, and POSTs it as application/octet-stream to /v1/encode/{model_name} on the Mac. Safetensors rather than pickle, deliberately - the server can't be made to execute anything.
On the Mac, a FastAPI bridge keeps a small pool of loaded encoders, runs the forward pass, and sends back the conditioning tensors in the same binary format. Then the interesting part: the encoder path matches native ComfyUI. Flux.2 Klein uses hidden states from layers 9, 18 and 27, stacked and reshaped to [batch, seq_len, 12288]. Flux.3 Klein taps eight layers - 4, 8, 12, 16, 20, 24, 28, 32 - which flattens to [batch, seq_len, 20480]. Returns in bf16.
One consequence you should internalize: this is an LLM reading a chat turn, not CLIP reading tags. Write sentences. (face:1.4) is inert punctuation here, and masterpiece, best quality is noise.
The two fields
model_name- a dropdown of three folder names:flux2-klein-4b-uncensored-text-encoder,flux2-klein-9b-uncensored-text-encoder,Qwen3-VL-4b-Heretic. It has to match the folder name inside the Mac's models directory, because that string is both the URL route and the thing the server sniffs to decide which architecture to load. The 🔄 Fetch Models from Server button queries/v1/modelsand repopulates the list.text- your prompt, multiline, dynamic prompts allowed.
Output is a single conditioning, wired into your Flux guider/sampler exactly where a CLIPTextEncode used to go. Distilled Klein at CFG 1 doesn't really consume a negative, so most people just run one of these. If your graph wants both, wire a second instance.
Installing it
Client side is easy - the pack's requirements.txt is just requests and safetensors:
cd ComfyUI/custom_nodes
git clone https://github.com/j0eyhu/ComfyUI-MacOffload-TE
Restart ComfyUI; the node shows up under ⚡ MacOffload/Conditioning. Then create macoffload_config.json inside the pack folder - the repo ships only macoffload_config.example.json, so copy and rename it:
{ "server_url": "http://192.168.1.42:8288" }
Or skip the file and set MACOFFLOAD_SERVER_URL in your ComfyUI launch script. The address lives only on your disk, never in workflow JSON, which is a genuinely good decision - a shared workflow can't point your machine at someone else's server.
The Mac side is the real work. In server/, make a venv, pip install -r requirements.txt (a pinned torch 2.14 / transformers 5.19 / FastAPI stack - expect several GB), copy .env.example to .env, set MODELS_DIR, drop the Hugging Face encoder repos in as folders, then python server.py. Port 8288 by default.
Where it bites
Connection refused. Test it from the PC before you blame ComfyUI: curl http://<mac-ip>:8288/health. If that hangs, it's the macOS firewall or a different subnet, not the node.
First run times out. The client waits up to 300 seconds for a response, and the first request is also the one that loads a multi-GB encoder into unified memory. Warm it up with a throwaway tiny graph before queueing a batch.
Wrong conditioning, silently. If you rename a model folder on the Mac, the server's type detection falls back to name heuristics and can load the wrong encoder class. Keep the folder names as published.
Two models, one Mac, MAX_MODELS=1. Switching between a 4B and 9B encoder means evicting and reloading on every swap. Bump MAX_MODELS=2 in .env if you've got the RAM.
Honest verdict
This pack is obscure - essentially zero discussion in the community corpora, and its niche is narrow: you need a Mac with enough unified memory and a VRAM-poor PC on the same LAN. If that's you, it solves a problem quantization only half-solves, and it keeps your diffusion model resident. If you don't own the Mac, you're better off with a hard-quantized Qwen3 encoder and the ordinary CLIPTextEncode - same conditioning path, one less machine to keep alive.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| model_name | COMBO | flux2-klein-4b-uncensored-text-encoder | Model folder name on remote Mac server. Click 'Fetch Models' to query models from server. |
| text | STRING | Text prompt to encode into conditioning embeddings. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| conditioning | CONDITIONING | — |