Rewrite README with classification docs, logo, and status icons

Updated documentation to reflect the 4-tier classification system
and uninstalled detection. Added SVG logo and color-coded status
indicator dots. Added architecture diagram and collapsible API
response example.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 14:01:39 +01:00
parent ae2c786d3a
commit 43a4fdee16
7 changed files with 153 additions and 35 deletions

136
README.md
View File

@@ -1,15 +1,46 @@
# ComfyUI Node Usage Stats
A ComfyUI custom node package that silently tracks which nodes and packages you actually use. Helps identify never-used packages that are safe to remove.
<p align="center">
<img src="docs/logo.svg" width="120" alt="Node Stats logo">
</p>
A ComfyUI custom node package that silently tracks which nodes and packages you actually use. Helps identify unused packages that are safe to remove — keeping your ComfyUI install lean.
## Features
- Tracks every node used in every workflow execution
- Maps each node to its source package
- SQLite storage for efficient querying
- Per-package aggregated stats (total nodes, used/unused, execution counts)
- Frontend dialog with never-used packages highlighted for removal
- Expandable rows to see individual node-level stats within each package
- **Silent tracking** — hooks into every prompt submission, zero config needed
- **Per-package classification** — packages are sorted into tiers based on usage recency
- **Smart aging** — packages gradually move from "recently unused" to "safe to remove" over time
- **Uninstall detection** — removed packages are flagged separately, historical data preserved
- **Expandable detail** — click any package to see individual node-level stats
- **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:
<table>
<tr>
<td><img src="docs/status_used.svg" width="18"> <b>Used</b></td>
<td>Actively used within the last month</td>
</tr>
<tr>
<td><img src="docs/status_unused_new.svg" width="18"> <b>Recently Unused</b></td>
<td>Not used yet, but tracking started less than a month ago — too early to judge</td>
</tr>
<tr>
<td><img src="docs/status_consider.svg" width="18"> <b>Consider Removing</b></td>
<td>Unused for 12 months — worth reviewing</td>
</tr>
<tr>
<td><img src="docs/status_safe.svg" width="18"> <b>Safe to Remove</b></td>
<td>Unused for 2+ months — confident removal candidate</td>
</tr>
<tr>
<td><img src="docs/status_uninstalled.svg" width="18"> <b>Uninstalled</b></td>
<td>Previously tracked but no longer installed — shown for reference</td>
</tr>
</table>
## Installation
@@ -24,28 +55,26 @@ Restart ComfyUI. Tracking starts immediately and silently.
### UI
Click the **"Node Stats"** button in the ComfyUI menu. A dialog shows:
Click the **Node Stats** button (bar chart icon) in the ComfyUI top menu bar. A dialog shows:
- Summary: how many packages are never-used vs used
- **Never Used** section (highlighted) — safe to remove
- **Used** section sorted by least-to-most executions
- Click any row to expand and see individual node stats
- **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
### API
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/nodes-stats/packages` | GET | Per-package aggregated stats |
| `/nodes-stats/packages` | GET | Per-package aggregated stats with classification |
| `/nodes-stats/usage` | GET | Raw per-node usage data |
| `/nodes-stats/reset` | POST | Clear all tracked data |
Example:
```bash
curl http://localhost:8188/nodes-stats/packages | python3 -m json.tool
```
### Package stats response format
<details>
<summary>Example response</summary>
```json
[
@@ -54,8 +83,9 @@ curl http://localhost:8188/nodes-stats/packages | python3 -m json.tool
"total_executions": 42,
"used_nodes": 5,
"total_nodes": 30,
"never_used": false,
"last_seen": "2026-02-22T12:00:00+00:00",
"installed": true,
"status": "used",
"nodes": [
{
"class_type": "SAMDetectorCombined",
@@ -65,34 +95,70 @@ curl http://localhost:8188/nodes-stats/packages | python3 -m json.tool
"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": []
}
]
```
## File Structure
```
__init__.py # Entry point: prompt handler, API routes
mapper.py # class_type -> package name mapping
tracker.py # SQLite persistence and stats aggregation
js/
nodes_stats.js # Frontend: menu button + stats dialog
pyproject.toml # Package metadata
```
</details>
## How It Works
```
Queue Prompt ──> Prompt Handler ──> Extract class_types ──> Background Thread
┌─────────────────────────┘
SQLite DB
usage_stats.db
┌──────────┐
│node_usage │ per-node counts & timestamps
│prompt_log │ full node list per prompt
└──────────┘
GET /nodes-stats/packages ◄──┘
Mapper merges DB data
with NODE_CLASS_MAPPINGS
Classify by recency ──> JSON response ──> UI Dialog
```
1. Registers a prompt handler via `PromptServer.instance.add_on_prompt_handler()`
2. On every prompt submission, extracts `class_type` from each node
3. Maps each class_type to its source package using `RELATIVE_PYTHON_MODULE`
4. Stores per-node counts and timestamps in SQLite (`usage_stats.db`)
5. Also logs the full set of nodes per prompt for future trend analysis
2. On every prompt submission, extracts `class_type` from each node in the workflow
3. Offloads recording to a background thread (non-blocking)
4. Maps each class_type to its source package using `RELATIVE_PYTHON_MODULE`
5. Upserts per-node counts and timestamps into SQLite
6. On stats request, merges DB data with current node registry and classifies by recency
## Data Storage
All data is stored in `usage_stats.db` in the package directory. Two tables:
All data is stored in `usage_stats.db` in the package directory.
- **node_usage**: per-node counts, first/last seen timestamps
- **prompt_log**: JSON array of nodes used per prompt, with timestamp
| 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 |
Use `POST /nodes-stats/reset` to clear all data.
Use `POST /nodes-stats/reset` to clear all data and start fresh.
## File Structure
```
__init__.py Entry point: prompt handler, API routes
mapper.py class_type → package name mapping
tracker.py SQLite persistence and stats aggregation
js/nodes_stats.js Frontend: menu button + stats dialog
pyproject.toml Package metadata
```