{"id":46310090,"url":"https://github.com/depasqualeorg/swift-hf-api","last_synced_at":"2026-06-11T23:00:47.440Z","repository":{"id":341909788,"uuid":"1171746798","full_name":"DePasqualeOrg/swift-hf-api","owner":"DePasqualeOrg","description":"Swift client for Hugging Face's REST APIs","archived":false,"fork":false,"pushed_at":"2026-06-06T17:16:08.000Z","size":723,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-06T17:21:10.449Z","etag":null,"topics":["ai","api","deep-learning","hugging-face","machine-learning","rest-api","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DePasqualeOrg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-03T15:08:14.000Z","updated_at":"2026-05-05T21:44:54.000Z","dependencies_parsed_at":"2026-03-09T00:01:00.866Z","dependency_job_id":null,"html_url":"https://github.com/DePasqualeOrg/swift-hf-api","commit_stats":null,"previous_names":["depasqualeorg/swift-hf-api"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/DePasqualeOrg/swift-hf-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DePasqualeOrg%2Fswift-hf-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DePasqualeOrg%2Fswift-hf-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DePasqualeOrg%2Fswift-hf-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DePasqualeOrg%2Fswift-hf-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DePasqualeOrg","download_url":"https://codeload.github.com/DePasqualeOrg/swift-hf-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DePasqualeOrg%2Fswift-hf-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34221150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","api","deep-learning","hugging-face","machine-learning","rest-api","swift"],"created_at":"2026-03-04T13:03:22.347Z","updated_at":"2026-06-11T23:00:47.434Z","avatar_url":"https://github.com/DePasqualeOrg.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swift HF API\n\nA Swift client for the Hugging Face Hub, backed by the Rust [`hf-hub`](https://github.com/huggingface/hf-hub) crate. This package is intentionally limited the models and datasets used for local inference and training.\n\nSwift HF API is independently maintained and is not associated with Hugging Face.\n\n## Status\n\nThe library is pre-1.0. Expect breaking changes.\n\n## What's covered\n\n- **Repositories**: `model(owner:name:)` and `dataset(owner:name:)` handles. Each handle exposes the universal protocol methods (`info`, `exists`, `listTree`, `pathsInfo`, `fileMetadata`, `listCommits`, `listRefs`, `commitDiff`, …).\n- **Listing**: `listModels` and `listDatasets` with `hf-hub`'s filter / sort / search builders.\n- **Downloads**: `downloadFile`, `downloadFileToBytes`, `downloadFileBytesStream`, `snapshotDownload`. Progress events stream through `AsyncThrowingStream`; cancellation flows from the consumer back to the Rust side via the `OperationHandle` token.\n- **Uploads**: `uploadFile`, `uploadFileBytes`, `uploadFolder`, `createCommit`, `deleteFile`, `deleteFolder`. Streaming variants emit `UploadEvent`s and resolve to a `CommitInfo`.\n- **Repo lifecycle**: `createRepository`, `deleteRepository`, `moveRepository`, `updateSettings`.\n- **Branches and tags**: `createBranch`, `deleteBranch`, `createTag`, `deleteTag`.\n- **Cache scan**: `scanCache()` returns a `CacheInfo` that mirrors the shape `huggingface-cli scan-cache` reports.\n- **Auth**: `currentUser()` for verifying the current token; OAuth refresh is glued into `HFClient` via `HFAPIHubAuth` so the inner client rotates tokens transparently.\n\n## Modules\n\n- **`HFAPI`**: the main client. `HFClient`, `ModelRepository`, `DatasetRepository`, `CacheInfo`, error types. Apple platforms also expose `NetworkMonitor` for explicit offline-mode checks; Linux omits it (no `NWPathMonitor` equivalent – provide your own detection or pass `.use` / `.bypass` to `NetworkAccess`).\n- **`HFAPIOAuth`**: Apple-platform OAuth flow. `OAuthManager`, `OAuthClient`, keychain token storage. Linux compiles to an empty target.\n- **`HFAPIHubAuth`**: the OAuth↔HFClient bridge. `OAuthClientFactory.client(authManager:)` returns a fully wired `HFClient` whose token rotates with the manager.\n- **`HFAPIShared`**: shared types. `TokenProvider` (used by `HFAPI` and `HFAPIOAuth`).\n\n## Usage\n\n### Basic client\n\n```swift\nimport HFAPI\n\n// Reads token + endpoint from environment (HF_TOKEN, HF_ENDPOINT, etc.).\nlet client = try HFClient()\n\nlet info = try await client.model(owner: \"openai-community\", name: \"gpt2\").info()\nprint(info.id, info.tags ?? [])\n```\n\nConfigure explicitly with named parameters:\n\n```swift\nlet client = try HFClient(\n    endpoint: \"https://huggingface.co\",\n    auth: .token(\"hf_…\"),\n    userAgent: \"MyApp/1.0\"\n)\n```\n\n### Snapshot download\n\n```swift\nlet url = try await client\n    .model(owner: \"openai-community\", name: \"gpt2\")\n    .snapshotDownload(allowPatterns: [\"*.json\", \"*.txt\"])\nprint(\"Snapshot at:\", url.path)\n```\n\n### Streaming progress\n\n`downloadFileStream` returns a ``DownloadStream`` – an `AsyncSequence` of ``DownloadEvent``. Iterate for progress, then `await stream.value` for the on-disk URL. Call `stream.cancel()` (or break out of the loop) to abort.\n\n```swift\nlet stream = client\n    .model(owner: \"owner\", name: \"name\")\n    .downloadFileStream(\"model.safetensors\")\n\nfor try await event in stream {\n    if case let .aggregateProgress(bytesCompleted, totalBytes, _) = event {\n        print(\"\\(bytesCompleted) / \\(totalBytes)\")\n    }\n}\nlet url = try await stream.value\n```\n\n### Authentication\n\n`HFClient` accepts a token in three shapes; pick whichever fits the use case.\n\n#### Static token\n\nFor a single fixed token (CLI scripts, environment-driven flows):\n\n```swift\nlet client = try HFClient(auth: .token(\"hf_…\"))\n```\n\nWhen `auth` is omitted (or set to `.env`), `HFClient` resolves a token from the environment at construction time, checking in priority order: `HF_TOKEN`, `HUGGING_FACE_HUB_TOKEN`, the file at `HF_TOKEN_PATH`, `$HF_HOME/token`, `~/.cache/huggingface/token`, then `~/.huggingface/token`. The order matches the HF CLI and Python `huggingface_hub` library. Pass `auth: .unauthenticated` to skip env detection entirely.\n\n#### OAuth via `OAuthClientFactory` (recommended for OAuth flows)\n\n`OAuthManager` is `@MainActor`-isolated, so construct it from a main-actor context (e.g., a SwiftUI `App` initializer or a `@MainActor` setup function):\n\n```swift\nimport HFAPI\nimport HFAPIOAuth\nimport HFAPIHubAuth\n\n@MainActor\nfunc makeAuthenticatedClient() async throws -\u003e HFClient {\n    let manager = try OAuthManager(\n        clientID: \"your-client-id\",\n        redirectURL: URL(string: \"myapp://oauth\")!,\n        scope: .basic,\n        keychainService: \"com.example.app\",\n        keychainAccount: \"huggingface\"\n    )\n    return try OAuthClientFactory.client(authManager: manager)\n}\n\n// Hub calls transparently consult the manager for a fresh token.\n// When the OAuth token rotates, the inner Rust client is rebuilt.\nlet client = try await makeAuthenticatedClient()\nlet user = try await client.currentUser()\n```\n\nThe bridge propagates OAuth errors precisely. When `validToken()` throws (refresh-token expired, keychain inaccessible), the next Hub call surfaces `HFError.tokenProviderFailed(message:)` carrying the original `OAuthError`'s `localizedDescription`. Pattern-match on `tokenProviderFailed` to drive a re-sign-in prompt.\n\n#### Composable provider (`TokenProvider`)\n\nPass a `TokenProvider` from `HFAPIShared` for multi-source chains. The cases are `.fixed(token:)`, `.environment`, `.oauth(manager:)`, `.composite([…])`, and `.custom { … }`. `.environment` uses the same six-source lookup list as `Auth.env`.\n\n```swift\nimport HFAPIShared\n\nlet client = try HFClient(auth: .provider(.composite([\n    .oauth(manager: authManager),\n    .environment,\n    .fixed(token: \"hf_fallback_token\"),\n])))\n```\n\nNote: `TokenProvider.composite([…])` short-circuits when a sub-provider throws – it does **not** advance to the next on error, only on `nil`. To skip an OAuth provider that's failing rather than abort the chain, wrap it in a `.custom` that catches: `.custom { try? await manager.validToken() }`.\n\n#### Custom closure\n\nFor one-off custom token logic where a `TokenProvider` would be overkill:\n\n```swift\nlet client = try HFClient(auth: .provider {\n    try await myCustomTokenStore.fetchCurrent()\n})\n```\n\nThe closure is `@Sendable () async throws -\u003e String?`. Returning `nil` runs the request unauthenticated; throwing aborts the Hub call with `HFError.tokenProviderFailed(message:)`. Wrap with `try?` for best-effort semantics where transient failures fall through to unauthenticated requests.\n\nThe four `Auth` cases (`.env`, `.unauthenticated`, `.token(_:)`, `.provider(_:)`) are mutually exclusive by construction – the type system prevents combining them, so there is no runtime \"mutual exclusion\" failure to handle.\n\n### Offline mode\n\nDownload calls take a `networkAccess: NetworkAccess` parameter (default `.default`) that controls whether the network is consulted on a cache miss:\n\n- `.use` – always hit the network on cache miss.\n- `.bypass` – cache-only; throws `localEntryNotFound` if the file isn't cached.\n- `.useIfAvailable` *(Apple-only)* – consults `NetworkMonitor.shared.state.shouldUseOfflineMode()` and falls back to `.bypass` when offline, `.use` otherwise.\n\n`.default` resolves to `.useIfAvailable` on Apple platforms and `.use` on Linux (no `NWPathMonitor` equivalent).\n\n```swift\n// Auto-detect (Apple default): online → fetch; offline → cache.\nlet url = try await client\n    .model(owner: \"openai-community\", name: \"gpt2\")\n    .snapshotDownload()\n\n// Force cache-only resolution.\nlet url = try await client\n    .model(owner: \"openai-community\", name: \"gpt2\")\n    .snapshotDownload(networkAccess: .bypass)\n\n// Force network resolution (skip the offline check).\nlet url = try await client\n    .model(owner: \"openai-community\", name: \"gpt2\")\n    .snapshotDownload(networkAccess: .use)\n```\n\n`HFAPI.NetworkMonitor` wraps `NWPathMonitor` and is Apple-only – the symbol does not exist in the Linux build. Linux consumers who need offline-aware behavior should pass `.use` or `.bypass` explicitly based on their own detection. Set `CI_DISABLE_NETWORK_MONITOR=1` to disable the offline-mode signal in CI environments where the path monitor can produce false negatives.\n\n## Testing\n\n- `swift test` runs read-only tests against the live Hub; the mutation tests skip cleanly without an opt-in env var.\n- `HFAPI_RUN_HUB_MUTATION_TESTS=1 swift test` opts into the mutation tests (create / upload / delete / branch / tag / commit). Each test creates an isolated `swift-hf-api-test-…-{uuid}` repo under the authenticated user's namespace and tears it down afterward.\n- The Rust crate is built and shipped as a SwiftPM artifactbundle. Set `HFAPI_RUST_LOCAL_ARTIFACTBUNDLE_PATH=rust/target/artifactbundle/HFAPIRust.artifactbundle` to point the package at a locally built bundle (see `scripts/rust/` for the assembly pipeline).\n\n## Platform support\n\nmacOS 14+, iOS 17+, Linux (excluding OAuth and HubAuth modules)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepasqualeorg%2Fswift-hf-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdepasqualeorg%2Fswift-hf-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepasqualeorg%2Fswift-hf-api/lists"}