# Comfy-Org/ComfyUI — codebase unpack

> Canonical page: https://codevetter.com/unpack/comfyui

This is a deterministic Repo Unpack scan of Comfy-Org/ComfyUI — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: b33e2b55cae074eca5aec96283cceac19aa249ba (2026-09-22)
- Last upstream commit: chore: update workflow templates to v0.11.68 (#16466)
- Generated by codevetter 1.12.0 on 2026-09-22
- 1166 files scanned · 19.9 MB

## Languages

- Python: 916 files
- JSON: 155 files
- YAML: 35 files
- Markdown: 13 files
- Shell: 1 files
- TOML: 1 files

## Repository structure

- comfy/ — 362 files
- tests-unit/ — 190 files
- comfy_extras/ — 165 files
- blueprints/ — 133 files
- comfy_api_nodes/ — 94 files
- app/ — 43 files
- comfy_api/ — 39 files
- .github/ — 34 files

Probable source entrypoint: `app/` (inferred from the tree, not upstream docs)

## Package

- pyproject.toml: ComfyUI v0.37.0 — 0 declared dependencies

## Structural health signals

Average score 5.6/10 across 96 files; 95 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- b33e2b55cae0 (2026-09-22) chore: update workflow templates to v0.11.68 (#16466)
- b09760de3079 (2026-09-22) [Partner Nodes] feat(Tencent): add Hunyuan Image 3.5 text-to-image and edit nodes (#16462)
- e638023d5449 (2026-09-21) Fast disk detection to all model loaders. (#16425)
- fc584aaa2265 (2026-09-22) Blend H3 VAE tiles against composited neighbours (#16436)
- d15842095092 (2026-09-21) Cuda graphs + memory compiler on ace step 1.5 autoregressive model. (#16461)

## Overview

ComfyUI (version 0.37.0) is a node-based inference engine and aiohttp web server for diffusion and generative AI models. A single Python process runs an HTTP/WebSocket frontend server (server.PromptServer) plus a daemon 'prompt_worker' thread that pops prompt graphs off a priority queue and executes them node-by-node through execution.PromptExecutor with aggressive inter-node output caching. Its distinctive architecture is a dynamic graph executor supporting lazy inputs, list-mapping, async node functions, and runtime subgraph expansion, paired with a checkpoint auto-detection system (comfy.model_detection) that identifies model families from state-dict keys and shapes.

## System map

ComfyUI is a single-process Python application: main.py parses CLI args, sets device env vars, runs custom-node prestartup scripts, loads all node definitions, initializes an optional SQLite database, then starts an aiohttp server and a daemon worker thread. The aiohttp layer (server.PromptServer) owns HTTP routes, WebSocket clients, and middleware; execution.PromptExecutor owns graph execution in the worker thread; the comfy/ package owns model loading, memory management, and sampling; nodes.py plus comfy_extras/, comfy_api_nodes/, and custom_nodes/ supply the node registry. Persistence is three-layered: an in-memory PromptQueue/history, filesystem dirs (input/output/temp/user/models) managed by folder_paths, and an Alembic-migrated SQLite DB (user/comfyui.db) for the assets system.
- Entry point is main.py: it enables args parsing via comfy.options, reads comfy.cli_args.args, sets HF_HUB_DISABLE_TELEMETRY/DO_NOT_TRACK/CUDA_VISIBLE_DEVICES env vars, runs custom-node prestartup scripts, then calls start_comfyui() which builds PromptServer, loads nodes, and spawns the prompt_worker daemon thread. — [main.py#L39-115](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L39-L115) [main.py#L489-551](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L489-L551) [main.py#L183-237](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L183-L237)
- server.PromptServer builds an aiohttp web.Application with a middleware chain (cache_control, deprecation_warning, optional compress_body, CORS or origin-only, CSP when api nodes disabled, optional comfyui_manager middleware) and registers all routes inside __init__ via a RouteTableDef. — [server.py#L215-267](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L215-L267)
- The worker loop prompt_worker() blocks on PromptQueue.get(timeout), calls PromptExecutor.execute(), marks the task done into history, then handles unload_models/free_memory queue flags and runs gc.collect() + model_management.soft_empty_cache() every ~10 seconds. — [main.py#L319-410](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L319-L410)
- Every route defined on the PromptServer RouteTableDef is duplicated under an /api prefix in add_routes() (e.g. /prompt and /api/prompt both work), plus static mounts for /extensions/<node>, /templates, /docs and the frontend web_root. — [server.py#L1223-1284](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1223-L1284)
- The node registry lives in module-level dicts NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS in nodes.py; init_extra_nodes() loads ~130 built-in comfy_extras files, comfy_api_nodes glob-matched files, and external custom_nodes via load_custom_node(). — [nodes.py#L2068-2137](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2068-L2137) [nodes.py#L2574-2610](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2574-L2610) [nodes.py#L2394-2552](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2394-L2552)
- Model/MLOps core lives under comfy/: model_detection.py fingerprints checkpoints from state-dict keys, model_management.py owns device/VRAM/pinning policy, model_patcher.py owns the ModelPatcher weight-patching abstraction, samplers.py/sample.py own the sampling loop, and ldm/ holds model implementations. — [comfy/model_detection.py#L44-120](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_detection.py#L44-L120) [comfy/model_management.py#L893-1044](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_management.py#L893-L1044) [comfy/model_patcher.py#L340](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_patcher.py#L340)
- Persistent state: a SQLite database (default user/comfyui.db, override via --database-url) is created by app/database/db.py init_db() using SQLAlchemy + Alembic migrations in alembic_db/, guarded by a filelock <db>.lock against concurrent ComfyUI processes. — [app/database/db.py#L66-85](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/database/db.py#L66-L85) [app/database/db.py#L147-263](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/database/db.py#L147-L263) [alembic.ini](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/alembic.ini)
- The web frontend is not in this repo: it ships as the pinned pip package comfyui-frontend-package==1.53.6 and FrontendManager.init_frontend() can download a release zip from api.github.com when --front-end-version requests a specific version; --front-end-root overrides with a local path. — [requirements.txt#L1-3](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/requirements.txt#L1-L3) [app/frontend_management.py#L355-431](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/frontend_management.py#L355-L431) [comfy/cli_args.py#L228-257](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L228-L257)
- CLI configuration is a module-level argparse parser in comfy/cli_args.py (~70 flags: --listen/--port, --cuda-device, VRAM modes, cache modes, dtype forcing, --disable-all-custom-nodes, --enable-manager, --database-url, --enable-assets) whose parsed `args` singleton is imported by nearly every module. — [comfy/cli_args.py#L61-275](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L61-L275)
- Directory layout is configured at import time in folder_paths.py: folder_names_and_paths maps logical model categories (checkpoints, loras, vae, diffusion_models, controlnet, upscale_models, ~20 total) to search dirs, plus output/temp/input/user dirs all relocatable via --base-directory or per-dir flags. — [folder_paths.py#L10-72](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L10-L72) [main.py#L140-180](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L140-L180)
- Runtime concurrency model: one asyncio event loop runs the HTTP server and a publish_loop() that drains a message queue fed thread-safely by send_sync() from the worker thread; WebSocket clients live in self.sockets keyed by clientId. — [server.py#L1395-1405](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1395-L1405) [server.py#L269-327](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L269-L327) [main.py#L412-418](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L412-L418)
- Optional sub-apps and managers attach in add_routes(): UserManager (/users, /userdata), ModelFileManager (/experiment/models), CustomNodeManager (/workflow_templates, /i18n), SubgraphManager, NodeReplaceManager, and an /internal sub-application from api_server InternalRoutes. — [server.py#L1223-1229](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1223-L1229) [app/user_manager.py#L123-440](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/user_manager.py#L123-L440) [api_server/routes/internal/internal_routes.py#L1-40](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/api_server/routes/internal/internal_routes.py#L1-L40)
- Build/run/test surface: pip install -r requirements.txt then `python main.py`; unit tests via `pytest tests-unit` (pytest.ini sets testpaths to tests and tests-unit); lint via ruff config in pyproject.toml and .github/workflows/ruff.yml. — [requirements.txt](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/requirements.txt) [pytest.ini#L1-9](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/pytest.ini#L1-L9) [pyproject.toml#L14-30](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/pyproject.toml#L14-L30) [.github/workflows/test-unit.yml](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/.github/workflows/test-unit.yml)

## Feature catalog

The user-facing surface is an HTTP+WebSocket API driving a node-graph execution engine, plus a large built-in node library. HTTP covers prompt submission, queue/history management, job status, image upload/view, model listing, object_info schema introspection, user data storage, and workflow templates. The node catalog spans core SD nodes in nodes.py, ~130 comfy_extras modules (audio, video, 3D, model merging, advanced samplers), and comfy_api_nodes that call paid third-party APIs. The optional ComfyUI Manager integration and the assets system (blake3-hashed media catalog in SQLite) are feature-flagged subsystems.
- POST /prompt accepts a workflow graph {node_id: {class_type, inputs}} plus optional client_id/extra_data/prompt_id/partial_execution_targets, runs validate_prompt, and heapq-pushes (number, prompt_id, prompt, extra_data, outputs_to_execute, sensitive) onto PromptQueue returning {prompt_id, number, node_errors}. — [server.py#L1075-1147](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1075-L1147) [execution.py#L1297-1314](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L1297-L1314)
- Queue and history endpoints: GET /queue returns running+pending with sensitive fields stripped by _remove_sensitive_from_queue; POST /queue supports clear/delete; GET /history and /history/{prompt_id} read the in-memory history dict; POST /history clears or deletes entries. — [server.py#L69-71](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L69-L71) [server.py#L1048-1073](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1048-L1073) [server.py#L1149-1217](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1149-L1217)
- A jobs API exposes GET /api/jobs, GET /api/jobs/{job_id}, POST /api/jobs/{job_id}/cancel and POST /api/jobs/cancel backed by comfy_execution/jobs.py with JobStatus pending/in_progress/completed/failed/cancelled. — [server.py#L824-1048](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L824-L1048) [comfy_execution/jobs.py#L1-40](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/jobs.py#L1-L40)
- POST /interrupt either targets a specific running prompt_id or globally interrupts via nodes.interrupt_processing -> comfy.model_management.interrupt_current_processing; POST /free sets unload_models/free_memory flags consumed by the worker loop. — [server.py#L1163-1204](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1163-L1204) [nodes.py#L48-52](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L48-L52) [main.py#L386-397](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L386-L397)
- File endpoints: POST /upload/image and /upload/mask write into input/temp/output dirs with subfolder confinement checks and duplicate detection via hashing; GET /view serves files (including blake3: hash resolution to asset paths) and GET /view_metadata/{folder} exposes safetensors metadata. — [server.py#L397-499](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L397-L499) [server.py#L516-560](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L516-L560) [server.py#L666-689](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L666-L689)
- Introspection endpoints: GET /object_info and /object_info/{node_class} serialize each node class's INPUT_TYPES/RETURN_TYPES/CATEGORY for the frontend; GET /models and /models/{folder} list folder_paths categories; GET /embeddings lists embedding names; GET /system_stats and /features report device and capability info. — [server.py#L337-356](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L337-L356) [server.py#L689-823](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L689-L823)
- The /ws WebSocket negotiates per-client feature_flags as the first message, then streams JSON events (status, executing, executed, progress, execution_start/cached/success/error) and binary frames for preview images (PREVIEW_IMAGE, UNENCODED_PREVIEW_IMAGE, PREVIEW_IMAGE_WITH_METADATA from protocol.BinaryEventTypes). — [server.py#L269-327](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L269-L327) [server.py#L1293-1397](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1293-L1397) [protocol.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/protocol.py)
- Core node set in nodes.py covers the SD1.x/SDXL workflow: CheckpointLoaderSimple, CLIPTextEncode, KSampler/KSamplerAdvanced, VAEEncode/VAEDecode(+Tiled), LoraLoader, ControlNetLoader/Apply, EmptyLatentImage, SaveImage/PreviewImage, LoadImage, and conditioning/latent/image transform nodes. — [nodes.py#L2068-2137](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2068-L2137) [nodes.py#L1572-1658](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L1572-L1658)
- comfy_extras/ contributes ~130 node modules loaded by init_builtin_extra_nodes: upscale models, mask/compositing, model merging, SD3/Flux/Hunyuan/Wan/Qwen video+audio model support, 3D (load/save/mesh/gaussian splat), GLSL shaders, logic/loop/math utility nodes, and training nodes (nodes_train, nodes_dataset). — [nodes.py#L2394-2552](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2394-L2552)
- comfy_api_nodes/ contains API nodes that call remote paid services (OpenAI, Anthropic, Gemini, Grok, Kling, Luma, ByteDance, ElevenLabs, Stability, etc.) authenticated through hidden AUTH_TOKEN_COMFY_ORG/API_KEY_COMFY_ORG extra_data keys; --disable-api-nodes blocks them and adds a restrictive CSP middleware. — [comfy_api_nodes/nodes_openai.py#L1-30](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api_nodes/nodes_openai.py#L1-L30) [execution.py#L161](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L161) [execution.py#L206-213](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L206-L213) [server.py#L200-243](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L200-L243)
- User/file management features: UserManager adds /users CRUD and /userdata file endpoints (GET/POST/DELETE/move) gated by --multi-user; get_public_user_directory blocks '__'-prefixed system user dirs from HTTP access. — [app/user_manager.py#L123-440](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/user_manager.py#L123-L440) [folder_paths.py#L154-216](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L154-L216) [comfy/cli_args.py#L219](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L219)
- ModelFileManager adds experimental /experiment/models routes including a preview endpoint that extracts embedded preview images from model files; CustomNodeManager serves /workflow_templates and /i18n translation JSON built from loaded custom nodes. — [app/model_manager.py#L28-105](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/model_manager.py#L28-L105) [app/custom_node_manager.py#L92-141](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/custom_node_manager.py#L92-L141)
- The assets system (--enable-assets) registers uploads and generated outputs into a SQLite catalog with blake3 content hashes, runs background filesystem scans, and emits events through the server's send_sync sink. — [app/assets/manager.py#L22-101](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/assets/manager.py#L22-L101) [server.py#L443-460](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L443-L460) [comfy/cli_args.py#L275](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L275)
- Latent previews during sampling are produced by latent_preview.py with methods none/auto/latent2rgb/taesd chosen by --preview-method/--preview-size, streamed to the client as binary preview frames via the hijacked progress hook. — [latent_preview.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/latent_preview.py) [comfy/cli_args.py#L122-137](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L122-L137) [main.py#L420-449](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L420-L449)
- Internal (frontend-only, unstable) endpoints are mounted as the /internal sub-app: /internal/logs, /internal/logs/raw and log-subscription handled by TerminalService. — [api_server/routes/internal/internal_routes.py#L1-40](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/api_server/routes/internal/internal_routes.py#L1-L40)

## Data flow

A prompt enters as JSON at POST /prompt, is validated into an executable output list, and becomes a heapq item on PromptQueue. The worker thread wraps it in DynamicPrompt (original + ephemeral + override layers) and builds an ExecutionList — a topological dissolve where nodes become ready when their link dependencies resolve. Each node call resolves inputs from cached upstream outputs, invokes the node's FUNCTION (mapped over input lists, async-aware), and stores outputs in signature-keyed caches; UI outputs and progress flow back over WebSocket via send_sync. Model weights flow through folder_paths resolvers into comfy.sd loaders that detect the architecture and wrap it in a ModelPatcher managed by model_management for VRAM offload. Results persist to the output dir (SaveImage) and the run record lands in the in-memory history dict (capped at 10000) plus the assets DB when enabled.
- Input boundary: POST /prompt -> trigger_on_prompt(on_prompt_handlers) -> number assignment -> node_replace_manager.apply_replacements -> execution.validate_prompt -> PromptQueue.put((number, prompt_id, prompt, extra_data, outputs_to_execute, sensitive)). — [server.py#L1075-1136](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1075-L1136) [server.py#L1459-1470](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1459-L1470) [execution.py#L1128-1282](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L1128-L1282)
- validate_prompt collects OUTPUT_NODE classes (optionally filtered by partial_execution_targets), recursively validates inputs (type matching via validate_node_input, min/max, combo membership, custom VALIDATE_INPUTS/validate_inputs hooks), detects dependency cycles, and validates loop boundaries via validate_loops. — [execution.py#L846-1120](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L846-L1120) [execution.py#L1163-1282](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L1163-L1282) [comfy_execution/validation.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/validation.py)
- Execution loop: PromptExecutor.execute_async wraps everything in torch.inference_mode, builds DynamicPrompt + ExecutionList, seeds it with output node ids, then repeatedly calls stage_node_execution -> module-level execute() -> complete/unstage until the list empties. — [execution.py#L727-843](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L727-L843) [comfy_execution/graph.py#L212-387](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/graph.py#L212-L387)
- Per-node execution order inside execute(): check output cache -> get_input_data resolves each input link through execution_list.get_cache (missing -> mark_missing and lazy evaluation via check_lazy_status returns PENDING) -> instantiate/cache the node object in caches.objects -> get_output_data -> _async_map_node_over_list -> node FUNCTION. — [execution.py#L438-565](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L438-L565) [execution.py#L163-235](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L163-L235) [execution.py#L251-327](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L251-L327)
- Intermediate results are cached by CacheSet: outputs cache uses CacheKeySetInputSignature (class_type + IS_CHANGED value + ancestor input signatures, folded via to_hashable) while objects cache uses CacheKeySetID (node_id, class_type); modes are CLASSIC/LRU/NONE/RAM_PRESSURE chosen by --cache-* flags. — [execution.py#L113-159](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L113-L159) [comfy_execution/caching.py#L68-120](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/caching.py#L68-L120) [main.py#L319-339](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L319-L339)
- Node functions can return plain tuples, dicts with 'result'/'ui'/'expand', or V3 NodeOutput objects; 'expand' produces an ephemeral subgraph injected into DynamicPrompt.ephemeral_prompt and re-scheduled, with the node's final outputs resolved later from pending_subgraph_results. — [execution.py#L359-422](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L359-L422) [execution.py#L578-612](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L578-L612) [comfy_execution/graph.py#L21-71](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/graph.py#L21-L71) [comfy_api/latest/_io.py#L2344](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api/latest/_io.py#L2344)
- Streaming output: nodes emit UI data via 'ui' dicts -> register_executed_outputs enriches them into asset references -> send_sync('executed', ...) to the client; sampler progress goes through comfy.utils.ProgressBar global hook -> send_sync('progress') + binary preview frames. — [execution.py#L565-577](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L565-L577) [comfy_execution/asset_enrichment.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/asset_enrichment.py) [main.py#L420-449](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L420-L449) [comfy/utils.py#L1292-1306](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/utils.py#L1292-L1306)
- Model loading path: folder_paths.get_full_path_or_raise resolves a filename inside a category's search dirs -> comfy.utils.load_torch_file reads safetensors/ckpt -> model_detection.model_config_from_unet fingerprints the state dict -> comfy.supported_models builds the model -> ModelPatcher wraps it -> load_models_gpu places it per VRAM policy. — [folder_paths.py#L441-468](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L441-L468) [comfy/sd.py#L2132-2215](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/sd.py#L2132-L2215) [comfy/model_detection.py#L44-120](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_detection.py#L44-L120) [comfy/model_management.py#L939-1044](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_management.py#L939-L1044)
- Sampling path inside a node: KSampler.sample -> common_ksampler -> comfy.sample.prepare_noise (seeded) -> latent_preview.prepare_callback -> comfy.sample.sample -> comfy.samplers.KSampler.sample drives the denoise loop calling model.apply_model per sigma step. — [nodes.py#L1572-1624](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L1572-L1624) [comfy/sample.py#L79-86](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/sample.py#L79-L86) [comfy/samplers.py#L1276-1443](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/samplers.py#L1276-L1443)
- History persistence: task_done() pops currently_running, strips the sensitive tuple element via process_item=remove_sensitive, and stores {prompt, outputs, status} in self.history keyed by prompt_id, evicting FIFO beyond MAXIMUM_HISTORY_SIZE=10000. — [execution.py#L1284-1341](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L1284-L1341) [main.py#L366-372](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L366-L372)
- Auth-sensitive extra_data keys (auth_token_comfy_org, api_key_comfy_org) are popped into a separate `sensitive` dict at enqueue time, reattached only inside the worker, and injected into node inputs via hidden input plumbing (Hidden.auth_token_comfy_org / hidden AUTH_TOKEN_COMFY_ORG). — [server.py#L1129-1134](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1129-L1134) [execution.py#L161](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L161) [execution.py#L206-211](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L206-L211) [main.py#L356-359](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L356-L359)
- File output boundary: SaveImage writes PNGs (with embedded prompt/workflow metadata unless --disable-metadata) into folder_paths.get_output_directory() with counter-suffixed filenames; LoadImage reads from the input directory through annotated_filepath/get_annotated_filepath resolvers. — [nodes.py#L1660-1679](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L1660-L1679) [folder_paths.py#L255-270](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L255-L270) [folder_paths.py#L343-357](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L343-L357)
- Asset enrichment: when enabled, AssetManager pauses its background scan during execution, registers uploaded/executed files into the DB catalog, and /view resolves blake3:<hash> filenames to asset paths via resolve_hash_to_path. — [main.py#L361-362](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L361-L362) [server.py#L524-531](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L524-L531) [app/assets/manager.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/assets/manager.py)

## Behavior traces

Traced flows: (1) startup from `python main.py` through arg parsing, env setup, prestartup scripts, node loading, DB init, route registration and server bind; (2) a prompt's journey from POST /prompt through validation, queueing, per-node execution, caching and WebSocket events; (3) model loading from a CheckpointLoaderSimple node through state-dict detection into a VRAM-managed ModelPatcher; (4) interrupt and memory-pressure handling; (5) image upload and /view retrieval with traversal guards.
- Startup order: comfy.options.enable_args_parsing -> args parse -> setup_logger -> (optional) comfy_aimdo.control.init for DynamicVRAM -> apply_custom_paths (extra_model_paths.yaml, dir overrides) -> init_mime_types -> execute_prestartup_script over custom_nodes -> import execution/server/nodes -> start_comfyui: PromptServer(loop) -> init_extra_nodes -> set_cudnn_benchmark -> setup_database(init_db + asset_manager.startup) -> add_routes -> hijack_progress -> prompt_worker thread -> prompt_server.setup + run -> TCPSite bind on --listen/--port. — [main.py#L1-37](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L1-L37) [main.py#L183-237](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L183-L237) [main.py#L489-551](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L489-L551) [server.py#L1410-1457](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1410-L1457)
- Prompt submission order: post_prompt -> request.json -> trigger_on_prompt -> client prompt_id validation via validate_job_id (canonical UUID) -> node_replace_manager.apply_replacements -> validate_prompt -> sensitive key extraction -> prompt_queue.put -> queue_updated() broadcasts status -> worker q.get pops the item. — [server.py#L1075-1147](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1075-L1147) [comfy_execution/jobs.py#L29-60](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/jobs.py#L29-L60) [execution.py#L1297-1314](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L1297-L1314)
- Worker execution order: prompt_worker gets item -> asset_manager.pause_background_scan -> PromptExecutor.execute -> execute_async: set_preview_method -> interrupt_processing(False) -> execution_start msg -> torch.inference_mode -> DynamicPrompt + reset_progress_state -> caches.set_prompt/clean_unused -> execution_cached msg -> loop stage_node_execution/execute -> execution_success or handle_execution_error -> task_done stores history -> send 'executing' node=None. — [main.py#L344-384](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L344-L384) [execution.py#L730-843](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L730-L843)
- Single node step order inside execute(): dynprompt id mapping (real/display/parent) -> caches.outputs.get short-circuit -> get_input_data (links via execution_list.get_cache, hidden PROMPT/DYNPROMPT/EXTRA_PNGINFO/UNIQUE_ID injection) -> send 'executing' -> lazy check via check_lazy_status -> get_output_data -> _async_map_node_over_list (slices list inputs, asyncio.create_task for coroutine functions, ExecutionBlocker propagation) -> merge_result_data -> caches.outputs.set + execution_list.cache_update -> 'executed' event. — [execution.py#L438-661](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L438-L661) [execution.py#L251-349](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L251-L349)
- Interrupt trace: POST /interrupt -> nodes.interrupt_processing -> comfy.model_management.interrupt_current_processing(True) -> flag checked by throw_exception_if_processing_interrupted inside the progress hook and before_node_execution -> InterruptProcessingException caught in execute() -> handle_execution_error sends 'execution_interrupted'. — [server.py#L1163-1193](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1163-L1193) [nodes.py#L48-52](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L48-L52) [main.py#L427](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L427) [execution.py#L618-626](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L618-L626) [execution.py#L692-699](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L692-L699)
- Checkpoint load trace: CheckpointLoaderSimple node -> comfy.sd.load_checkpoint_guess_config -> utils.load_torch_file -> model_detection.unet_prefix_from_state_dict + model_config_from_unet (state-dict key/shape fingerprinting) -> model_config classes from comfy.supported_models -> CLIP/VAE patchers built -> ModelPatcher returned as MODEL output -> later load_models_gpu/free_memory decide device placement and weight offloading. — [comfy/sd.py#L2132-2215](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/sd.py#L2132-L2215) [comfy/model_detection.py#L44-120](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_detection.py#L44-L120) [comfy/model_patcher.py#L340](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_patcher.py#L340) [comfy/model_management.py#L893-1044](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_management.py#L893-L1044)
- Image upload trace: POST /upload/image -> request.post() -> image_upload -> get_dir_by_type(input/temp/output) -> normpath join + commonpath containment check -> hash-compare dedup loop renaming 'name (i).ext' -> write file -> asset_manager.register_upload -> JSON {name, subfolder, type, asset?}. — [server.py#L370-462](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L370-L462)
- WebSocket lifecycle: GET /ws -> ws.prepare -> sid from clientId query or uuid4 -> sockets[sid]=ws -> send 'status' with queue info -> first TEXT message may carry feature_flags (stored in sockets_metadata, server flags replied) -> all server->client traffic funnels through send_sync -> messages queue -> publish_loop -> send_json/send_bytes. — [server.py#L269-327](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L269-L327) [server.py#L1375-1405](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1375-L1405) [comfy_api/feature_flags.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api/feature_flags.py)
- OOM/error path: exception inside execute() -> formatted inputs captured -> comfy.model_management.is_oom check triggers unload_all_models and debug_memory_summary logging -> error_details {node_id, exception_message, exception_type, traceback, current_inputs} -> handle_execution_error -> 'execution_error' WebSocket message -> worker records status 'error' in history. — [execution.py#L627-656](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L627-L656) [execution.py#L686-712](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L686-L712) [main.py#L367-372](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L367-L372)
- RAM-pressure caching behavior: with default RAM_PRESSURE cache, execute_async wires ram_release callback into memory_management.set_ram_cache_release_state; after each node it releases toward inactive headroom, computes shortfall vs virtual_memory_available, frees large intermediates then pins if needed. — [execution.py#L745-748](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L745-L748) [execution.py#L799-811](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L799-L811) [comfy_execution/caching.py#L1-66](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/caching.py#L1-L66)

## Testing signals

Testing is pytest-based and split into two trees: tests-unit (fast unit tests, run in CI on Linux/Windows/macOS with CPU torch) and tests (integration: execution tests that spawn a real server subprocess and drive it over WebSocket, and inference tests that run full workflows and compare generated images against a baseline directory). Markers 'inference' and 'execution' allow deselection. Coverage of the node library itself is thin — most tests target the execution engine, validation, caching, and server endpoints rather than model math.
- pytest.ini sets testpaths to both tests and tests-unit, registers 'inference' and 'execution' markers, and adds -s (no output capture); pythonpath=. makes the repo root importable. — [pytest.ini#L1-9](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/pytest.ini#L1-L9)
- tests/execution/test_execution.py spins up the real server via subprocess.Popen([sys.executable, 'main.py', ...]), waits, connects a ComfyClient over websocket-client, submits prompt graphs built with GraphBuilder, and asserts on WS events and output images. — [tests/execution/test_execution.py#L1-30](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/execution/test_execution.py#L1-L30) [tests/execution/test_execution.py#L505-580](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/execution/test_execution.py#L505-L580)
- tests/execution also covers async nodes, jobs API, preview method override, progress isolation, and the public API (test_public_api.py), with a testing_nodes helper package of custom nodes for the tests. — [tests/execution](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/execution)
- tests/inference/test_inference.py runs real diffusion workflows (ComfyGraph wrapper, KSampler imported from comfy.samplers) writing images to --output_dir; tests/compare performs quality regression by comparing directories, and conftest.py deliberately runs test_quality last. — [tests/inference/test_inference.py#L1-30](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/inference/test_inference.py#L1-L30) [tests/conftest.py#L28-45](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/conftest.py#L28-L45) [tests/README.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/README.md)
- tests-unit covers the execution engine (test_execution_list, validate_node_input, loop validation, nested loops, cache providers, reentry), server/user endpoints (prompt_server_test, system_user_endpoint_test), folder_paths, security (security_test dir), assets, and comfy internals — all CPU-only. — [tests-unit/execution_test](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests-unit/execution_test) [tests-unit/prompt_server_test](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests-unit/prompt_server_test) [tests-unit/README.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests-unit/README.md)
- CI: .github/workflows/test-unit.yml runs `pytest tests-unit` on ubuntu-latest/windows-2022/macos-latest with Python 3.12 and CPU-only torch; it is marked continue-on-error, so unit failures do not block merges. — [.github/workflows/test-unit.yml](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/.github/workflows/test-unit.yml)
- Additional workflows: test-execution.yml and test-ci.yml run the execution/integration suites, test-launch.yml smoke-tests server launch (--quick-test-for-ci exits after startup), and ruff.yml lints with the rule set pinned in pyproject.toml. — [.github/workflows/test-execution.yml](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/.github/workflows/test-execution.yml) [.github/workflows/test-ci.yml](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/.github/workflows/test-ci.yml) [comfy/cli_args.py#L211](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L211) [pyproject.toml#L14-30](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/pyproject.toml#L14-L30)
- Test deps are separate: tests-unit/requirements.txt plus websocket-client/opencv/scikit-image for integration tests per tests/README.md; inference tests require downloaded models, so they are not runnable in plain CI. — [tests-unit/requirements.txt](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests-unit/requirements.txt) [tests/README.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/README.md) [.github/workflows/test-unit.yml](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/.github/workflows/test-unit.yml)
- No coverage tooling, no mocked-HTTP layer for aiohttp routes, and no tests under comfy/ for individual model implementations — model correctness is only exercised indirectly through the heavyweight inference suite. (inferred) — [pytest.ini](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/pytest.ini) [tests](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests) [tests-unit](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests-unit)
- A --quick-test-for-ci flag in main.py exits right after the worker thread starts, which is what test-launch.yml uses to verify the server boots cleanly. — [main.py#L529-532](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L529-L532) [comfy/cli_args.py#L211](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L211)

## Risk map

Biggest risks: there is no authentication on the HTTP API, custom nodes are arbitrary code executed at startup, and model file formats include pickle-capable extensions. The codebase has accumulated scattered path-traversal and XSS mitigations that must be replicated at every new file endpoint. The execution engine is a single shared mutable state machine (server.client_id, last_node_id, module-level registries) so concurrent or reentrant use is fragile. Memory management and the aimdo/DynamicVRAM integration contain version-dependent protocol fallbacks that are easy to break.
- No authentication exists on any route: default bind is 127.0.0.1, but --listen with no value exposes 0.0.0.0,:: — an unauthenticated API that can queue prompts, read/write userdata files, upload images, and hit /internal/logs. — [comfy/cli_args.py#L63](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L63) [server.py#L1075-1147](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1075-L1147) [app/user_manager.py#L334-440](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/user_manager.py#L334-L440) [api_server/routes/internal/internal_routes.py#L20-40](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/api_server/routes/internal/internal_routes.py#L20-L40)
- Custom nodes are arbitrary Python: execute_prestartup_script exec_modules every custom_nodes/*/prestartup_script.py before the server starts, and load_custom_node exec_modules each module — remote-code-execution by design; mitigations are only --disable-all-custom-nodes/--whitelist-custom-nodes and optional comfyui_manager policy. — [main.py#L183-237](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L183-L237) [nodes.py#L2246-2266](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2246-L2266) [nodes.py#L2365-2382](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2365-L2382)
- supported_pt_extensions includes .ckpt/.pt/.bin/.pkl — formats that can embed pickle payloads; loading relies on comfy.utils.load_torch_file's safe handling, so changes there are security-critical. (inferred) — [folder_paths.py#L10](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L10)
- Path traversal defenses are reimplemented per endpoint: /view checks '..' and leading '/', subfolder joins use os.path.commonpath containment, and folder_paths.is_within_directory/get_annotated_filepath add realpath-based containment — any new file-serving endpoint must repeat this correctly. — [server.py#L536-549](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L536-L549) [server.py#L410-415](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L410-L415) [folder_paths.py#L326-357](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L326-L357)
- Stored-XSS mitigation is centralized in folder_paths.DANGEROUS_CONTENT_TYPES/is_dangerous_content_type with a Sec-Fetch-Dest:image carve-out for SVG; endpoints serving user content must route dangerous types to octet-stream or they reintroduce XSS. — [folder_paths.py#L273-323](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L273-L323)
- origin_only_middleware is an admitted partial fix for DNS-rebinding/cross-site POSTs to a loopback server ('the proper fix would be to add a cookie'): it 403s Sec-Fetch-Site:cross-site and Host/Origin hostname mismatches only when Host resolves to loopback. — [server.py#L159-197](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L159-L197)
- Shared mutable globals: server.client_id and last_node_id are single-slot fields on PromptServer set from extra_data of whichever prompt is running, and NODE_CLASS_MAPPINGS is a module-level dict mutated by every extension — one concurrently executing prompt or a misbehaving custom node can corrupt routing/display state. (inferred) — [server.py#L264-267](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L264-L267) [execution.py#L736-739](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L736-L739) [nodes.py#L2295-2303](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2295-L2303)
- comfy_aimdo protocol drift is handled by chained TypeError fallbacks (0.4.9/0.4.10 signatures) in main.py; silent wrong-version behavior is a real hazard since the fallbacks catch TypeError broadly. — [main.py#L71-81](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L71-L81) [main.py#L278-281](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L278-L281)
- The queue item is a positional tuple where index 5 is `sensitive` extra data; _remove_sensitive_from_queue and the remove_sensitive lambda both rely on tuple position, so reordering the tuple silently leaks auth tokens into queue/history responses. — [server.py#L69-71](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L69-L71) [main.py#L356-372](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L356-L372) [execution.py#L161](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L161)
- hook_breaker_ac10a0.py is a manual save/restore shim that protects comfy.model_management.cast_to from being hooked by custom nodes — evidence that custom-node monkeypatching has caused production incidents and protection is opt-in per function. — [hook_breaker_ac10a0.py#L1-17](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/hook_breaker_ac10a0.py#L1-L17) [main.py#L511-521](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L511-L521)
- DB init kills the process on lock contention only when --enable-assets is set; otherwise it logs and continues with a degraded assets layer — divergence between code paths makes failures mode-dependent. — [main.py#L452-486](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L452-L486) [app/database/db.py#L123-139](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/database/db.py#L123-L139)
- Alembic migration 0007_record_content_split is explicitly destructive: upgrading through it discards the prior asset catalog (tags, metadata, previews, renames) keeping only a .bkp file. — [app/database/db.py#L200-258](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/database/db.py#L200-L258)
- API nodes make outbound calls to dozens of paid third-party services using the user's comfy-org token; --disable-api-nodes exists as the kill switch and also adds a strict CSP header, implying these nodes are treated as the network-risk boundary. — [comfy_api_nodes](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api_nodes) [comfy/cli_args.py#L217](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L217) [server.py#L200-243](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L200-L243)

## Extension points

ComfyUI's primary extension mechanism is the custom_nodes directory scanned at startup: V1 extensions export NODE_CLASS_MAPPINGS/NODE_DISPLAY_NAME_MAPPINGS dicts (and optional WEB_DIRECTORY for frontend JS), while V3 extensions expose a comfy_entrypoint() returning a ComfyExtension whose get_node_list() yields ComfyNode classes with declarative Schemas. Secondary hooks: prestartup_script.py per package, server.on_prompt_handlers for prompt mutation, custom aiohttp routes via PromptServer.instance.routes, extra model paths via yaml config, progress handlers, cache providers, and node replacement rules.
- V1 node contract: a module in custom_nodes/ exporting NODE_CLASS_MAPPINGS {name: class} where each class defines INPUT_TYPES (required/optional/hidden), RETURN_TYPES, FUNCTION (method name), CATEGORY; OUTPUT_NODE=True makes it an execution target; registered into the global registry by load_custom_node. — [nodes.py#L2246-2304](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2246-L2304) [nodes.py#L56-77](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L56-L77) [custom_nodes/example_node.py.example](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/custom_nodes/example_node.py.example)
- V3 node contract: modules export comfy_entrypoint() (sync or async) returning a ComfyExtension; get_node_list() returns io.ComfyNode subclasses whose GET_SCHEMA() provides node_id, inputs/outputs as typed Input/Output objects, hidden flags, and behavior flags (is_output_node, not_idempotent, enable_expand, accept_all_inputs, loop_boundary). — [nodes.py#L2305-2335](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2305-L2335) [comfy_api/latest/_io.py#L1704-1780](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api/latest/_io.py#L1704-L1780) [comfy_api/latest/_io.py#L2296](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api/latest/_io.py#L2296)
- Frontend extension point: WEB_DIRECTORY module attr or pyproject.toml [tool.comfy] web dir registers a static JS dir served at /extensions/<name>; /extensions endpoint enumerates all JS for the frontend to import. — [nodes.py#L2270-2292](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2270-L2292) [server.py#L356-368](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L356-L368) [server.py#L1245-1247](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1245-L1247)
- Per-package prestartup hook: any custom_nodes/<pkg>/prestartup_script.py is exec'd before node loading, letting packages patch the environment early (used e.g. for dependency installs). — [main.py#L183-237](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L183-L237)
- Prompt mutation hook: PromptServer.add_on_prompt_handler registers callables run by trigger_on_prompt on every POST /prompt body before validation (exceptions are logged and skipped). — [server.py#L1459-1470](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1459-L1470) [server.py#L1079](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1079)
- HTTP route extension: custom nodes can append to PromptServer.instance.routes (the same RouteTableDef), and every added route is automatically mirrored under /api by add_routes. (inferred) — [server.py#L262-267](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L262-L267) [server.py#L1236-1243](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1236-L1243)
- Model path extension: extra_model_paths.yaml (example in repo root) and --extra-model-paths-config call utils.extra_config.load_extra_path_config which feeds folder_paths.add_model_folder_path to add search dirs per category. — [main.py#L140-149](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L140-L149) [utils/extra_config.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/utils/extra_config.py) [extra_model_paths.yaml.example](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/extra_model_paths.yaml.example) [folder_paths.py#L373-389](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L373-L389)
- Execution hooks for nodes: IS_CHANGED/fingerprint_inputs controls cache reuse; check_lazy_status marks required inputs for lazy evaluation; VALIDATE_INPUTS/validate_inputs custom-validates; ExecutionBlocker short-circuits branches; GraphBuilder lets a node emit an 'expand' subgraph. — [execution.py#L64-105](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L64-L105) [execution.py#L503-522](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L503-L522) [execution.py#L884-893](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L884-L893) [comfy_execution/graph_utils.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/graph_utils.py)
- Cache providers: comfy_execution/cache_provider.py exposes _get_cache_providers()/_has_cache_providers and PromptExecutor calls provider.on_prompt_start/on_prompt_end around each run — an external cache persistence seam. — [comfy_execution/cache_provider.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/cache_provider.py) [execution.py#L714-725](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L714-L725)
- Progress reporting is extensible via add_progress_handler in comfy_execution/progress.py; WebUIProgressHandler is the built-in implementation forwarding to the websocket client. — [comfy_execution/progress.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/progress.py) [execution.py#L753-754](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L753-L754)
- Feature flags: comfy_api/feature_flags.py maintains CLI_FEATURE_FLAG_REGISTRY (--list-feature-flag dumps it) and per-connection negotiation lets clients declare capabilities like supports_preview_metadata that change server behavior. — [comfy_api/feature_flags.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api/feature_flags.py) [main.py#L7-11](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L7-L11) [main.py#L436-447](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L436-L447)
- Comfy API versioning seam: comfy_api/version_list.supported_versions are registered through register_versions(ComfyAPIWithVersion) in init_public_apis, letting custom nodes target a stable versioned API surface (v0_0_1, v0_0_2, latest). — [nodes.py#L2566-2575](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2566-L2575) [comfy_api/version_list.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api/version_list.py) [comfy_api](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_api)
- NodeReplaceManager rewrites submitted prompt graphs (apply_replacements is invoked in post_prompt before validation) — a server-side node-substitution extension point. — [server.py#L1113](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1113) [app/node_replace_manager.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/node_replace_manager.py)
- comfyui_manager is an optional pip-installed extension enabled by --enable-manager that adds its own middleware, prestartup, and node-load policy hooks (should_be_disabled). — [main.py#L117-137](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L117-L137) [server.py#L245-246](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L245-L246) [nodes.py#L2375-2378](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2375-L2378)

## Contributor handoff

AGENTS.md is unusually prescriptive and is the first file to read: it demands minimal diffs, no new dependencies, no outbound network calls in core, strict layer boundaries (execution.py must not learn API/persistence concepts), no torch.no_grad wrappers (inference_mode already wraps execution), and reuse of comfy.ops/quant_ops/Comfy Kitchen optimized ops for model code. Read main.py -> server.py -> execution.py -> nodes.py -> folder_paths.py -> comfy/cli_args.py to understand any user-facing change. Tests: pytest tests-unit for fast checks; tests/execution needs a spawned server; tests/inference needs real models. Watch the traps: import-time side effects everywhere, tuple-indexed queue items, three different node ids (real/display/ephemeral), and signature-based caching that silently reuses outputs.
- AGENTS.md mandates: smallest possible diff, no new dependencies, no internet requests from core ComfyUI (no telemetry/upload/update-check code paths), and aggressive deletion of dead compat code. — [AGENTS.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/AGENTS.md)
- AGENTS.md architecture rule: keep layer boundaries — execution.py consumes the prompt graph and must not know workflow/frontend/persistence ids; fix leaks with caller-side mapping or narrow interfaces rather than passing context objects through. — [AGENTS.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/AGENTS.md)
- AGENTS.md model rules: never add torch.no_grad/inference_mode wrappers (execution is already inside torch.inference_mode), never add freeze/trainability toggles, prefer existing optimized ops in comfy.ops/comfy.quant_ops/Comfy Kitchen, and DiT models must tolerate non-patch-multiple latents via pad_to_patch_size. — [AGENTS.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/AGENTS.md) [execution.py#L751](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L751)
- Import order is load-bearing: torch must not be imported before main.py's late import block (it warns if 'torch' is in sys.modules), which is why ExecutionBlocker lives in comfy_execution/graph_utils.py rather than graph.py — keep heavy imports out of modules parsed early. — [main.py#L245-261](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L245-L261) [comfy_execution/graph.py#L9-10](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/graph.py#L9-L10)
- The args singleton from comfy.cli_args is parsed at import time and read by folder_paths at import time to fix base_path/models_dir — tests and embedding code must control argv or env carefully; comfy.options.enable_args_parsing() is the gate. — [comfy/cli_args.py#L61-64](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/cli_args.py#L61-L64) [folder_paths.py#L14-23](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L14-L23) [main.py#L1-4](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L1-L4)
- Queue tuple layout is positional and load-bearing: (number, prompt_id, prompt, extra_data, outputs_to_execute, sensitive); index 5 is stripped before exposure — preserve arity when modifying put/get/task_done or the remove_sensitive lambdas. — [server.py#L1134](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L1134) [main.py#L366-372](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/main.py#L366-L372) [server.py#L69-71](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L69-L71)
- Three node-id namespaces coexist: ephemeral ids (created by expand), display ids (UI mapping), and real ids (original prompt); always use dynprompt.get_real_node_id/get_display_node_id rather than raw ids in execution code. — [comfy_execution/graph.py#L49-68](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/graph.py#L49-L68) [execution.py#L439-443](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L439-L443)
- Caching can silently skip your code path: outputs are keyed by input signature including IS_CHANGED/fingerprint_inputs — when debugging a node that 'doesn't run', check CacheKeySetInputSignature and the node flags NOT_IDEMPOTENT / UNIQUE_ID hidden input first. — [comfy_execution/caching.py#L83-120](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy_execution/caching.py#L83-L120) [execution.py#L64-105](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/execution.py#L64-L105)
- Safe edit boundaries: add a node in nodes.py or a comfy_extras/nodes_*.py file (register in NODE_CLASS_MAPPINGS), add routes in the owning app/* manager, add model support via comfy/model_detection.py signature + comfy/supported_models entry — do not create parallel registries. — [nodes.py#L2068-2137](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2068-L2137) [nodes.py#L2394-2552](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/nodes.py#L2394-L2552) [app/model_manager.py#L28](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/app/model_manager.py#L28) [comfy/model_detection.py](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/comfy/model_detection.py)
- Run `pytest tests-unit` after changes; unit CI is continue-on-error so green CI does not prove correctness — for executor changes also run tests/execution which needs websocket-client and spawns main.py as a subprocess. — [tests-unit/README.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests-unit/README.md) [.github/workflows/test-unit.yml](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/.github/workflows/test-unit.yml) [tests/execution/test_execution.py#L505-562](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/tests/execution/test_execution.py#L505-L562)
- When touching file-serving endpoints, reuse folder_paths.is_within_directory/get_annotated_filepath and is_dangerous_content_type rather than hand-rolling checks — traversal/XSS guards are the most-reviewed security surface. — [folder_paths.py#L273-357](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/folder_paths.py#L273-L357) [server.py#L536-549](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/server.py#L536-L549) [AGENTS.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/AGENTS.md)
- Style: ruff lint (E, W, F, T print-usage, S102/S307, N805) with E501/E722/E731/E402 ignored; comments sparse; match local style — long lines and module-level state are normal here. — [pyproject.toml#L14-30](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/pyproject.toml#L14-L30) [AGENTS.md](https://github.com/Comfy-Org/ComfyUI/blob/b33e2b55cae074eca5aec96283cceac19aa249ba/AGENTS.md)

Source repository: https://github.com/Comfy-Org/ComfyUI
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/comfyui.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
