CWK Prompt Composer
Pills, autocomplete, and a CLIP encoder in one node — CWK Prompt Composer
- clip
- positive_prompt
- negative_prompt
- positive_cond
- negative_cond
If your prompts are danbooru-tag soup - which they are, if you run anything in the SD 1.5/SDXL/Illustrious/Pony line - CWK Prompt Composer is the closest thing to an IDE for writing them. It's a prompt text editor that turns your positive and negative prompts into colored, draggable pills, gives you autocomplete for every tag and embedding you own, throws in wildcard loading and server-side presets, and then also encodes the result to conditioning. One node replaces the usual "three text boxes + two CLIP Text Encode nodes" blob in the middle of your graph.
The honest framing up front: this is a quality-of-life pack aimed squarely at tag-style prompting. Its tag library is literally the danbooru list (99k+ tags, downloaded into tags/main.txt). If your workflow is a single sentence into Flux 2 or Anima - where your prompt is read as an instruction by an LLM text encoder and (word:1.3) is silently discarded - most of what makes this node fun does nothing for you. Keep it for the CLIP-era models it was built around.
How it works
Almost all the magic is on the front end. The Python node itself is small: it takes your two strings, and if you've wired a clip model in, encodes them. Everything else - pill canvas, category-colored syntax highlighting, tag pickers, wildcards, presets, the export dialog - is JavaScript living in the pack's web/ directory, talking to a few /cwk/* API endpoints the pack registers with ComfyUI's server.
The clever bit is the built-in encoding. Two parsers, selectable via the parser dropdown:
comfy(default) - the standard ComfyUI path:clip.tokenize()+encode_from_tokens(). Weights behave exactly like any CLIP Text Encode node.A1111- a fully self-contained reimplementation of Automatic1111'sparse_prompt_attention, supporting(word:1.3),((word)),[word], andBREAK, with per-token emphasis and mean normalization. It doesn't need ComfyUI_smZNodes or any other pack; it's right there innodes.py. If you migrated from A1111 and never got comfortable with ComfyUI's weighting, this makes the syntax you already know work.
The inputs that matter
The two required inputs are just positive_prompt and negative_prompt - multiline strings, and the ones you'll spend your time in. Then the optional ones:
clip- wire a CLIP model here if you want conditioning outputs. Leave it empty and the node degrades to a string formatter: it returns the prompts and empty lists for the conds.parser-comfyorA1111, as above.flux_guidance- default 3.5. If you change it from the default, it injects thatguidancevalue into the positive conditioning, exactly like the FluxGuidance node. You want this on Flux. On non-Flux models changing it does nothing useful.zero_out_negative- zeroes the negative conditioning tensors, mirroring ConditioningZeroOut. Reach for it on distilled-guidance / CFG 1 style workflows where the negative is ignored anyway.
Outputs are positive_prompt, negative_prompt (both STRING), and positive_cond / negative_cond (both CONDITIONING). The conds plug straight into a KSampler; the strings feed anything else you want to preview or log.
Installing it
Either ComfyUI Manager (search "CWK Prompt Composer") or:
cd ComfyUI/custom_nodes
git clone https://github.com/cowneko/CWK_Prompt_Composer.git
Then restart ComfyUI. There's no requirements.txt and no heavy dependency - it uses only torch and aiohttp, which ComfyUI already ships. One thing to know: if tags/main.txt is missing, the pack fetches the danbooru tag list from a remote gist on first use, so the very first run needs network. It ships a 99k-line main.txt, so you usually won't see it.
Gotchas worth knowing
The A1111 parser is a faithful port, but remember what it is: CLIP-era syntax for CLIP-era models. Feed ((word:1.4)) through it into an LLM-encoded model and you're just writing literal punctuation into an instruction. That's not a bug in this node - it's the new text encoders dropping support for weighting.
The 75-token counter in each panel header is there for a reason: it shows a chunk indicator when you blow past the CLIP chunk boundary, so you can see where BREAK would actually help. And if you're coming from A1111, the pill-mode right-click menu hides a genuinely useful option: "Add to Tag List", which saves a tag to the right tags/*.txt file in alphabetical order - effectively building your own personal tag library that persists across sessions.
It's a niche pack - essentially zero search presence - so if something's weird, your first stop is the GitHub issues. But for the tag-prompting crowd, this is the rare case where the fanciest feature, the built-in encoding, is also what de-clutters your workflow the most.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| positive_prompt | STRING | — | |
| negative_prompt | STRING | — | |
| clipopt | CLIP | — | |
| parseropt | COMBO | comfy | 2 options: comfy, A1111 |
| flux_guidanceopt | FLOAT | 3.50–100 | — |
| zero_out_negativeopt | BOOLEAN | false | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| positive_prompt | STRING | — |
| negative_prompt | STRING | — |
| positive_cond | CONDITIONING | — |
| negative_cond | CONDITIONING | — |