comfyui-screenshot-pipeline

v2026.09.24

Containerized README-screenshot pipeline (Docker + Playwright) for ComfyUI custom-node packs. Use when generating pack screenshots, adding `just screenshots`, or capturing modal/gesture node UI.

GitHub
安装命令
npx skhub add laurigates/comfyui-screenshot-pipeline
Markdown
SKILL.md

comfyui-screenshot-pipeline

Add the containerized README-screenshot generator to a ComfyUI usability pack. It is the deferred piece from comfyui-node-scaffold (which intentionally does not emit it). The same pattern ships in comfyui-gallery-loader, comfyui-sampler-info, comfyui-touch-numeric, comfyui-prompt-editor, comfyui-model-gallery, comfyui-touch-resize, and comfyui-touch-connect — those are the living reference implementations.

When to Use This Skill

Use this skill when...Use the alternative when...
Adding a reproducible README-screenshot generator to an existing ComfyUI pack — Docker + Playwright driver, just screenshots, committed docs/<out>.pngBootstrapping a brand-new pack repo → comfyui-node-scaffold (it intentionally defers the screenshot pipeline)
Capturing the pack's real frontend deterministically (modal dialog, gesture affordance, or transient overlay)Running the full idea→registry lifecycle → comfy-node

Why containerized

The shot must not depend on whatever models / theme / frontend a dev machine happens to have. A Docker image pins the ComfyUI release (hence the frontend bundle) and the Playwright/Chromium revision (the largest source of cross-host font-rendering drift), boots ComfyUI headless on CPU with no models, drives the pack's real public surface, and writes a PNG to a mounted docs/. Re-runs are deterministic.

Pick the archetype

ArchetypeUse when the pack…What the driver does
modalopens an HTML dialog over a widget (the modal "vein": gallery-loader, sampler-info, touch-numeric, prompt-editor, model-gallery)load a workflow with the target node, wait for the pack's patch flag on the widget, invoke widget.onPointerDown, wait for .cmp-dialog, screenshot it
gesture-affordanceis a canvas gesture whose only static surface is a painted affordance (touch-resize's corner-hint bracket)select a node directly (no selectNode → no Vue toolbox) so onDrawForeground paints, optionally inject an illustrative callout overlay, clip the canvas region around the node
gesture-overlayshows a transient overlay only during a live gesture that can't run headlessly (touch-connect's magnifier loupe)force the canvas state (connecting_links etc.), dispatch a synthetic touch pointer the pack listens for, then screenshot the activated overlay element

For a backend model pack (model-gallery), add --seed-models: a fresh ComfyUI has empty model dirs, so the grid renders empty. The generator emits seed_models.py that drops zero-byte placeholder files (the /list endpoint enumerates names only, never reads contents) across a couple of subfolders.

How to run

add_screenshots.py is stdlib-only. Run it from the pack repo root (or pass --dir <pack>). The script ships with this skill, so reference it via ${CLAUDE_SKILL_DIR}:

# Modal pack (seed keypad over the `seed` widget)
python3 ${CLAUDE_SKILL_DIR}/add_screenshots.py --name comfyui-touch-numeric --variant modal --node KSampler --widget seed --flag _touchNumericPatched --ready .tn-keypad --out seed.png

# Backend model pack (seed placeholder models first)
python3 ${CLAUDE_SKILL_DIR}/add_screenshots.py --name comfyui-model-gallery --variant modal --node CheckpointLoaderSimple --widget ckpt_name --flag _modelGalleryPatched --ready .mg-card --out picker.png --seed-models

# Gesture pack — painted affordance
python3 ${CLAUDE_SKILL_DIR}/add_screenshots.py --name comfyui-touch-resize --variant gesture-affordance --node KSampler --out hint.png

# Gesture pack — forced overlay
python3 ${CLAUDE_SKILL_DIR}/add_screenshots.py --name comfyui-touch-connect --variant gesture-overlay --out loupe.png

