Managing a Model Library: Storage, Naming and Versions
By the end of this lesson you will have one copy of each model on your disk instead of three, every engine in this course reading from it, a record beside each file saying where it came from and what it hashes to, and a rule for deciding what to delete that is better than “whatever is biggest when the disk fills up”.
This is the least exciting page in this part. It is also the one that decides whether Part 9 is a pleasant afternoon or a day of re-downloading things you already have.
The problem, stated plainly
Section titled “The problem, stated plainly”By the end of Part 9 you will have four programs that all want the same weights, and each of them has its own idea of where weights live:
llama.cppreads whatever path you give--model. It has no library at all, which makes it the easiest to satisfy.- Ollama keeps a content-addressed store of blobs plus one manifest per tag, at
~/.ollama/modelson macOS,/usr/share/ollama/.ollama/modelson Linux andC:\Users\%username%\.ollama\modelson Windows. - LM Studio expects
~/.lmstudio/models/publisher/model/model-file.gguf— three levels, publisher then model then file. - The Hugging Face cache, which
transformers,mlx-lm, vLLM and thehfcommand all share, at~/.cache/huggingface/hubby default.
Left alone, a household that experiments with all four ends up with the same 5 GB file four times, under four names, with no record of which conversion any of them is. The fix is one directory and three ways of pointing at it.
One download, four readers
- Download once, verifiedhf download into ~/models/<publisher>/<repository>/, checksum checked against the Hub, .sha256 written beside the file. This is Part 4's fetch-model.sh.
- llama.cpp reads the pathllama-server --model ~/models/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf. Nothing to configure.
- LM Studio reads a symbolic linkA link at ~/.lmstudio/models/Qwen/Qwen3-8B-GGUF/ pointing into the library satisfies the publisher/model/file layout without a second copy.
- Ollama reads a ModelfileFROM ./Qwen3-8B-Q4_K_M.gguf imports the file into its own store once, under a name you chose, with the template and parameters you chose.
- Everything Python reads the cacheHF_HOME or HF_HUB_CACHE moves the shared cache onto the same disk, so the safetensors originals are somewhere you can find and prune.
Planning the disk before you fill it
Section titled “Planning the disk before you fill it”Storage plans go wrong because people budget for the model they want and not for the four they will try. A workable rule is to plan for three models at your tier plus one tier above, which is roughly three times the size of your usual model, and to keep the small one permanently because it costs almost nothing and answers most of your “does this script work” questions.
| Memory tier | A sensible resident set | Rough library size |
|---|---|---|
| 8 GB | Qwen3-1.7B Q8_0, Qwen3-4B Q4_K_M | under 5 GB |
| 12–16 GB | the above plus Qwen3-8B Q4_K_M | about 10 GB |
| 24 GB | the above plus Qwen3-14B Q4_K_M | about 20 GB |
| 32 GB | the above plus gpt-oss-20b MXFP4 | about 35 GB |
| 48–64 GB | the above plus Qwen3-30B-A3B Q4_K_M | about 55 GB |
| 96–128 GB | the above plus one very large model | 120 GB and up |
Those are file sizes, from Part 4’s table of published sizes on the Hub. The number that actually fills a disk is larger, because the Hugging Face cache keeps the safetensors originals of anything you converted, and because a model kept in two formats — GGUF for llama.cpp and MLX for a Mac — is two files by necessity, not by accident.
The Hugging Face cache, which is not a directory of models
Section titled “The Hugging Face cache, which is not a directory of models”Anyone who has looked inside ~/.cache/huggingface/hub and given up deserves an
explanation. The documentation gives one: each repository becomes a folder named
models--<org>--<name>, and inside it are four directories with different jobs.
blobsholds “the actual files that we have downloaded. The name of each file is their hash.”snapshotsholds one folder per revision, containing symbolic links with the real file names, pointing at the blobs. This is the layout that lets two revisions of a repository share an unchanged file instead of storing it twice.refsrecords which commit a branch name currently points at.treescaches the file list of a commit, so re-downloading something already cached costs a single network call rather than one per file.
Two practical consequences. Deleting things by hand from inside that tree breaks the
bookkeeping, which is why the CLI has its own delete commands. And on Windows, where
symbolic links need Developer Mode or an administrator, the documentation says the library
“does not use the blobs/ directory but directly stores the files in the snapshots/
directory instead”, so the same file downloaded at two revisions is stored twice. If you are
on Track N under Windows and the cache is larger than the sum of your models, that is why.
The cache also writes a CACHEDIR.TAG file, which “tells backup tools (e.g. Borg, restic,
rsync) that the directory contains re-downloadable cache data and can safely be excluded
from backups”. Honour it. Backing up sixty gigabytes of files that a single command can
fetch again is a waste of the backup you actually need, which is the one in this part’s lab.
RunnableAll tracks
export HF_HOME=/data/hfhf download Qwen/Qwen3-4B-GGUF Qwen3-4B-Q4_K_M.gguf --local-dir ~/models/Qwen/Qwen3-4B-GGUFHF_HOME moves the whole Hugging Face home; HF_HUB_CACHE moves only the hub cache. Set it
in your shell profile, not per command, or you will end up with two caches and no idea which
is which.
Making the other tools read your library
Section titled “Making the other tools read your library”LM Studio: a link in the right shape
Section titled “LM Studio: a link in the right shape”LM Studio’s requirement is a path shape, not a file format, and a symbolic link satisfies a path shape:
RunnableTrack M · Apple silicon
mkdir -p ~/.lmstudio/models/Qwenln -s ~/models/Qwen/Qwen3-8B-GGUF ~/.lmstudio/models/Qwen/Qwen3-8B-GGUFlms lsThe same works on Linux. On Windows, a link needs Developer Mode or an elevated shell, for
the same reason the Hugging Face cache degrades there; lms import copying the file is the
supported alternative, at the cost of a second copy.
Ollama: a Modelfile, or a different store
Section titled “Ollama: a Modelfile, or a different store”Ollama will not read a loose GGUF file from an arbitrary path at run time, but the Modelfile
reference documents FROM ./ollama-model.gguf as a way to build a model from one:
RunnableAll tracks
printf 'FROM %s/models/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf\nPARAMETER num_ctx 8192\n' "$HOME" > Modelfileollama create qwen3-8b-local -f Modelfileollama listThat imports the weights into Ollama’s own store, so it is a copy — the honest trade is that
you get Ollama’s scheduler and one extra copy of one model, rather than a copy of everything.
If you would rather have Ollama’s whole store on the library disk, OLLAMA_MODELS moves it,
and on Linux the FAQ is explicit that the service user needs access:
sudo chown -R ollama:ollama <directory>.
Naming and recording, so that six months later you know what you have
Section titled “Naming and recording, so that six months later you know what you have”Part 4 set the rule: keep the publisher’s namespace in the path, so
~/models/Qwen/Qwen3-8B-GGUF/Qwen3-8B-Q4_K_M.gguf rather than ~/models/qwen3-8b.gguf.
Three things belong beside the file, and none of them is expensive:
- The checksum. A
.sha256file next to the weights, written at download time, is what turns “the model started behaving oddly” into a question you can answer in a minute. - The provenance. Which repository, which revision, which day. A community quantisation is a legitimate artefact and it is not the publisher’s file; when your benchmark disagrees with somebody else’s, this is the first difference to check.
- The reason. One line in the library README saying what this model is for on this machine. Future you will not remember why there are two 8B models.
The hf CLI can check the first of those against the Hub for a whole directory at once.
hf cache verify Qwen/Qwen3-8B-GGUF --local-dir ~/models/Qwen/Qwen3-8B-GGUF validates every
local file in that directory against the checksums the Hub publishes and exits non-zero on a
mismatch:
Output — what you should see
Verified 13 file(s) for 'Qwen/Qwen3-8B-GGUF' (model) in ... All checksums match.Pruning, with a rule instead of a panic
Section titled “Pruning, with a rule instead of a panic”Deleting models is the part people do badly, usually at midnight when a download has failed for lack of space. Decide the rule in advance.
A rule that works: keep anything you have benchmarked, anything smaller than 3 GB, and anything you used this month; delete the rest, largest first. Benchmarked models are worth keeping because a comparison across time needs the same artefact at both ends. Small models are worth keeping because they cost nothing and save minutes every day. Everything else is one download away.
Start by seeing what you have, in each of the three stores:
RunnableAll tracks
du -sh ~/models/*/* | sort -h | tail -20ollama listhf cache lshf cache ls aggregates by repository and shows size, last access and last modification, and
it accepts filters such as --filter "accessed>30d", which is very close to the rule above
written as a command.
Both cache commands accept --dry-run, which prints what would go and removes nothing, and
--yes for when you are scripting it. Preview first, always; then delete the one you meant:
RunnableAll tracks
ollama listollama rm qwen3-8b-localhf cache prune is the safe one to run regularly: an unreferenced revision is by definition
one that no branch or tag points at any more, and the .incomplete files it removes are
partial downloads that nothing will ever use. hf cache rm and ollama rm are the ones to
read twice.
Make promotion and rollback operations explicit
Section titled “Make promotion and rollback operations explicit”Use separate concepts for a downloaded candidate, an evaluated artefact and an active service alias. A download becomes a candidate after integrity and provenance checks. It becomes eligible for use after the task evaluation. Updating the alias is the promotion step, and the previous mapping is the rollback record.
For every promoted model, retain the source repository and revision, exact file hashes, licence, conversion recipe, tokeniser/template identity and evaluation result. Include context and memory limits in the alias’s deployment configuration. An alias called “chat” should remain stable for clients even when the underlying checkpoint changes, but its history must remain inspectable.
Before removing an old model, check whether adapters, quantised derivatives or saved experiments depend on it. A small adapter can require a large exact base that you are about to delete. Rebuildable files may be candidates for removal; unique training data and evaluation records usually are not. Test rollback by restoring the previous alias mapping and repeating a representative request, rather than assuming that keeping a filename is sufficient.
- Four tools, four ideas of where models live: a bare path for llama.cpp, a content-addressed
store for Ollama, a
publisher/model/file.gguftree for LM Studio, and the shared Hugging Face cache for everything Python. - One library at
~/models, with the publisher namespace preserved, feeds all of them: a path for llama.cpp, a symbolic link for LM Studio, a Modelfile import for Ollama. - The Hugging Face cache is blobs plus symbolic links, not a folder of models. Delete from it
with
hf cache rmandhf cache prune, never by hand, and never back it up: it carries aCACHEDIR.TAGasking you not to. - On Windows the cache stores duplicates instead of links unless Developer Mode is on, which explains a great deal of unexplained disk usage on Track N.
- Record the checksum, the provenance and the reason beside every file.
hf cache verifyre-checks a whole directory against the Hub. - Prune by a rule decided in advance: keep what you benchmarked, keep what is tiny, keep what you used this month, delete the rest largest first.
Check your understanding
Sources for this lesson
6 verified · checked 2026-09-08
- 01Hugging Face Hub documentation — Understand caching§ File-based caching; refs, blobs, snapshots, trees; limitations; CACHEDIR.TAG; inspect, verify and clean your cachehuggingface.co/docs/huggingface_hub/guides/manage-cache2026-09-08
- 02Ollama documentation — FAQ§ Where are models stored; how do I set them to a different locationraw.githubusercontent.com/ollama/ollama/main/docs/faq.mdx2026-09-08
- 03Ollama documentation — Modelfile reference§ FROM — build from a GGUF fileraw.githubusercontent.com/ollama/ollama/main/docs/modelfile.mdx2026-09-08
- 04LM Studio Docs — Import Models§ Expected directory structurelmstudio.ai/docs/app/advanced/import-model2026-09-08
- 05LM Studio Docs — lms CLIlmstudio.ai/docs/cli2026-09-08
- 06Hugging Face Hub documentation — Command Line Interface (hf)§ hf download; hf cachehuggingface.co/docs/huggingface_hub/guides/cli2026-09-08
Every technical claim on this page was checked against the official documentation of the tool, vendor or model publisher on the date shown, at the version pinned for the course. Where the course disagrees with folklore, the source is how you can tell which one to trust.