In the rapidly evolving landscape of machine learning development, managing large AI models remains a significant challenge. Today, Hugging Face has announced a groundbreaking solution: swift-huggingface, a comprehensive Swift package designed to provide a complete client for the Hugging Face Hub. This release comes as a response to persistent community feedback and represents a significant leap forward in integrating Swift applications with the broader AI ecosystem.

The Pain Points of Model Management

When swift-transformers 1.0 was released earlier this year, the response from the Swift AI development community was clear and consistent. The existing implementation struggled with fundamental issues that hindered productivity:

"Downloads were slow and unreliable. Large model files (often several gigabytes) would fail partway through with no way to resume."

The inability to resume interrupted downloads of multi-gigabyte models forced developers into workarounds, such as manually downloading models and bundling them with their applications—a practice that defeats the purpose of dynamic model loading.

Another critical issue was the lack of interoperability with Python, the dominant language in machine learning:

"No shared cache with the Python ecosystem. Swift apps downloaded to a different location with a different structure. If you'd already downloaded a model using the Python CLI, you'd download it again for your Swift app."

This duplication wasted storage space and bandwidth, creating friction for teams working across multiple programming environments.

Authentication complexity presented yet another barrier:

"Authentication is confusing. Where should tokens come from? Environment variables? Files? Keychain? The answer is, 'It depends', and the existing implementation didn't make the options clear."

A Ground-Up Solution

swift-huggingface addresses these challenges through a complete rewrite focused on reliability and developer experience. The new package delivers:

  • Complete Hub API coverage — models, datasets, spaces, collections, discussions, and more
  • Robust file operations — progress tracking, resume support, and proper error handling
  • Python-compatible cache — share downloaded models between Swift and Python clients
  • Flexible authentication — a TokenProvider pattern that makes credential sources explicit
  • OAuth support — first-class support for user-facing apps that need to authenticate users
  • Xet storage backend support (Coming soon!) — chunk-based deduplication for significantly faster downloads

Flexible Authentication with TokenProvider

One of the most significant improvements is the new authentication system. The TokenProvider pattern makes credential sources explicit and intuitive:

import HuggingFace

// For development: auto-detect from environment and standard locations
// Checks HF_TOKEN, HUGGING_FACE_HUB_TOKEN, ~/.cache/huggingface/token, etc.
let client = HubClient.default

// For CI/CD: explicit token
let client = HubClient(tokenProvider: .static("hf_xxx"))

// For production apps: read from Keychain
let client = HubClient(tokenProvider: .keychain(service: "com.myapp", account: "hf_token"))

The auto-detection mechanism follows the same conventions as the Python huggingface_hub library, creating seamless interoperability:

  • HF_TOKEN environment variable
  • HUGGING_FACE_HUB_TOKEN environment variable
  • HF_TOKEN_PATH environment variable (path to token file)
  • $HF_HOME/token file
  • ~/.cache/huggingface/token (standard HF CLI location)
  • ~/.huggingface/token (fallback location)

This means if developers have already authenticated using the Python CLI, swift-huggingface will automatically detect and use those credentials.

OAuth for User-Facing Applications

For applications where users need to sign in with their Hugging Face accounts, swift-huggingface includes a complete OAuth 2.0 implementation:

import HuggingFace

// Create authentication manager
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"
)

// Sign in user (presents system browser)
try await authManager.signIn()

// Use with Hub client
let client = HubClient(tokenProvider: .oauth(manager: authManager))

// Tokens are automatically refreshed when needed
let userInfo = try await client.whoami()
print("Signed in as: \(userInfo.name)")

The OAuth manager handles token storage in the Keychain, automatic refresh, and secure sign-out, eliminating the need for manual token management in user-facing applications.

Reliable Downloads for Large Models

Downloading large models is now straightforward with proper progress tracking and resume support:

// Download with progress tracking
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
)

If a download is interrupted, developers can resume it seamlessly:

// Resume from where you left off
let fileURL = try await client.resumeDownloadFile(
    resumeData: savedResumeData,
    to: destinationURL,
    progress: progress
)

For downloading entire model repositories, the downloadSnapshot function handles everything efficiently:

let modelDir = try await client.downloadSnapshot(
    of: "mlx-community/Llama-3.2-1B-Instruct-4bit",
    to: cacheDirectory,
    matching: ["*.safetensors", "*.json"],  // Only download what you need
    progressHandler: { progress in
        print("Downloaded \(progress.completedUnitCount) of \(progress.totalUnitCount) files")
    }
)

