# Attribute GC — TriliumNext Maintenance Tool Scans all notes in your TriliumNext database for broken relations, unused labels, rare attributes, and near-duplicate names. Preview and batch-delete them — **deletions persist**. > **v2.0** — Rewritten as a JS Frontend note with full `api.runOnBackend()` access. Scan and delete both work end-to-end on TriliumNext. The previous HTML Render Note approach (v1.x) could only detect — deletion did not persist. See [Why this works](#why-this-works). ## Features - **Full scan** — SQL-backed via `api.sql.getRows`. Classifies every label and relation by usage count and health. - **Broken relation detection** — Relations pointing to deleted or missing target notes. - **Rare attribute flagging** — Attributes used ≤2 times, plus temp/draft/test patterns. - **Semantic duplicate finder** — Levenshtein distance to surface near-identical names (`pipeline` vs `pipelne`, `autor` vs `autores`). - **Dry run mode** — Toggle on to preview what would be deleted without making changes. - **Batch deletion** — Auto-select all problematic attributes, then delete in one click. - **Protected attributes** — 50+ system/internal labels and relations are locked from deletion. - **Theme-aware** — Uses Trilium CSS variables, matches your theme automatically. ## Installation 1. Create a **JS Frontend** code note in TriliumNext 2. Paste the full content of `attribute-gc.js` 3. Choose your mode: - **Right panel widget**: add label `#widget`, reload (Ctrl+R), open any note - **Full-page Render Note**: create a Render Note, add relation `~renderNote` → JS Frontend, open the Render Note ## Usage 1. Click **Escanear** — stats dashboard appears with attribute counts 2. Filter by status (**Quebrados**, **Raros**, **Sem uso**, **Sistema**, **Saudáveis**) or search by name 3. Click **Auto-selecionar** to check all non-system problematic attributes, or tick individual rows 4. **Toggle Dry Run OFF** (yellow banner disappears) 5. Click **Executar limpeza** → confirm — attributes are permanently removed The individual **remover** button on each row works the same way (skips the batch dialog). ## Compatibility | Environment | Scan | Delete | |---|---|---| | **TriliumNext** | `api.sql.getRows` | `getNotesWithLabel` / `removeLabel` | | **Classic Trilium** | `api.sql.getRows` | `getNotesWithLabel` / `removeLabel` | Both use the same backend path — `api.runOnBackend()` with the standard entity API. Becca stays in sync, changes persist. ## Why this works v1.x used an **HTML Render Note** with inline `