Model or dataset
huggingface/hf-mount avatar
huggingface/hf-mount

hf-mount: mounting Hugging Face repos and buckets as a local filesystem

Mount Hugging Face Buckets and repos as local filesystems. No download, no copy, no waiting.

817 stars73 forksRustApache-2.0

At a glance

What is it?
hf-mount is a Rust command line tool that exposes Hugging Face Buckets and Hub repos through FUSE or NFS, fetching files lazily on first read so a training run touches only the bytes it needs. It is deliberately not a general network filesystem, and the README is explicit about the workloads it refuses.
Who is it for?
hf-mount suits a team that streams large model or dataset repos from the Hub in read-heavy jobs where disk space is the binding constraint, and it is the wrong tool for anything that needs multi-writer semantics, cross-node locking or strong consistency, since the README states files can be stale for up to 10 seconds and the last writer wins.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A directory that fetches on first read

The problem hf-mount addresses is disk space and start-up time. Loading a model from the Hub normally means downloading it, and a multi-gigabyte checkpoint is a multi-gigabyte copy on the machine and a wait before training starts. hf-mount offers a different shape: a directory that behaves like a local path, where the bytes arrive the first time something reads them.

The project's own summary of the idea is blunt about the trade: no download, no copy, no waiting. A file is fetched lazily on first read, so only the bytes your code actually touches ever hit the network. The usage example is the shortest possible illustration, since the path is handed to an ordinary library call and nothing else changes:

python
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("/tmp/gpt-oss")  # reads on demand, no download step

Two kinds of source are supported. Repos, meaning any model or dataset repository on the Hub, are mounted read-only. Buckets, the S3-like object storage on the Hub designed for large-scale mutable data such as training checkpoints, logs and artifacts without git version control, are mounted read-write.

The audience is machine learning engineers working on large artifacts, and the README frames it in a specific way: agents do not require complex APIs or SDKs, they thrive on the filesystem, with ls, cat, find, grep and composable UNIX pipelines. A mount is a way of giving an agent a directory to explore.

The code is Rust, the licence is Apache-2.0, and the project moves quickly, with v0.12.0, v0.13.0 and v0.13.1 published in September 2026 and the last push on 2026-10-18.

Two backends, and the choice is mostly about privileges

The mechanism underneath is a filesystem, and there are two implementations of it.

NFS is the recommended backend and the one that works everywhere. It needs no root and no kernel extension, which in practice means it runs in a container, on a shared machine, or under a restricted account without ceremony. FUSE gives tighter kernel integration, with page cache invalidation and per-file metadata revalidation, and it requires root on Linux or macFUSE on macOS.

That difference in privileges is what decides the choice for most people, and it also decides which binary you can install. On Linux, the FUSE path needs fuse3, installed on Debian-family systems with sudo apt-get install -y fuse3, where the pre-built binaries only need the runtime and building from source additionally needs libfuse3-dev. On macOS it needs macFUSE, which is installed with brew install macfuse and requires a reboot on first install.

The build from source is feature-gated, so you compile only the backend you want. Rust 1.89 or newer is required, and the commands are:

bash
# NFS only (no system deps, works everywhere)
cargo build --release --features nfs

# FUSE (requires macFUSE on macOS, fuse3 on Linux)
cargo build --release --features fuse

# All backends
cargo build --release --features fuse,nfs

The result is three binaries, hf-mount, hf-mount-nfs and hf-mount-fuse, and the Cargo manifest makes the split explicit with the fuser and nfsserve crates as optional dependencies behind the fuse and nfs features. The default feature set is empty, which is why the Docker build has to name its features explicitly.

Mounting a repo, and the options that matter

The start command takes a kind, a source and a mount point, and the options are where the real control lives:

bash
# Public model (no token needed)
hf-mount start repo openai/gpt-oss-20b /tmp/model

# Private model
hf-mount start --hf-token $HF_TOKEN repo myorg/my-private-model /tmp/model

# Dataset
hf-mount start repo datasets/open-index/hacker-news /tmp/hn

