puhhh2k downloadsFork of oz-clear-unused-images for clearing unused images from vaults.
Clear Unused Images Plus is an Obsidian plugin for finding and deleting images that are no longer referenced in your vault. It scans markdown notes, supported frontmatter references, canvas files, and attachment links, then compares those references against image files in the vault.
Use it when attachments accumulate over time and you want cleanup to follow Obsidian's own deletion behavior instead of bypassing your vault settings.
This project is a maintained fork of oz-clear-unused-images. The current fork is maintained by Aleksei B. The original plugin author is Ozan.
See CHANGELOG.md for release history.


Requirements: Obsidian 1.8.10 or newer.
Clear Unused Images Plus..trash.Clear unused images from the Command Palette.Deleted files and folders follow Obsidian's own file deletion preference:
.trash inside the vault.The plugin provides three cleanup commands:
Clear unused images checks only image files. It is limited to jpg, jpeg, png, gif, svg, bmp, and webp. When image folder rules are configured, a manual run also reviews matching image-containing folders as atomic units.Clear unused attachments checks all non-note attachments in the vault, not just images. This can include PDFs, audio, video, archives, and other non-markdown files. When attachment folder rules are configured, it also reviews each selected folder and its descendants as one atomic attachment unit.Clear unused folders removes empty folders recursively, starting with the deepest folders first. It follows Obsidian's file deletion preference and keeps folders under excluded folder paths.Use Clear unused images for routine image cleanup. Use Clear unused attachments more carefully because it has a wider scope: it can move any unreferenced non-note attachment, or every descendant of an approved matching attachment folder, to trash. The attachment cleanup flow always shows a review modal before deletion. Use Clear unused folders after file cleanup if you want to remove empty folder structure left behind, or enable Clear empty folders after image cleanup to do that automatically.
You can run cleanup from the ribbon icon or from the Command Palette with Ctrl/Cmd + P.
![]()

If Delete Logs is enabled, the plugin shows a modal with information about deleted files:

If all images are still used, the plugin reports that nothing was deleted:

Use Image folder rules to treat selected folders and everything inside them as atomic image units during manual Clear unused images. The rule syntax is the same as Attachment folder rules: case-insensitive suffixes, case-sensitive parent paths, exact-name recursive parents, and anchored case-sensitive regular expressions.
For example, the parent path rule attachments selects each immediate child folder under attachments, but not the parent itself or deeper folders separately. A matching folder is considered only when it contains at least one jpg, jpeg, png, gif, svg, bmp, or webp descendant.
Clear unused images. Vault-load and periodic cleanup never plan or delete matching folders.Review image folder cleanup can disable that preview for manual image cleanup. When it is off, loose unused images, whole matching folders (including Markdown and non-image descendants), and eligible empty direct parents may move to Obsidian-configured trash without confirmation. Clear unused attachments still always requires review, and automatic cleanup still ignores image folder rules.Clear empty folders after image cleanup is enabled. When that setting is off, the selected folders are removed but their parents stay. Cleanup never cascades to higher ancestors.Use Attachment folder rules to treat a selected folder and everything inside it as one atomic attachment during manual Clear unused attachments. Separate rules with commas or put one rule on each line.
| Rule | Behavior |
|---|---|
.html |
Legacy suffix rule. Selects folders whose names end with .html. Suffix matching is case insensitive. |
Attachments |
Parent path rule. Selects the immediate child folders of the vault-relative Attachments path. Matching is case sensitive. It does not select Attachments itself or deeper descendants. |
**/attachments |
Recursive parent rule. Selects the immediate child folders under every folder whose exact path segment is attachments, whether it is at the vault root or nested. Matching is case sensitive and does not match Attachments, attachments-old, or my attachments. |
/^Attachments\/[^/]+$/ |
Regular expression rule. Tests the expression, case sensitively, against each folder's full vault-relative path. This example selects only immediate children of Attachments. |
Clear unused attachments. It does not affect Clear unused images, vault-load cleanup, periodic cleanup, or Clear unused folders.^ and $. For predictable linear matching, the supported subset allows literals, escapes, character classes, and at most one +, *, or ? quantified character class per path segment. Groups, alternation, wildcards, lookarounds, flags, backreferences, and bounded quantifiers are rejected.You can configure up to 50 rules, with a maximum of 256 characters each. Legacy suffixes remain limited to 64 characters. Parent paths must be vault relative and cannot contain empty, . or .. segments or backslashes. A recursive parent rule must be **/ followed by exactly one literal folder name.
Recursive parent rules were introduced after 1.9.0. In 1.9.0 and earlier, **/attachments was treated as a literal parent path; the recursive interpretation now selects that literal location plus immediate children under every other exact attachments folder segment. Legacy standalone **, multi-segment **/... values, and wildcard-like names are now rejected fail-closed instead of being treated as literal paths. Every newly selected folder still goes through the normal review and deletion safeguards.
Enable Clean Images On Vault Load to run image cleanup once after the vault layout is ready:

