ComfyUI Node Usage Stats
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:
Installation
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 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 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": "<dir-name>"} |
/nodes-stats/trials/stop |
POST | End a trial (made permanent or disabled) — body {"package": "<dir-name>"} |
curl http://localhost:8188/nodes-stats/packages | python3 -m json.tool
Example response
[
{
"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)
- Registers a prompt handler via
PromptServer.instance.add_on_prompt_handler() - On every prompt submission, extracts
class_typefrom each node and the full prompt dict - Offloads recording to a background thread (non-blocking)
- Maps each class_type to its source package using
RELATIVE_PYTHON_MODULE - Detects model file selections by introspecting each node's
INPUT_TYPES()for folder-dropdown inputs, then resolves filenames viafolder_paths - Upserts per-node and per-model counts and timestamps into SQLite
- On stats request, merges DB data with current node registry / installed models and classifies by recency
Data Storage
All data is stored in <ComfyUI user dir>/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.
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