← back to Exo
Add HF_ENDPOINT in the app settings (#1783)
6cdfbb7e8b19ab9fee431de4560c88e428cf9f63 · 2026-03-24 17:05:49 +0000 · rltakashige
## Motivation
Some users (primarily in China) are unable to access HuggingFace.co. HF
supports the HF_ENDPOINT env variable, and we also support it, but there
is no way to easily do that from the app currently.
## Test Plan
### Manual Testing
hf-mirror works
empty field works
google.com endpoint fails
Files touched
M app/EXO/EXO/ExoProcessController.swiftM app/EXO/EXO/Views/SettingsView.swiftM justfile
Diff
commit 6cdfbb7e8b19ab9fee431de4560c88e428cf9f63
Author: rltakashige <rl.takashige@gmail.com>
Date: Tue Mar 24 17:05:49 2026 +0000
Add HF_ENDPOINT in the app settings (#1783)
## Motivation
Some users (primarily in China) are unable to access HuggingFace.co. HF
supports the HF_ENDPOINT env variable, and we also support it, but there
is no way to easily do that from the app currently.
## Test Plan
### Manual Testing
hf-mirror works
empty field works
google.com endpoint fails
---
app/EXO/EXO/ExoProcessController.swift | 12 ++++++++++++
app/EXO/EXO/Views/SettingsView.swift | 15 +++++++++++++++
justfile | 4 ++++
3 files changed, 31 insertions(+)
diff --git a/app/EXO/EXO/ExoProcessController.swift b/app/EXO/EXO/ExoProcessController.swift
index a97c0a06..f978d0e0 100644
--- a/app/EXO/EXO/ExoProcessController.swift
+++ b/app/EXO/EXO/ExoProcessController.swift
@@ -4,6 +4,7 @@ import Foundation
private let customNamespaceKey = "EXOCustomNamespace"
private let hfTokenKey = "EXOHFToken"
+private let hfEndpointKey = "EXOHFEndpoint"
private let enableImageModelsKey = "EXOEnableImageModels"
private let offlineModeKey = "EXOOfflineMode"
private let onboardingCompletedKey = "EXOOnboardingCompleted"
@@ -53,6 +54,14 @@ final class ExoProcessController: ObservableObject {
UserDefaults.standard.set(hfToken, forKey: hfTokenKey)
}
}
+ @Published var hfEndpoint: String = {
+ return UserDefaults.standard.string(forKey: hfEndpointKey) ?? ""
+ }()
+ {
+ didSet {
+ UserDefaults.standard.set(hfEndpoint, forKey: hfEndpointKey)
+ }
+ }
@Published var enableImageModels: Bool = {
return UserDefaults.standard.bool(forKey: enableImageModelsKey)
}()
@@ -273,6 +282,9 @@ final class ExoProcessController: ObservableObject {
if !hfToken.isEmpty {
environment["HF_TOKEN"] = hfToken
}
+ if !hfEndpoint.isEmpty {
+ environment["HF_ENDPOINT"] = hfEndpoint
+ }
if enableImageModels {
environment["EXO_ENABLE_IMAGE_MODELS"] = "true"
}
diff --git a/app/EXO/EXO/Views/SettingsView.swift b/app/EXO/EXO/Views/SettingsView.swift
index bc600efe..64deae83 100644
--- a/app/EXO/EXO/Views/SettingsView.swift
+++ b/app/EXO/EXO/Views/SettingsView.swift
@@ -12,6 +12,7 @@ struct SettingsView: View {
@State private var pendingNamespace: String = ""
@State private var pendingHFToken: String = ""
+ @State private var pendingHFEndpoint: String = ""
@State private var pendingEnableImageModels = false
@State private var pendingOfflineMode = false
@State private var needsRestart = false
@@ -42,6 +43,7 @@ struct SettingsView: View {
.onAppear {
pendingNamespace = controller.customNamespace
pendingHFToken = controller.hfToken
+ pendingHFEndpoint = controller.hfEndpoint
pendingEnableImageModels = controller.enableImageModels
pendingOfflineMode = controller.offlineMode
needsRestart = false
@@ -74,6 +76,17 @@ struct SettingsView: View {
.foregroundColor(.secondary)
}
+ Section {
+ LabeledContent("HuggingFace Endpoint") {
+ TextField("default", text: $pendingHFEndpoint)
+ .textFieldStyle(.roundedBorder)
+ .frame(width: 200)
+ }
+ Text("Defaults to huggingface.co. Use a mirror (e.g. hf-mirror.com) for China.")
+ .font(.caption)
+ .foregroundColor(.secondary)
+ }
+
Section {
Toggle("Offline Mode", isOn: $pendingOfflineMode)
Text("Skip internet checks and use only locally available models.")
@@ -454,6 +467,7 @@ struct SettingsView: View {
private var hasGeneralChanges: Bool {
pendingNamespace != controller.customNamespace || pendingHFToken != controller.hfToken
+ || pendingHFEndpoint != controller.hfEndpoint
|| pendingOfflineMode != controller.offlineMode
}
@@ -464,6 +478,7 @@ struct SettingsView: View {
private func applyGeneralSettings() {
controller.customNamespace = pendingNamespace
controller.hfToken = pendingHFToken
+ controller.hfEndpoint = pendingHFEndpoint
controller.offlineMode = pendingOfflineMode
restartIfRunning()
}
diff --git a/justfile b/justfile
index f278e579..c3bab3c8 100644
--- a/justfile
+++ b/justfile
@@ -31,6 +31,10 @@ build-dashboard:
package:
uv run pyinstaller packaging/pyinstaller/exo.spec
+build-app: package
+ xcodebuild build -project app/EXO/EXO.xcodeproj -scheme EXO -configuration Debug -derivedDataPath app/EXO/build
+ @echo "\nBuild complete. Run with:\n open {{justfile_directory()}}/app/EXO/build/Build/Products/Debug/EXO.app"
+
clean:
rm -rf **/__pycache__
rm -rf target/
← fac6832e fix warmup consistency for slow machines (#1748)
·
back to Exo
·
Prevent Qwen3.5 looping by using mlx lm fork (#1784) b6240a97 →