TriliumNext-Toolkit/Attribute-Garbage-Collector/README.md
2026-05-15 23:06:07 -03:00

5 KiB

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.

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 <script> tags. TriliumNext sandboxes HTML notes — api is not available, fetch() calls return 401, froca mutations are local-only, and all deletion attempts failed to persist.

v2.0 is a JS Frontend note — the standard Trilium extension format (same as Canvas Linker, Word Count, Task Planner). It has direct access to:

  • api.runOnBackend() — execute backend code
  • api.sql.getRows() — SQL queries for fast aggregation
  • api.getNotesWithLabel() / api.getNotesWithRelation() — find notes by attribute
  • note.removeLabel() / note.removeRelation() — delete through the entity lifecycle

No hacks, no workarounds. The same pattern used by every other Trilium plugin.

How it works

Scan

api.runOnBackend(() => {
    // SQL aggregation — one query, instant results
    api.sql.getRows(`SELECT name, type, COUNT(*) ... GROUP BY name, type`);
    // Broken relation detection
    api.sql.getRows(`SELECT ... LEFT JOIN ... WHERE target IS NULL`);
});

Delete

api.runOnBackend((names, types) => {
    for (const name of names) {
        const notes = api.getNotesWithLabel(name);  // or getNotesWithRelation
        for (const note of notes) {
            note.removeLabel(name);  // goes through Becca → persisted to DB
        }
    }
}, [names, types]);

Context detection

The same JS file auto-detects whether it's loaded as a widget (#widget label) or a render note dependency (~renderNote relation), adjusting layout and sizes accordingly.

Protected attributes

template, workspace, iconClass, cssClass, run, runOnInstance, runAtStartup, shareAlias, shareHiddenFromTree, archived, pinned, bookmarked, weight, color, renderNote, child, runOnNoteCreation, noteType, mime, shareCss, shareJs, shareRaw, shareDisallowRobotIndexing, keyboardShortcut, label, relation, promoted, multiplicity, labelDefinition, relationDefinition, toc, readOnly, excludeFromExport, appCss, appTheme, sorted, sortDirection, sortFoldersFirst, top, hide, hidePromotedAttributes, disableVersioning, calendarRoot, dateNote, datePattern, inbox, sqlConsole, searchHome, hoistedNote, similarNotes, versioningLimit, mapRootNoteId, system, root


🌐 Idioma / Language: A interface está em português brasileiro (PT-BR). Para traduzir, abra o arquivo attribute-gc.js no Trilium e substitua as strings de texto.

License

MIT


Images

screen capture