{"slug": "shelf-sorting-downloads-offline-with-a-23-mb-open-model", "title": "Shelf: sorting Downloads offline with a 23 MB open model", "summary": "A developer built Shelf, an Apache-2.0 command-line tool that sorts a Downloads folder offline using the 23 MB 8-bit ONNX export of all-MiniLM-L6-v2 for plain-text files, with extension rules handling photos, PDFs and archives. The tool scores each file against short per-folder prototype sentences and only moves it when the top folder beats the runner-up by at least 0.05 cosine similarity, otherwise sending it to Unsorted, and it offers a dry run plus an undo log. The developer reports the embedding approach got 7 of 10 synthetic text files right, after an initial chat-model attempt with Qwen2.5 0.5B and 1.5B that got only 2 or 3 right.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19)*\n\nShelf is a command-line tool that tidies a messy folder. Point it at your Downloads folder and it shows you where every top-level file would go. When you're happy with the plan, you run it again with `--apply` and the files move into folders like `Documents`, `Images` and `Receipts`.\n\nPhotos, PDFs and archives are sorted by their extension, so no model is involved. Plain-text files are different: a `.txt` or `.md` file tells you nothing about what it contains. For those, a small open-weight sentence embedding model reads the first 1,000 characters and compares them with short descriptions of each folder. If it can't clearly pick one, the file goes to `Unsorted` instead of a guessed folder.\n\nIt's for anyone who keeps putting off the clutter. You don't have to decide where each file goes, and you don't have to delete anything to make room.\n\nThere is no hosted version, because the tool runs on your own machine. Here is what a dry run prints on a folder of ten sample text files plus a few binaries:\n\n``` php\n01-shop.txt      -> Receipts/01-shop.txt  (model)\n02-appt.txt      -> Letters/02-appt.txt   (model)\n03-cake.txt      -> Recipes/03-cake.txt   (model)\n04-parse.txt     -> Unsorted/04-parse.txt (unsorted)\nholiday.jpg      -> Images/holiday.jpg    (rule)\ntaxes.pdf        -> Documents/taxes.pdf   (rule)\n\nDry run: nothing was moved. Run again with --apply to move these files.\n```\n\nThe output shows the reason for each decision, so you can check the plan before anything moves.\n\nGitHub: [https://github.com/Shishir2405/shelf](https://github.com/Shishir2405/shelf) (Apache-2.0)\n\n**Stack.** TypeScript on Node.js 20, with no framework. The only runtime dependencies are `@huggingface/transformers` for the model and `zod` for validating the undo log.\n\n**Model.** `Xenova/all-MiniLM-L6-v2`, an ONNX export of `sentence-transformers/all-MiniLM-L6-v2`, licensed Apache-2.0. I use the 8-bit weights, which are about 23 MB on disk. The model is downloaded once to `~/.cache/shelf/models`. After that, sorting needs no network.\n\n**How a text file is decided.** Each folder has two or three short prototype sentences, such as \"a receipt listing items, subtotal, tax and total paid\". The file's text is embedded once, and each folder is scored by its best-matching prototype. The top folder wins only if it beats the runner-up by at least 0.05 cosine similarity. Otherwise the file is `Unsorted`. Any answer outside the allowed folder list is discarded, so the model cannot create folders on its own.\n\n**What I tried first.** My first plan used a chat model, Qwen2.5 in 0.5B and 1.5B sizes, to pick a folder. On ten labeled sample files it got 2 or 3 right, and it kept choosing the same folder regardless of content. Scoring folder names by log-probability did not help. The 1.5B model was about 1.6 GB and was no better. Switching to a sentence embedder with a much smaller model fixed the problem.\n\n**Safety.** This was the part I cared most about, because a file tidier that loses files is worse than no tidier at all:\n\n`--apply`.` report (2).pdf`.`.shelf-log.json`. `shelf undo <folder>` reverses the last run, and anything it can't restore safely is reported and left alone.\n**Tests.** 31 unit and integration tests run without downloading the model. They cover the rules, name collisions, the decision margin, the dry run, the undo, and a folder with a symlink and a hidden file. CI runs the same validation: typecheck, lint, format check, tests and build.\n\n**Measured, honestly.** On ten synthetic text files that I wrote for this test, the real model got 7 right. Two went to `Unsorted` and one was wrong: a line of code containing the word \"total\" went to `Receipts`. The folder descriptions were edited while I looked at these files, so this number is optimistic. There is no held-out benchmark yet.\n\nWhat the open approach made possible here:\n\nWhat a closed API would have done better: a larger model would almost certainly be more accurate on messy text. I accepted lower accuracy to keep the files local.\n\nNo DevRelay session was saved for this project, so I'm not including one.\n\nI haven't measured how much time it saves, so I'm not claiming a number. What it removes is the decision on every file: the dry run shows the whole plan, and the undo log means a wrong guess costs one command to reverse.", "url": "https://wpnews.pro/news/shelf-sorting-downloads-offline-with-a-23-mb-open-model", "canonical_source": "https://dev.to/shishir_shrivastava_86e7f/shelf-sorting-downloads-offline-with-a-23-mb-open-model-19pe", "published_at": "2026-10-21 17:27:05+00:00", "updated_at": "2026-10-21 17:40:09.077478+00:00", "lang": "en", "topics": ["ai-tools", "machine-learning", "natural-language-processing", "developer-tools"], "entities": ["Shelf", "Shishir2405", "all-MiniLM-L6-v2", "Qwen2.5", "Hugging Face", "GitHub", "Hacktoberfest"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/shelf-sorting-downloads-offline-with-a-23-mb-open-model", "markdown": "https://wpnews.pro/news/shelf-sorting-downloads-offline-with-a-23-mb-open-model.md", "text": "https://wpnews.pro/news/shelf-sorting-downloads-offline-with-a-23-mb-open-model.txt", "jsonld": "https://wpnews.pro/news/shelf-sorting-downloads-offline-with-a-23-mb-open-model.jsonld"}}