How to Move the Hugging Face Cache to Another Drive
Every model you pull with transformers, diffusers, vLLM or the hf CLI lands in ~/.cache/huggingface on your boot drive. One environment variable, HF_HOME, moves it. The hard part is moving the files you already have: the cache stores model files as symlinks into a blobs folder, and two common copy commands break that layout without printing an error.
Bottom Line
- Set
HF_HOMEto a folder on the big drive. Set it before Python importshuggingface_hub. The variable is read at import time. - Or set
HF_HUB_CACHEif you only want model downloads moved. It defaults to$HF_HOME/hub. - Copy with
rsync -aorcp -R. Model files are relative symlinks intoblobs/. Tools that follow or skip symlinks break the cache. - What we tested tonight:
rsync -rdropped every model file with no error exit you would notice. Pythonshutil.copytreedefaults tripled a two-revision cache. - Verify with
hf cache lsandhf cache verify. Then delete the old folder. TRANSFORMERS_CACHEis old advice. The current transformers guide listsHF_HUB_CACHE,HF_HOMEandXDG_CACHE_HOMEonly.
Which Variable Moves What
The huggingface_hub environment variable reference defines one root and several children.
| Variable | Default | What lives there |
|---|---|---|
HF_HOME | ~/.cache/huggingface | Everything below, plus your token |
HF_HUB_CACHE | $HF_HOME/hub | Model, dataset and Space downloads. This is the big one. |
HF_XET_CACHE | $HF_HOME/xet | Xet chunk and shard caches |
HF_ASSETS_CACHE | $HF_HOME/assets | Files that downstream libraries cache |
HF_TOKEN_PATH | $HF_HOME/token | Your access token |
XDG_CACHE_HOME | unset | Used only when HF_HOME is not set |
Pick HF_HOME in most cases. One variable moves every cache, and the Xet cache stops filling the boot drive too. Pick HF_HUB_CACHE when a policy keeps tokens on the system disk.
Deprecated names still work but lose to their replacements: HUGGINGFACE_HUB_CACHE is replaced by HF_HUB_CACHE, and HUGGING_FACE_HUB_TOKEN by HF_TOKEN. The transformers install guide no longer mentions TRANSFORMERS_CACHE at all.
Why a Normal Copy Can Break It
The hub cache is not a plain folder of model files. The cache guide documents this layout:
hub/
└── models--org--name/
├── blobs/ # real file data, named by hash
├── refs/ # branch name -> commit hash
├── snapshots/
│ └── <commit>/
│ └── model.safetensors -> ../../blobs/<hash>
└── trees/ # cached file lists per commit
Each file in snapshots/ is a relative symlink to a blob. Two revisions that share a file point at the same blob, so the data is stored once. A copy tool has three options for each symlink: copy the link, copy the file it points at, or skip it. Only the first option gives you a working cache of the same size.
We Tested Five Copy Methods
We built a fake cache with one 50MB blob and two snapshot folders that link to it. That is the shape you get after a model repo updates and you download it again. Then we copied it five ways on macOS 26.3.
| Method | Size after copy | Symlinks after copy | Result |
|---|---|---|---|
| Original | 48MB | 2 | — |
cp -R src dst | 48MB | 2 | Works |
rsync -a src/ dst/ | 48MB | 2 | Works |
shutil.copytree(src, dst, symlinks=True) | 48MB | 2 | Works |
rsync -r src/ dst/ | 48MB | 0 | Broken. Printed skipping non-regular file per link. Snapshots are empty. |
shutil.copytree(src, dst) | 143MB | 0 | Bloated. Each link became a full copy. |
The rsync -r failure is the dangerous one. The size looks right because the blobs copied. The model still fails to load, because the files the library opens were never created. With HF_HUB_OFFLINE=1 you get a missing-file error. Without it, the library simply downloads the model again into the new cache.
The copytree failure scales with your history. Our test cache had two revisions of one file. A cache that holds three revisions of a 17GB model can grow to 51GB on the new drive. Check any “move my cache” Python snippet for symlinks=True before you run it.
Both failures are general symlink behaviour, not a Hugging Face bug. The cache format just exposes them.
The Move, Step by Step
macOS and Linux
# 1. Copy, keeping symlinks as symlinks
rsync -a ~/.cache/huggingface/ /Volumes/BigDrive/huggingface/
# 2. Point the libraries at the new location (add to ~/.zshrc or ~/.bashrc)
export HF_HOME=/Volumes/BigDrive/huggingface
# 3. Open a new shell, then check the copy
hf cache ls
hf cache verify <org/model>
# 4. Only now remove the old cache
rm -rf ~/.cache/huggingface
Check the link count before you delete anything:
find ~/.cache/huggingface/hub -type l | wc -l
find /Volumes/BigDrive/huggingface/hub -type l | wc -l
The two numbers must match. A zero on the new drive means the copy tool dropped the links.
Services do not read your shell profile. A vLLM or text-generation server started by systemd needs Environment="HF_HOME=/mnt/bigdrive/huggingface" in its unit file. A shell export never reaches it. This is the same trap as moving Ollama models.
Docker containers need the mount and the variable. Mount the new folder into the container and set HF_HOME to the path inside the container.
Windows
- Copy
C:\Users\<you>\.cache\huggingfaceto the new drive, for exampleD:\huggingface. - Open Edit environment variables for your account and create
HF_HOMEwith valueD:\huggingface. - Close every terminal and IDE, then reopen them.
- Run
hf cache lsto check.
Windows often has no symlinks in the cache to begin with. The cache guide says huggingface_hub cannot create them without Developer Mode or admin rights. In that case it stores full files in snapshots/ and copies are simple. If you enabled Developer Mode, copy with a tool that keeps symlinks.
Shared Drives and External Disks
| Situation | Setting | Tradeoff |
|---|---|---|
| NAS shared by Linux and Windows machines | HF_HUB_DISABLE_SYMLINKS=1 | No deduplication. Each revision stores full files. |
| External USB drive | HF_HOME on the drive | If the drive is not mounted, the library downloads again to the path. |
| Offline machine | HF_HUB_OFFLINE=1 | Missing files raise an error instead of a silent re-download. |
The docs recommend HF_HUB_DISABLE_SYMLINKS=1 for the NAS case, because symlinks created on Linux are not always traversable on Windows.
Set HF_HUB_OFFLINE=1 for the first run after a move. A broken copy then fails loudly. Without it, a broken copy costs you a full re-download and you may not notice.
Clean Up Before You Move
Moving garbage is slow. Two commands shrink the cache first:
hf cache ls --revisions --filter "size>1GB" # find the big ones
hf cache prune # delete unreferenced revisions and .incomplete files
hf cache prune removes revisions that no branch or tag points to, plus partial downloads. Old revisions are exactly the files that blow up a dereferencing copy, so pruning first also protects you from the copytree problem.
When It Does Not Work
| Symptom | Cause | Fix |
|---|---|---|
| Model downloads again after the move | Variable not set in that process | Set HF_HOME before import; restart the kernel or service |
hf cache ls shows repos but loading fails offline | Copy tool skipped symlinks (rsync -r) | Re-copy with rsync -a |
| New drive is 2-3x larger than the old cache | Copy tool followed symlinks | Re-copy with rsync -a, or run hf cache prune |
| Works in terminal, not in the server | systemd or Docker never saw the variable | Set it in the unit file or container env |
| Token “lost” after the move | You set HF_HOME, token lives in $HF_HOME/token | Copy the token file too, or run hf auth login again |
Do You Need a Bigger Drive Instead?
Moving the cache only helps if the target drive is large. Our model storage sizing guide has the numbers: 1TB fills fast, 2TB suits a single-GPU box, and 4TB suits a 48GB-VRAM machine. The cache grows fastest when you keep several quantizations of the same model.
See Also
- How Much Storage Do You Need for Local Models? — drive sizing and what to buy
- How to Move Ollama Models to Another Drive — the
OLLAMA_MODELSversion of this job - Using Hugging Face Models With Ollama — how the two download caches relate
- vLLM vs llama.cpp vs SGLang for One User — the runtimes that read this cache
- Quantization in Plain English — why you end up storing Q4, Q6 and Q8 of one model
Sources
- huggingface_hub environment variables —
HF_HOME,HF_HUB_CACHE,HF_XET_CACHE,HF_ASSETS_CACHE,HF_TOKEN_PATH,HF_HUB_DISABLE_SYMLINKS,HF_HUB_OFFLINE, deprecated names; read 2026-09-14 - huggingface_hub cache guide — blobs/refs/snapshots/trees layout, relative symlinks, Windows limitation,
hf cache ls,verify,prune; read 2026-09-14 - transformers installation guide — cache variable priority list; read 2026-09-14
- Copy-method test: run by us on macOS 26.3 (openrsync, Python 3) on 2026-09-14 with a synthetic cache of one 50MB blob and two snapshot symlinks. GNU rsync and GNU cp were not tested.
Need OpenClaw fixed live?
Remote rescue sessions for gateway, auth, tunnel, VPS, and model access problems.
See Rescue Session