The snapshot function tracks metadata for each file, ensuring subsequent calls only download files that have changed.

Shared Cache with Python Ecosystem

swift-huggingface implements a Python-compatible cache structure that allows seamless sharing between Swift and Python clients:

~/.cache/huggingface/hub/
├── models--deepseek-ai--DeepSeek-V3.2/
│   ├── blobs/
│   │   └── <etag>           # actual file content
│   ├── refs/
│   │   └── main             # contains commit hash
│   └── snapshots/
│       └── <commit_hash>/
│           └── config.json  # symlink → ../../blobs/<etag>

This approach offers several advantages:

  • Download once, use everywhere: If a model has already been downloaded with the Python CLI or library, swift-huggingface will find it automatically.
  • Content-addressed storage: Files are stored by their ETag in the blobs/ directory. If two revisions share the same file, it's only stored once.
  • Symlinks for efficiency: Snapshot directories contain symlinks to blobs, minimizing disk usage while maintaining a clean file structure.

The cache location follows the same environment variable conventions as Python, and swift-huggingface uses file locking to prevent race conditions when multiple processes access the same cache.

Before and After: A Tale of Two Implementations

The difference between the old HubApi and swift-huggingface is stark. Here's a comparison of downloading a model snapshot:

Before (HubApi in swift-transformers):

// Before: HubApi in swift-transformers
let hub = HubApi()
let repo = Hub.Repo(id: "mlx-community/Llama-3.2-1B-Instruct-4bit")

// No progress tracking, no resume, errors swallowed
let modelDir = try await hub.snapshot(
    from: repo,
    matching: ["*.safetensors", "*.json"]
) { progress in
    // Progress object exists but wasn't always accurate
    print(progress.fractionCompleted)
}

After (swift-huggingface):

// After: swift-huggingface
let client = HubClient.default

let modelDir = try await client.downloadSnapshot(
    of: "mlx-community/Llama-3.2-1B-Instruct-4bit",
    to: cacheDirectory,
    matching: ["*.safetensors", "*.json"],
    progressHandler: { progress in
        // Accurate progress per file
        print("\(progress.completedUnitCount)/\(progress.totalUnitCount) files")
    }
)

While the API surface appears similar, the implementation is fundamentally different—built on URLSession download tasks with proper delegate handling, resume data support, and metadata tracking.

Beyond Downloads: Complete Hub API

swift-huggingface offers more than just robust download capabilities—it provides a complete Hub client for interacting with all aspects of the Hugging Face ecosystem:

// List trending models
let models = try await client.listModels(
    filter: "library:mlx",
    sort: "trending",
    limit: 10
)

// Get model details
let model = try await client.getModel("mlx-community/Llama-3.2-1B-Instruct-4bit")
print("Downloads: \(model.downloads ?? 0)")
print("Likes: \(model.likes ?? 0)")

// Work with collections
let collections = try await client.listCollections(owner: "huggingface", sort: "trending")

// Manage discussions
let discussions = try await client.listDiscussions(kind: .model, "username/my-model")

The package also includes comprehensive support for Hugging Face Inference Providers, giving Swift applications instant access to hundreds of machine learning models:

import HuggingFace

// Create a client (uses auto-detected credentials from environment)
let client = InferenceClient.default

// Generate images from a text prompt
let response = try await client.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
)

// Save the generated image
try response.image.write(to: URL(fileURLWithPath: "generated.png"))

The Road Forward

The swift-huggingface team is actively working on two key fronts:

  1. Integration with swift-transformers: A pull request is in progress to replace HubApi with swift-huggingface, which will bring reliable downloads to everyone using swift-transformers, mlx-swift-lm, and the broader Swift ML ecosystem.

  2. Faster downloads with Xet: Support for the Xet storage backend is being added, which will enable chunk-based deduplication and significantly faster downloads for large models.

swift-huggingface represents a significant step forward in making Swift a first-class citizen in the machine learning ecosystem. By solving fundamental problems around model management, authentication, and interoperability, it opens new possibilities for Swift developers building AI-powered applications.

For developers looking to enhance their Swift ML projects, swift-huggingface offers a compelling solution that bridges the gap between Swift and Python ecosystems while providing the reliability and performance needed for production applications.

Article illustration 1