# Zettelclean Keep a Zettelkasten filename's slug in sync with the note's H1 heading. Zettelclean resolves the "three sources of truth for a title" problem (filename vs H1 vs YAML `title:`) by separating concerns: - The **H1 heading** in the note body is the single source of truth for the human title. - The **filename** is a derived machine identity: `TIMEID-slug(H1).md`. - No YAML is written. Files stay pure Markdown. It is a small, one-way, prefix-gated renamer: edit the H1, and a moment later the filename's slug tail follows. Nothing else is touched. ## How it works - A note is a zettel when its filename starts with a **TIMEID**: a run of 12 to 18 digits (a timestamp), for example `20260728145404-my-note.md`. Files without that prefix are ignored, so plain notes, daily notes, Excalidraw and Kanban files are never renamed. - The TIMEID is minted **once** and never changes. Only the slug tail is regenerated. - When you edit the H1, zettelclean waits about 5 seconds of idle, then renames the file to `TIMEID-slug(H1).md` using Obsidian's own rename (so backlinks are updated). A 10 second cooldown prevents a just-renamed file from being renamed again. - Sync is strictly one-way, H1 to filename. Renaming a file by hand is never fought. - Delete the H1 and the filename collapses back to the bare `TIMEID.md`. The slug is lowercase, ASCII, dash-separated: accents are folded (`Ciências` becomes `ciencias`), runs of punctuation and whitespace collapse to a single dash, and leading and trailing dashes are trimmed. ## Creating notes Use Obsidian's built-in **Unique note creator** core plugin to mint the TIMEID: 1. Settings -> Core plugins -> enable "Unique note creator". 2. Set "Unique note format" to `YYYYMMDDHHmmss` (14 digits, second precision - avoids same-minute collisions). 3. Click the "Create new unique note" ribbon icon. You get `20260728145404.md`; type your `# Title`, and zettelclean takes over from there. Zettelclean also accepts an existing 12-digit (`YYYYMMDDHHmm`) vault if you prefer not to change the setting. ### Retrofitting existing notes Notes created before you adopted this workflow have no TIMEID. Right-click such a note in the file explorer and choose **"Add zettel TIMEID to filename"**. It mints a fresh timestamp, prepends it, and the note is now a zettel that syncs on future H1 edits. ## Pretty sidebar (optional) By default the file explorer shows the slugged filename (with dashes). If you want the sidebar, tabs and graph to show the pretty H1 instead - with no YAML in your files - install the **Front Matter Title** community plugin and set its feature templates to: ``` #heading | _basename ``` That reads the first H1 directly and falls back to the filename when there is none. ## Settings None. Zettelclean is zero-config in this version. The 5 second settle and 10 second cooldown are fixed. ## Development - `npm install` (or `pnpm install`). - `npm run dev` - compile in watch mode. - `npm run build` - typecheck and produce `main.js`. - `npm test` - run the slug unit tests on Node's built-in test runner. - `npm run lint` - eslint with the Obsidian ruleset. The pure string logic lives in `src/slug.ts` and is unit-tested in isolation; the Obsidian wiring lives in `src/main.ts`. ## License 0-BSD.