The README documented five of the seven nodes - Save Image (Civitai) and Prompt + LoRAs, the two largest features, appeared nowhere - and what it did document, it documented in prose. It is now compact and built to be scanned: what the pack does, three screenshots, install, the node table, and links out. Everything longer moved into wiki/: Home, Usage, Nodes, API, Architecture, Development and Troubleshooting. Nodes.md was generated from the real schemas and API.md was diffed field by field against a running server, so neither describes a version of the code that does not exist. The Civitai Updater relationship is written down properly, as a table of which sidecar field feeds which feature and what stops working without one. Only the AutoV2 hash has a fallback, which is worth saying plainly. A workflow publishes wiki/ to the repository's GitHub wiki, rewriting repo-relative image and file links so they resolve there. The wiki repo has to be created once in the web UI before the first run. Screenshots are captured from a real ComfyUI running this branch, driven with Playwright at 2x against a generated demo LoRA folder - illustrative names and stand-in preview art, never a real collection. Six shots, 352 KB as WebP. Assets restructured to match the sibling civitai-updater project: registry art sized and quantised (the banner from 4.8 MB to 487 KB at exactly 21:9), screenshots in assets/docs/, originals kept in assets/source/. pyproject's registry URLs follow the moved files. The example workflow is now two model configurations, Krea 2 and Z-Image Turbo, each with its own Warp, switched into one shared pipeline. Its output image carries both the workflow and the Civitai parameters block it was saved with. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.7 KiB
Development
Setting up
Clone anywhere and link it into ComfyUI rather than working inside
custom_nodes:
$src = "C:\path\to\ComfyUI-WarpPipe"
$dst = "C:\path\to\ComfyUI\custom_nodes\warppipe"
New-Item -ItemType Junction -Path $dst -Target $src
ln -s /path/to/ComfyUI-WarpPipe /path/to/ComfyUI/custom_nodes/warppipe
Checks
Everything CI runs, in the order it runs it:
python -m ruff check . --exclude .agents --exclude .claude
python -m ruff format --check . --exclude .agents --exclude .claude
python -m pytest -q
npm ci && npm run check
The Python tools are pinned in the workflow and the frontend lockfile is committed, both for the same reason: a build going red should mean the code changed, not that a tool released that morning.
npm run check is eslint plus prettier over web/. npm run format writes the
formatting rather than checking it.
Tests
pytest needs no ComfyUI. tests/conftest.py installs a fake comfy,
comfy_api and torch into sys.modules and loads warp_pipe.py fresh for
each test, so legacy and V3 registration can both be exercised in one run.
The fakes exist to make import work and to let schemas be inspected. They are not a simulation of ComfyUI: anything depending on real execution semantics has to be tried in ComfyUI.
Worth knowing when adding tests:
warp_pipeandpackage_loaderfixtures give you a freshly imported module;warp_pipe_loader(enable_v3=True)gives you the V3 path.- A test that asserts a fix should be checked against the unfixed code once, by reverting the change and watching it go red. A regression test that never could have failed is decoration.
test_the_package_ships_every_file_the_frontend_needsreadspyproject.tomland asserts every file underweb/is matched by apackage-dataglob. Add a.cssthere and it will tell you before the wheel does.
Adding a node
- Write the class in
warp_pipe.pywithINPUT_TYPES,RETURN_TYPES,RETURN_NAMES,FUNCTIONandCATEGORY. - Add it to
NODE_DEFINITIONS. That is what both registration paths are built from, so this is the only list. - Add a V3 class and an entry in
V3_NODE_CLASSES. Startup logs an error naming anything inNODE_DEFINITIONSwithout one, and a test fails. - Write
web/docs/<Node ID>.md. ComfyUI shows it behind the?on the node. - Document it in Nodes.md and, if it is worth showing, the README.
V3 schemas share one field-id namespace across inputs and outputs, so an output
mirroring an input needs a distinct id and a matching display_name — model
in, model_out displayed as model out.
Screenshots
assets/docs/*.webp are captured from a real ComfyUI, not mocked. The setup:
- Build a small demo LoRA folder — plausible filenames in the
creator - name - version (base)convention,.civitai.infosidecars, and generated stand-in preview art. Never the real library; a public README should not carry somebody's model collection. - Run a second ComfyUI on another port with
--base-directorypointed at that folder, so the running instance is untouched.--base-directorydoes not overrideextra_model_paths.yaml, so copymain.pyand the other loose modules into a scratch directory beside junctions to the package directories; ComfyUI then looks for the config next to that copy and finds none. - Drive it with Playwright against an installed Chrome, at
deviceScaleFactor: 2, hiding.workflow-tabs-container,.side-toolbar-container,.subgraph-breadcrumband.actionbar-containerso the app's own chrome stays out of the clip.
Save flat UI shots as lossless WebP and anything with real gradients as quality 90. Palette-quantised PNG bands badly on preview art.
The wiki
wiki/ in this repo is the source of truth - it reviews alongside the code that
changes it. A workflow copies it into the GitHub wiki on every push to main
that touches it, so the pages are also browsable at /wiki with GitHub's own
navigation.
The wiki is a separate repository, so repo-relative paths do not resolve there.
The workflow rewrites them on the way in: ../assets/... becomes a
raw.githubusercontent.com URL and anything else ../ becomes a blob URL.
Links between wiki pages are left alone, because GitHub resolves Usage.md to
the Usage page by itself. Keep writing them relative and the rewrite handles it.
One manual step, once: GitHub does not create the wiki repository until a page
has been made in the web UI. Create any page there and the workflow takes over -
it replaces the contents wholesale, so a page deleted from wiki/ disappears.
Releasing
- Move the
[Unreleased]block inCHANGELOG.mdunder a new version heading with today's date. - Set the version in both
pyproject.tomlandversion.txt. - Merge to
main.
The publish workflow fires on a push touching pyproject.toml, but only
publishes when the version there actually changed against the previous commit —
editing lint config does not re-publish. A manual workflow_dispatch always
publishes.
Semver as this project reads it: a new node or a new capability is a minor; a
change that makes an existing workflow load differently is a major. 3.0.0 was
the CONTROL → WARPPIPE rename. 4.0.0 is the prompt box and the Civitai save
node — nothing breaks, but it is a different pack to use.
Registry metadata
[tool.comfy] in pyproject.toml carries the publisher, display name, and raw
GitHub URLs for assets/registry/icon.png and assets/registry/banner.png.
Those two are the sized, quantised copies — the originals live in
assets/source/ and are far too heavy for a listing page.