Hugging Face announces swift-huggingface, a Swift package that provides a full client for the Hub. What does that mean for you as an iOS, macOS or Swift app developer? Reliable downloads, Python-compatible cache, straightforward authentication and an API designed for real production experience.
What swift-huggingface brings
swift-huggingface is a rewrite focused on reliability and developer experience. It’s not just a thin wrapper: it covers the entire Hub API (models, datasets, spaces, collections, discussions), robust file operations and compatibility with the cache layout used by Python.
Why does that matter? Because now your Swift app can use models without making the user manually download gigabytes or deal with downloads that fail with no way to resume.
Key technical features:
Full coverage of the Hub API: listing, details, collections and discussions.
Robust downloads: progress tracking, resume support and better error handling.
Python-compatible cache: share ~/.cache/huggingface/hub between Swift and Python clients.
Flexible authentication: a clear, consistent TokenProvider pattern.
OAuth 2.0 ready for apps with user login.
Xet support (coming soon): chunk deduplication for much faster downloads.
Authentication: TokenProvider and OAuth explained
One of the most common headaches is: where do tokens come from? swift-huggingface adopts the TokenProvider pattern so token handling is explicit and controllable.
Simple examples:
import HuggingFace
// Auto-detection for development
let client = HubClient.default
// Explicit token for CI
let clientCI = HubClient(tokenProvider: .static("hf_xxx"))
// Read token from Keychain for production
let clientProd = HubClient(tokenProvider: .keychain(service: "com.myapp", account: "hf_token"))
Auto-detection follows the same conventions as huggingface_hub in Python: HF_TOKEN, HUGGING_FACE_HUB_TOKEN, standard file paths and CLI locations. If you already ran hf auth login, the Swift client will detect it.
Need user account login? There’s a full OAuth manager:
import HuggingFace
let authManager = try HuggingFaceAuthenticationManager(
clientID: "your_client_id",
redirectURL: URL(string: "yourapp://oauth/callback")!,
scope: [.openid, .profile, .email],
keychainService: "com.yourapp.huggingface",
keychainAccount: "user_token"
)
try await authManager.signIn()
let client = HubClient(tokenProvider: .oauth(manager: authManager))
let userInfo = try await client.whoami()
print("Signed in as: \(userInfo.name)")
The manager handles Keychain storage, automatic refresh and secure sign-out. No more manual token juggling.
Downloads, resume and Python-compatible cache
Large downloads used to be fragile: they would fail halfway with no resume. swift-huggingface uses URLSession with download tasks, delegate support, resumeData handling and fine-grained metadata tracking.
Example of a download with progress:
let progress = Progress(totalUnitCount: 0)
Task {
for await _ in progress.publisher(for: \.fractionCompleted).values {
print("Download: \(Int(progress.fractionCompleted * 100))%")
}
}
let fileURL = try await client.downloadFile(
at: "model.safetensors",
from: "microsoft/phi-2",
to: destinationURL,
progress: progress
)
And if it’s interrupted:
let fileURL = try await client.resumeDownloadFile(
resumeData: savedResumeData,
to: destinationURL,
progress: progress
)
For entire repositories there’s downloadSnapshot, which compares metadata and only downloads what changed:
let modelDir = try await client.downloadSnapshot(
of: "mlx-community/Llama-3.2-1B-Instruct-4bit",
to: cacheDirectory,
matching: ["*.safetensors", "*.json"],
progressHandler: { progress in
print("Downloaded \(progress.completedUnitCount) of \(progress.totalUnitCount) files")
}
)
The cache layout is compatible with Python. On disk you’ll see something like:
To avoid race conditions when multiple processes touch the same cache, the client uses file locking (flock(2)). That’s crucial in environments where a CI pipeline and a local app might try to write the same file.
Hub API and access to inference providers
The client exposes all the usual operations: list models, get details, manage collections and discussions.
Quick example using the API and the inference client:
let client = HubClient.default
let models = try await client.listModels(filter: "library:mlx", sort: "trending", limit: 10)
let model = try await client.getModel("mlx-community/Llama-3.2-1B-Instruct-4bit")
print("Downloads: \(model.downloads ?? 0)")
let infClient = InferenceClient.default
let response = try await infClient.textToImage(
model: "black-forest-labs/FLUX.1-schnell",
prompt: "A serene Japanese garden with cherry blossoms",
provider: .hfInference,
width: 1024,
height: 1024,
numImages: 1,
guidanceScale: 7.5,
numInferenceSteps: 50,
seed: 42
)
try response.image.write(to: URL(fileURLWithPath: "generated.png"))
Integration and how to get started today
If you already use swift-transformers, there’s a PR in progress to replace HubApi with swift-huggingface, which will bring reliable downloads across the Swift ecosystem.
They’re also working on Xet support, which promises much faster downloads through chunk deduplication. If you deal with very large models, that can change the experience end to end.
Worried about migrating or integrating this into an existing app? The maintainers offer help and are open to feedback. If you’ve had download problems in Swift, your report will help prioritize fixes.
swift-huggingface isn’t just a feature list: it’s a practical improvement in how Swift apps consume models and Hugging Face services. If you work with ML on Apple platforms, it’s worth trying and giving feedback.