# Specific revision
hf-mount start repo openai-community/gpt2 /tmp/gpt2 --revision v1.0

# Subfolder only
hf-mount start repo openai-community/gpt2/onnx /tmp/onnx

A public repo needs no token. A private one needs a token, and the command picks up HF_TOKEN from the environment or accepts it explicitly through --hf-token, which is the safer choice on a shared machine where an environment variable may end up in a process listing or a log.

Two of those lines are worth pausing on. The --revision flag pins the mount to a specific version of the repo, which is the difference between a reproducible run and a run that changes under you when upstream commits. And the subfolder form, mounting openai-community/gpt2/onnx, means you expose one directory of a larger repo rather than the whole tree, which keeps the listing readable and the lazy fetch narrow.

Mounts are managed with a status command and a stop command that takes the mount point:

bash
hf-mount status                  # list running mounts
hf-mount stop /tmp/data          # stop and unmount

Logs go to ~/.hf-mount/logs/ and PID files to ~/.hf-mount/pids/, which is where you look when a mount does not appear.

Buckets are the read-write half

Repos are immutable in this model, so the writable path is the bucket.

bash
hf-mount start --hf-token $HF_TOKEN bucket myuser/my-bucket /tmp/data

# Read-only
hf-mount start --hf-token $HF_TOKEN --read-only bucket myuser/my-bucket /tmp/data

# Subfolder only
hf-mount start --hf-token $HF_TOKEN bucket myuser/my-bucket/checkpoints /tmp/ckpts

The bucket concept is the Hub's S3-like object storage, built for large-scale mutable data, meaning training checkpoints, logs and artifacts, without git version control. That distinction is the one to hold on to. A repo mount gives you a versioned snapshot of somebody else's data, and a bucket mount gives you a working directory that happens to be backed by the Hub.

The read-only flag is worth using by default even on a bucket. The mount is exposed to whatever is running on the machine, and a mount that can only be read removes an entire class of accident, particularly when a training job decides to write a checkpoint into the wrong path.

The same options apply: a token, and a subfolder. Mounting only the checkpoints directory of a bucket is a small thing that makes the mount far more legible in a listing, and it keeps the lazy fetch away from the parts of the bucket nobody is reading.

The consistency model is where the limits live

The README has a Not for list, and it is the most useful section in the documentation for anyone deciding whether to adopt this.

It is not a general-purpose networked filesystem. There is no multi-writer support and no cross-node file locking. It is not for latency-sensitive random I/O, because the first reads require network round trips, which means a random access pattern pays a network latency per first touch. It is not for workloads that need strong consistency, because files can be stale for up to ten seconds. It is not for heavy concurrent writes from multiple mounts, because the last writer wins and there is no conflict detection. And it is not for editing files with text editors in their default streaming mode, where the tool advises using --advanced-writes instead.

Advisory file locks are the nuance. flock and fcntl POSIX record locks are supported locally on a single mount on both backends, which the documentation says is enough for Python filelock, huggingface_hub, datasets and similar cache-coordination use cases within one machine. They are not coordinated across multiple clients. So a shared training cache on one node works, and two nodes writing the same cache do not coordinate.

The ten second staleness figure and the last-writer-wins rule together define the tool as a read-oriented cache with a write path bolted on for checkpoints, not as storage you would design a distributed system around.

Installing: Homebrew ships the NFS backend only

Installation is where the backend split shows up in practice.

On macOS and Linux, Homebrew is the easy route:

bash
brew install hf-mount

On macOS that installs the NFS backend only, giving you hf-mount and hf-mount-nfs. The FUSE backend has to be downloaded manually or built from source on macOS, and the reason given is that macFUSE is closed-source and not distributable through homebrew-core. That is a licensing constraint rather than a technical one, and it means the two backends are not always available from the same channel.

Pre-built binaries are also published on GitHub Releases for Linux x86_64, Linux aarch64 and macOS Apple Silicon, with separate daemon, NFS and FUSE builds for each platform.

For scripts, containers and debugging, the backend binaries can be run directly in the foreground, which is the behaviour to prefer in a container image where there is no user session to daemonise into:

