# ComfyUI Node Usage Stats

Node Stats logo

A ComfyUI custom node package that silently tracks which nodes, packages, and model files you actually use. Helps identify unused packages and models that are safe to remove — keeping your ComfyUI install lean. ## Features - **Silent tracking** — hooks into every prompt submission, zero config needed - **Node & model tracking** — tracks custom node packages and model files (checkpoints, VAEs, ControlNets, etc.) separately - **Per-package classification** — packages are sorted into tiers based on usage recency - **Per-model classification** — models grouped by type (checkpoints, vae, …) with the same recency tiers - **Smart aging** — items gradually move from "recently unused" to "safe to remove" over time - **Uninstall detection** — removed packages/models are flagged separately, historical data preserved - **Expandable detail** — click any package to see individual node-level stats - **One-click disable** — disable unused packages straight from the dialog via ComfyUI Manager (per-package or in bulk), reversible at any time - **Workflow tab** — on loading a workflow, splits unresolved nodes into *Missing* (install via Manager) and *Disabled*, with a temporary **Enable 7d** trial that auto-disables packages left unused - **Non-blocking** — DB writes happen in a background thread, no impact on workflow execution ## Package Classification Packages are classified into tiers based on when they were last used:
Used Actively used within the last month
Recently Unused Not used yet, but tracking started less than a month ago — too early to judge
Consider Removing Unused for 1–2 months — worth reviewing
Safe to Remove Unused for 2+ months — confident removal candidate
Uninstalled Previously tracked but no longer installed — shown for reference
## Installation ```bash cd /path/to/ComfyUI/custom_nodes git clone https://github.com/ethanfel/Comfyui-Nodes-Stats.git ``` Restart ComfyUI. Tracking starts immediately and silently. ## Usage ### UI Click the **Node Stats** button (bar chart icon) in the ComfyUI top menu bar. A dialog opens with three tabs: **Nodes tab** - Summary bar with counts for each classification tier - Sections for each tier, sorted from most actionable to least - Expandable rows — click any package to see per-node execution counts and timestamps - **Disable** buttons on the "Safe to Remove" and "Consider Removing" tiers (see below) ### Disabling unused packages When [ComfyUI Manager](https://github.com/ltdrdata/ComfyUI-Manager) is installed, the "Safe to Remove" and "Consider Removing" sections show a **Disable** button on each package, plus a **Disable all** button per section. Disabling: - Hands off to ComfyUI Manager, which moves the package into `custom_nodes/.disabled/` - Is fully reversible — re-enable any package from ComfyUI Manager whenever you like - Requires a ComfyUI restart to unload the package from the running session (a banner with a **Restart ComfyUI** button appears after disabling) If ComfyUI Manager is not installed, the disable buttons are hidden and stats work as before. ### Workflow tab & temporary enable Whenever you load a workflow, the extension scans for node types the running ComfyUI can't resolve and, if any are found, opens the dialog on the **Workflow** tab. Unresolved nodes are split into two groups: - **Missing** — the owning package isn't installed. Install is handled by [ComfyUI Manager](https://github.com/ltdrdata/ComfyUI-Manager) like always: the **Install** button opens Manager's Custom Nodes Manager (use its *Missing* filter). - **Disabled** — the package is installed but currently disabled. Each row offers: - **Enable 7d** — re-enable the package and start a *temporary trial*. - **Enable** — re-enable permanently (no trial). **The temporary trial** is a rolling budget of **7 distinct boot-days**. A "boot-day" is counted at most once per calendar day, the first time ComfyUI starts that day — so the clock measures days you actually run ComfyUI, not wall time. **Any execution that uses the package resets the counter to zero.** If a trial package goes its full budget of distinct boot-days without being used, it is **auto-disabled on the next UI load** (handed to ComfyUI Manager exactly like a manual disable) and the trial is cleared. As with any disable, a ComfyUI restart is required to fully unload it. Re-enabling and auto-disabling both go through ComfyUI Manager, so the whole Workflow tab is inert when Manager is not installed (the backend still tracks trial state, but no enable/disable actions are offered). **Models tab** - Summary bar with counts for each tier across all model types - Sections per model type (checkpoints, vae, controlnet, …) - Per-model table showing execution count, last used date, and status ### API | Endpoint | Method | Description | |----------|--------|-------------| | `/nodes-stats/packages` | GET | Per-package aggregated stats with classification | | `/nodes-stats/usage` | GET | Raw per-node usage data | | `/nodes-stats/models` | GET | Per-type model stats with classification | | `/nodes-stats/reset` | POST | Clear all tracked data | | `/nodes-stats/trials` | GET | Active temporary-enable trials with `days_remaining`/`expired` | | `/nodes-stats/trials/start` | POST | Begin/restart a trial — body `{"package": ""}` | | `/nodes-stats/trials/stop` | POST | End a trial (made permanent or disabled) — body `{"package": ""}` | ```bash curl http://localhost:8188/nodes-stats/packages | python3 -m json.tool ```
Example response ```json [ { "package": "ComfyUI-Impact-Pack", "total_executions": 42, "used_nodes": 5, "total_nodes": 30, "last_seen": "2026-02-22T12:00:00+00:00", "installed": true, "status": "used", "nodes": [ { "class_type": "SAMDetectorCombined", "package": "ComfyUI-Impact-Pack", "count": 20, "first_seen": "2026-01-01T00:00:00+00:00", "last_seen": "2026-02-22T12:00:00+00:00" } ] }, { "package": "ComfyUI-Unused-Nodes", "total_executions": 0, "used_nodes": 0, "total_nodes": 12, "last_seen": null, "installed": true, "status": "safe_to_remove", "nodes": [] } ] ```
## How It Works ``` Queue Prompt ──> Prompt Handler ──> Extract class_types + prompt ──> Background Thread │ ┌───────────────────────────────┘ ▼ SQLite DB usage_stats.db ┌─────────────┐ │ node_usage │ per-node counts & timestamps │ prompt_log │ full node list per prompt │ model_usage │ per-model counts & timestamps └─────────────┘ │ GET /nodes-stats/packages ◄─────────┤ GET /nodes-stats/models ◄─────────┘ │ ▼ Merge DB data with installed nodes/models, classify by recency │ ▼ JSON response ──> UI Dialog (Nodes tab / Models tab) ``` 1. Registers a prompt handler via `PromptServer.instance.add_on_prompt_handler()` 2. On every prompt submission, extracts `class_type` from each node and the full prompt dict 3. Offloads recording to a background thread (non-blocking) 4. Maps each class_type to its source package using `RELATIVE_PYTHON_MODULE` 5. Detects model file selections by introspecting each node's `INPUT_TYPES()` for folder-dropdown inputs, then resolves filenames via `folder_paths` 6. Upserts per-node and per-model counts and timestamps into SQLite 7. On stats request, merges DB data with current node registry / installed models and classifies by recency ## Data Storage All data is stored in `/nodes_stats/usage_stats.db` (survives extension reinstalls). | Table | Contents | |-------|----------| | `node_usage` | Per-node: class_type, package, execution count, first/last seen | | `prompt_log` | Per-prompt: timestamp, JSON array of all class_types used | | `model_usage` | Per-model: filename, type, execution count, first/last seen | | `trial_packages` | Per temporary-enable trial: package, enable date, unused-boot-day counter, budget | Use `POST /nodes-stats/reset` to clear all data and start fresh. ## Slow ComfyUI boot? Diagnose the model-folder scan If ComfyUI is slow to start at the "scanning model folders" / "Building node definitions" stage, the cause is almost always model folders on a slow (often network) filesystem: ComfyUI walks every registered model folder on each boot, and that cache is in-memory only (lost on restart). `tools/diagnose_model_scan.py` measures this the same way ComfyUI does and ranks the folders by scan cost, flags network mounts and their `actimeo`/`cache` options, and points at the worst offender. It is read-only. ```bash cd /path/to/ComfyUI python tools/diagnose_model_scan.py # 30s cap per folder python tools/diagnose_model_scan.py --timeout 600 --warm # full timing + warm pass ``` Typical fix for network-mounted model folders (CIFS): raise the attribute-cache timeout so the kernel keeps the listing warm across restarts, e.g. `actimeo=3600,acdirmax=3600,acregmax=3600,cache=loose`. ## File Structure ``` __init__.py Entry point: prompt handler, API routes mapper.py class_type → package mapping; model filename → type mapping tracker.py SQLite persistence and stats aggregation js/nodes_stats.js Frontend: menu button + stats dialog (Nodes/Models/Workflow tabs) tools/diagnose_model_scan.py Standalone: diagnose slow model-folder scans at boot pyproject.toml Package metadata tests/ Unit tests for tracker and mapper ```