Flags: --name (pack dir name = the served URL segment, used as the Docker COPY target — must match the real dir), --variant, --out (PNG filename, also the EXPECTED_OUTPUTS the entrypoint asserts), --node/--widget/--flag/ --ready (modal capture placeholders — the node type, the widget name the pack patches, the pack's per-widget patch-guard property, and an inner dialog selector that proves the body rendered), --seed-models, --dir, --comfy-ref (default v0.22.0), --playwright (default 1.49.1). It refuses to overwrite an existing screenshots/ unless --force.

It writes screenshots/{Dockerfile,Dockerfile.dockerignore,entrypoint.sh,package.json,capture.mjs,workflow.json,README.md} (+ seed_models.py with --seed-models), and appends a screenshots recipe to the pack's justfile if one isn't already there.

After running: tailor, iterate, embed

  1. Tailor capture.mjs + workflow.json. The generic infra is done; the capture is pack-specific. For modal, the placeholders are filled from your flags but verify the widget name, patch flag, and the --ready inner selector against the real pack JS. For the gesture variants, the emitted driver is the touch-resize / touch-connect approach — adjust selectors, forced state, and any injected overlay to your pack.

  2. Iterate without rebuilding. Build once, then mount the fast-changing files into the cached image so each run is ~10–15s instead of a ~4-min rebuild:

    docker build -f screenshots/Dockerfile -t <pack>-screenshots .
    docker run --rm -v "$(pwd)/docs:/out" -v "$(pwd)/screenshots/capture.mjs:/opt/screenshots/capture.mjs" -v "$(pwd)/screenshots/workflow.json:/opt/screenshots/workflow.json" <pack>-screenshots
    

    For a gesture pack iterating on the extension itself, also mount the pack JS: -v "$(pwd)/web/js/<ext>.js:/opt/ComfyUI/custom_nodes/<pack>/web/js/<ext>.js".

  3. Final run + embed. just screenshots produces the committed docs/<out>.png. Embed it as a README hero with an italic caption (see the reference packs). Land it as a docs(screenshots): change (no release bump). If the work also changes pack behavior (e.g. an affordance color), split that into its own fix(...)/feat(...) commit so release-please attributes it correctly.

Gotchas (all encountered building the family)

  • biome ignores screenshots/ in these packs, so CI's biome check . won't lint capture.mjs — but keep it clean anyway (2-space indent, double quotes) to match the family.
  • ruff DOES lint seed_models.py via ruff check . / ruff format --check .. The generator's output is already ruff-clean and formatted.
  • entrypoint.sh shellcheck: the for f in ${EXPECTED_OUTPUTS} loop is intentional word-splitting; the generator includes the # shellcheck disable=SC2086 directive so a pre-commit shellcheck hook doesn't fail.
  • Dismiss the first-run dialog. A fresh ComfyUI profile opens a PrimeVue "Workflow Templates" dialog (.p-dialog-mask) over the canvas; the drivers press Escape and remove the mask before shooting.
  • deviceScaleFactor: 2 gives crisp 2× PNGs; the modal shell is .cmp-dialog.
  • widget.onPointerDown may be the pack's own wrapper that chains the original first and only opens the modal if the original didn't consume the event — invoking it with {} as the pointer works for the family's widgets. If a modal won't open this way, fall back to the pack's Strategy-B button (prompt-editor's ⤢, gallery-loader's 📁) — see those capture scripts.
  • Pin lockstep. The Playwright version is pinned in BOTH the Dockerfile FROM and package.json; bump together. COMFYUI_REF pins the frontend bundle — bump deliberately (the modal/canvas render is sensitive to it).

The generic files (what's identical across packs)

entrypoint.sh (boots ComfyUI on --cpu :8188, waits for /system_stats, runs the driver, asserts $EXPECTED_OUTPUTS exist), Dockerfile.dockerignore, and package.json (modulo the name) are the same everywhere. The Dockerfile differs only by pack name, EXPECTED_OUTPUTS, and the optional model-seeding block. capture.mjs + workflow.json are the only genuinely pack-specific files — and the reference packs are the canonical examples to crib from.

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

comfyui-plugin/skills/comfyui-screenshot-pipeline

默认分支

main

最新提交

1668324

Tree SHA

b2d4cc3