Herdr UI
Herdr의 TUI가 뛰어나며, 창을 통해 추가되는 기능
DeepSeek Harness 모바일 클라이언트로 iPhone에서 작업공간·채팅·실시간 응답·Agent 실행 기록을 WebSocket으로 연결
DeepSeek Harness Mobile 是一个面向 DeepSeek Harness 的原生移动端客户端。它通过 dsh-plugin-mobile-gateway 与 Harness 建立 WebSocket 连接,将工作区、会话、实时回复和 Agent 执行轨迹带到 iPhone,同时延续 DeepSeek WebUI 克制、清晰的视觉语言
개발 도구Kotlin · SwiftGitHub @Clarklevis1995직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗English · 简体中文 · 日本語 · 한국어 · Español · Français · Deutsch · Português (Brasil)
Native Android and iOS apps with core business logic shared through Kotlin Multiplatform.
Connect to DeepSeek Harness through Mobile Gateway to access workspaces, live conversations, Agent traces, plugins, scheduled tasks, and files from your phone, tablet, or foldable.
Website: Whaleness
Whaleness is an independently developed third-party native mobile client for DeepSeek Harness. Both Android and iOS apps use Kotlin Multiplatform (KMP):
shared is the source of truth for shared business state, including protocol handling, state machines, reducers, projections, and synchronization.androidApp implements the Android app with Kotlin, Jetpack Compose, and OkHttp.DeepSeekHarnessMobile builds the iOS interface with SwiftUI/UIKit and accesses shared logic through a Kotlin/Native framework.Both apps connect to Harness over WebSocket through dsh-plugin-mobile-gateway. Networking, secure storage, files, images, lifecycle handling, and background execution use native platform APIs. Business rules are consolidated in shared/commonMain wherever practical.
dsh-plugin-mobile-gateway 0.11.1 or later installed and enabled. AppRelease/release-info.json defines the required minimum version.Join the Whaleness beta WeChat group 2 to share feedback, discuss your experience, and get support. Scan with WeChat, or save the image and recognize it in WeChat.
Updated on October 28, 2026. The original image states that the code is valid before November 4, 2026. If it has expired, check the product page for the latest group QR code.
| Platform / module | Status | Main components |
|---|---|---|
KMP shared | Used by Android and iOS | Gateway protocol, stores/reducers, conversation and trace projections, history synchronization, questions/approvals, session control, workspace file state, and code preview support |
| Android | Native client available | Jetpack Compose, OkHttp WebSocket, DataStore for non-sensitive settings, Keystore for credentials, CameraX/ML Kit QR scanning, foreground service, attachment cache, file downloads, and previews |
| iOS | Native client available | SwiftUI/UIKit, URLSession WebSocket, UserDefaults for non-sensitive settings, Keychain for credentials, QR pairing, background execution, attachments, and workspace files |
Android and iOS each have their own native UI and platform integrations. Features and interactions are being aligned, while some system-level behavior differs between platforms.
read-only, workspace-write, and danger-full-access. These control the Agent on the host, not the phone's local filesystem.Latest iOS product screenshots: the 1.7.10 image set was captured on October 22–23, 2026; the iPhone Duo set was captured on October 26, 2026. The interface shown is Chinese. Product screenshot sources · Duo screenshot sources.
Screenshots show the iOS app with Chinese UI; Android implements the corresponding information architecture and workflows with Jetpack Compose. The voice, file, text-size, and iPad screenshots were captured on October 16, 2026, using version 1.7.6. See screenshot sources.
View the slide-up-to-cancel state
DeepSeek Harness
│
dsh-plugin-mobile-gateway
│
WebSocket
┌───────────────┴───────────────┐
│ │
Android OkHttp Transport iOS URLSession GatewayClient
│ │
KMP Gateway Runtime Swift Router / KMP Adapter
│ │
└───────────────┬───────────────┘
│
KMP shared / commonMain
Protocol · Store · Reducer · Projection
History Sync · Question/Approval · Workspace Files
┌───────────────┴───────────────┐
│ │
Jetpack Compose SwiftUI / UIKit
Android UI iOS UI
protocol/: Gateway DTOs, JSON representations, and wire decoding.gateway/: Platform transport interfaces, pairing, authentication, request correlation, reconnection, and event backpressure. Android uses the full shared runtime, with OkHttp providing the underlying transport.domain/: Reducers for sessions, questions, approvals, and session control.projection/: Incremental conversation and trace projections.sync/: History pagination, live-tail merging, and deduplication.facade/: Coarse-grained stores, intents, and events for Swift/Kotlin adapters, plus workspace paths, chunk ordering, progress, and SHA-256 verification.The shared module does not depend on Compose, SwiftUI, Android Framework, or Apple UI frameworks. iOS reuses shared stores, reducers, projections, and file state machines. Its Swift GatewayClient still owns WebSocket connections and reconnection, forwarding events into the shared module through an adapter; iOS does not yet use the full KMP Gateway Runtime.
Each platform handles secure storage, image processing, temporary files, system sharing/opening, and application lifecycle. The shared module owns the remote file protocol, state transitions, chunk consistency, and integrity checks without accessing platform filesystems directly.
.
├── shared/ # Kotlin Multiplatform business logic
│ └── src/
│ ├── commonMain/ # Protocol, state machines, projections, sync, facades
│ └── commonTest/ # Cross-platform unit tests
├── androidApp/ # Native Android app (Jetpack Compose)
│ └── src/
│ ├── main/ # App code and platform integrations
│ ├── test/ # JVM tests
│ └── androidTest/ # Device tests
├── DeepSeekHarnessMobile/ # Native iOS app (SwiftUI/UIKit)
├── DeepSeekHarnessMobileTests/ # iOS XCTest tests
├── DeepSeekHarnessMobile.xcodeproj
├── Docs/ # Research, KMP migration, and validation
└── Design/ # Design specifications and artwork
dsh-plugin-mobile-gateway 0.11.1+ enabled.compileSdk / targetSdk).Set up Java 17 and point ANDROID_HOME or ANDROID_SDK_ROOT to your Android SDK.
Build a Debug APK from the repository root:
./gradlew :androidApp:assembleDebug
Install it on a connected device or emulator:
./gradlew :androidApp:installDebug
Launch DshMobile and scan the pairing QR code from WebUI, or enter pairing details manually.
The Debug APK is generated at:
androidApp/build/outputs/apk/debug/androidApp-debug.apk
To let an Android emulator access the host's 127.0.0.1:3080, first run:
adb reverse tcp:3080 tcp:3080
DeepSeekHarnessMobile.xcodeproj in Xcode.DeepSeekHarnessMobile scheme and your target device.Build KMP Framework phase automatically selects and compiles the matching Kotlin/Native framework.You do not need to build the framework manually first. To build only the Apple Silicon iOS Simulator framework:
./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
Install or upgrade dsh-plugin-mobile-gateway in DeepSeek Harness (minimum 0.11.1), then fully exit and restart dsh web:
dsh plugin --profile web add dsh-plugin-mobile-gateway@latest
Open the Mobile Devices panel in WebUI and enable mobile connections and device authentication.
Make sure the WebSocket endpoint is reachable from your mobile device or simulator.
Generate a one-time pairing QR code/token and authenticate in the Android or iOS app.
Return to the home screen, confirm that Gateway is connected, then choose a workspace and session.
Common endpoints:
| Environment | Endpoint |
|---|---|
| iOS Simulator | ws://127.0.0.1:3080/ws/mobile |
Android Emulator with adb reverse | ws://127.0.0.1:3080/ws/mobile |
| Physical device on the same LAN | ws://<HOST-LAN-IP>:3081/ws/mobile |
| Public deployment | wss://<your-domain>/ws/mobile |
[!IMPORTANT] A physical phone cannot reach your computer through
127.0.0.1. Thews://examples are for trusted local development only. Usewss://with correctly configured TLS and device authentication on public or untrusted networks. Do not include one-time pairing tokens in logs, issues, or chat messages.
[!NOTE] Physical devices on a LAN use the separate port
3081listener provided bydsh-plugin-mobile-gateway. It serves only authenticated/ws/mobilerequests; other paths return 404. Port3080belongs to DSH WebUI and listens on loopback only, so physical devices cannot connect through it.
Run Android unit tests, lint, and the APK build:
./gradlew \
:androidApp:testDebugUnitTest \
:androidApp:lintDebug \
:androidApp:assembleDebug
Run the shared Kotlin/Native tests on Apple Silicon macOS:
./gradlew :shared:iosSimulatorArm64Test
With an Android device or emulator available, run device tests:
./gradlew :androidApp:connectedDebugAndroidTest
For iOS tests, select the DeepSeekHarnessMobile scheme in Xcode and choose Product → Test. The build phase links DeepSeekHarnessShared.framework for the selected architecture automatically.
Some linked technical documents are currently available in Chinese.
The following documents record the KMP migration and Android implementation. For the current state, refer to this README and the source code:
Whaleness is under active development. The KMP shared module and native Android and iOS apps are implemented. Protocol support, platform consistency, and the mobile experience continue to evolve alongside DeepSeek Harness and Mobile Gateway.
This is an independently developed third-party client for DeepSeek Harness.
Both apps' About screens use AppRelease/release-info.json and AppRelease/release-notes.md. The JSON version must match the app version; minimumGatewayVersion specifies the required minimum Mobile Gateway plugin version. Markdown contains the release notes for that version. Apps load these bundled resources locally without fetching the text over the network.
The KMM dual-release skill writes reviewed release notes and synchronizes the resource version before compilation. It verifies that the resources in the APK, AAB, and iOS bundle match the source files, and restores resources and version files if packaging fails. Changes to release notes require rebuilding the apps; editing only the release output directory does not update bundled content.
The Build Metal Library phase runs scripts/build_metal_library.sh, locates an installed Metal toolchain, and writes default.metallib into the app bundle. It clears Android Studio's injected TOOLCHAINS and SDKROOT only in its subprocess, while explicitly preserving the current iOS SDK and deployment target. This avoids false missing-Metal-toolchain errors caused by forcing XcodeDefault.
Android checks https://download.whaleness.cc/latest.json first and falls back to GitHub Releases if the request fails or the configuration is invalid. The schemaVersion: 1 configuration includes version, versionCode, packageName, downloadUrl, size, and sha256, with optional githubDownloadUrl and releaseNotes. Downloads accept only configured trusted accelerated-download domains and this project's GitHub URLs. If the accelerated source fails, the app switches to the fallback while verifying package size, SHA-256, version, package name, and signature against the same configuration.
Publishing uploads an immutable versioned APK before updating the root latest.json. Update manifests should bypass CDN caching; APK files may be cached. When no newer build is found, no GitHub request is made. Startup checks remain silent, while manual checks in Settings display their result.
Run python3 scripts/configure_r2_release.py to save S3 object read/write credentials for the configured bucket in ~/.config/whaleness/r2-release.json with permissions 600. sh scripts/r2_release.sh --check only verifies connectivity. sh scripts/r2_release.sh --prepare <release-directory> generates a manifest; --publish <release-directory> performs the remote publication. The S3 SDK is installed in the isolated build/r2-tools environment.
When local configuration exists, the KMM dual-release skill publishes automatically: validate local packages, upload an immutable APK whose filename includes the build number, verify both the remote object and public download, then conditionally update latest.json. A failed upload can be retried with the same release directory without rebuilding. Set R2_UPLOAD=0 for local packaging only. Full upload tests may generate R2 read requests; the initial connection check does not modify remote objects.