bash
hf-mount-nfs repo gpt2 /tmp/gpt2
hf-mount-fuse --hf-token $HF_TOKEN bucket myuser/my-bucket /mnt/data

On macOS there is also a launchd LaunchAgent recipe in the documentation for starting the NFS backend automatically at login, with the plist pointing at the hf-mount-nfs binary and RunAtLoad and KeepAlive set.

The container story is in the repository as well. The Dockerfile is a multi-stage build using cargo-chef, so the dependency layer is cached separately from the source layer, and it ends on debian:bookworm-slim with libfuse3-3 and ca-certificates installed, building the FUSE daemon and its sidecar binary.

Where a plain download would serve you better

The alternative to mounting is the obvious one: download the repo with the usual tooling and read it from local disk. The difference in approach is the shape of the cost. A download spends disk and time up front, and then every read is local. A mount spends a network round trip on the first read of each file and then caches, so the cost follows the access pattern rather than preceding it.

For a read-heavy training or evaluation job that touches most of the weights anyway, the download is simpler and the mount buys little. For a job that reads one shard out of a large dataset, or that has no disk budget at all, the mount is the one that fits. A third option sits between them, mounting a general object storage client such as an S3-style FUSE tool, which gives similar lazy behaviour but without the Hub-specific features: no --revision pinning, no repo and bucket distinction, and the bucket semantics come from the object store rather than from the Hub.

The other thing to check before committing is the dependency pinning. The Cargo manifest pulls the xet client, core, data and runtime crates from the huggingface/xet-core repository at a fixed revision rather than a branch, and the comment in the manifest explains why: so that releases are reproducible. That is the right choice for a released binary, and it does mean the xet side of the stack is updated deliberately rather than continuously.

What the project does not do is provide a caching layer you control or a local mirror. The cache belongs to the filesystem and the operating system.

Editorial conclusion

hf-mount suits a team that streams large model or dataset repos from the Hub in read-heavy jobs where disk space is the binding constraint, and it is the wrong tool for anything that needs multi-writer semantics, cross-node locking or strong consistency, since the README states files can be stale for up to 10 seconds and the last writer wins. Verify first which backend you can actually run, because the Homebrew formula on macOS ships the NFS build only and the FUSE build needs macFUSE, and confirm your workload tolerates first-read network round trips rather than assuming the mount behaves like local disk.

Frequently asked questions

How do I mount a Hugging Face repo as a local directory with hf-mount?

Run hf-mount start repo openai/gpt-oss-20b /tmp/model for a public repo, or hf-mount start --hf-token $HF_TOKEN repo myorg/my-private-model /tmp/model for a private one. The token is picked up from HF_TOKEN in the environment or passed with --hf-token, and the mount is read-only.

What is the difference between the NFS and FUSE backends in hf-mount?

NFS is the recommended backend, works everywhere, and needs no root and no kernel extension. FUSE offers tighter kernel integration with page cache invalidation and per-file metadata revalidation, but requires root on Linux or macFUSE on macOS.

Can I write to a mounted Hugging Face Bucket?

Yes. Buckets are mounted read-write with hf-mount start --hf-token $HF_TOKEN bucket myuser/my-bucket /tmp/data, while repos are read-only. You can force a read-only mount with --read-only, and you can mount a subfolder of a bucket.

Is hf-mount safe for concurrent writers?

Not across machines. The README lists it as not suitable for general-purpose networked filesystems, with no multi-writer support and no cross-node file locking, and warns that files can be stale for up to 10 seconds and that the last writer wins. Advisory locks work locally on a single mount on both backends.

How do I install hf-mount on macOS?

With brew install hf-mount, which on macOS installs the NFS backend only, since macFUSE is closed-source and cannot be distributed through homebrew-core. For the FUSE backend, download the binary manually or build from source with cargo build --release --features fuse, and install macFUSE first, which requires a reboot on first install.

Official sources

  1. huggingface/hf-mount on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/huggingface-hf-mount.svg)](https://hysenlabs.com/projects/huggingface-hf-mount)

Was this useful?