Clear unused attachments.Image folder rules; it continues deleting only individual unused images.Enable Clean Images Every X Minutes to run recurring image cleanup while Obsidian stays open:

Image folder rules; it continues deleting only individual unused images.Enable Clear empty folders after image cleanup to remove folders that become empty after unused image cleanup deletes images:

Clear unused images, Clean Images On Vault Load, and Clean Images Every X Minutes.Clear unused attachments.Clear unused images with image folder rules, it also controls whether an eligible direct parent folder is removed after its selected folders are deleted and it becomes empty.Use excluded folders to prevent cleanup from deleting files under specific vault paths. Separate multiple folders with commas and provide full paths inside the vault.

Turn on Exclude subfolders if the excluded paths should protect every child folder too:

Use Excluded file extensions to keep specific file types regardless of whether they are linked from any note. Separate extensions with commas; matching is case insensitive and a leading dot is optional (pdf, .mp4 both work). This is handy when you store files in the vault but never attach them — for example PDFs opened with Obsidian's PDF viewer.
npm ci
npm run dev
npm test
npm run build
npm ci installs the locked dependency set used by CI and release builds.npm install is fine when you intentionally update dependencies.npm run dev builds in watch mode.npm test runs the Vitest suite.npm run build creates the production main.js bundle.npm run build, refresh the installed vault copy before manual testing:cp main.js .obsidian/plugins/clear-unused-images-plus/main.js
cp styles.css .obsidian/plugins/clear-unused-images-plus/styles.css
git diff --no-index -- main.js .obsidian/plugins/clear-unused-images-plus/main.js
git diff --no-index -- styles.css .obsidian/plugins/clear-unused-images-plus/styles.css
No output means the local Obsidian plugin copy is in sync.
GitHub Releases are published by GitHub Actions when a version tag is pushed.
package.json, package-lock.json, manifest.json, versions.json, and CHANGELOG.md.npm run lint, npm test, and npm run build.main.js and styles.css into .obsidian/plugins/clear-unused-images-plus/ for manual Obsidian verification.main, and merge it.main:git tag -s -m "X.Y.Z" X.Y.Z HEAD
git push origin main
git push origin X.Y.Z
The release workflow verifies that the tag version matches package.json, manifest.json, and versions.json, runs the release audit, rebuilds main.js, creates GitHub artifact attestations, and uploads manifest.json, main.js, and styles.css as release assets. Obsidian requires the GitHub release tag to match manifest.json exactly, so use 1.0.0, not v1.0.0.
src/main.ts - Obsidian plugin entry pointsrc/util.ts - vault scanning and cleanup orchestrationsrc/linkDetector.ts - markdown and wikilink reference detectionsrc/referenceUtils.ts - pure reference and path helperssrc/attachmentFolders.ts - atomic attachment-folder planning, safety checks, and deletion revalidationsrc/folderCleanup.ts - empty-folder cleanup behaviortests/ - regression coverage for cleanup, references, settings, and schedulingdocs/assets/ - screenshot assets used in this READMEstyles.css - plugin stylesmain.js - built plugin bundleTests use vitest, with jsdom available through per-file @vitest-environment jsdom comments when DOM coverage is needed. The most important coverage is around markdown links, wikilinks, frontmatter references, canvas parsing, excluded folders, delete failure handling, and startup or periodic cleanup scheduling. Run npm run lint and npm test before publishing changes.
When fixing safety bugs, add a focused regression first, verify it fails, then fix the implementation. For deletion or exclusion bugs, cover both helper behavior and cleanup-flow results.
main.js is generated; do not edit it by hand..obsidian/plugins/clear-unused-images-plus/ is for testing only and is not part of the Git repository.