Comfy-Org/ComfyUI
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.
- 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.
- 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.
- 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.
- 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().
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.