DeepSeek Harness Remote
DeepSeek Harness Remote 可将手机或另一台电脑与你运行 DeepSeek Harness 的电脑安全连接,随时随地继续你的工作,方便随时查看进度并继续工作。
AI 翻译
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Android assistant that gets things done on your phone. Describe a task and it taps, types and follows through.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗An Android app that does tasks on your phone for you: say or type what you want, and it uses Claude to look at the screen and tap, type and swipe through your apps until the job is done. It is built first for blind, low-vision and motor-impaired users, and works for anyone who wants hands-free control of any app.
Phones assume you can see the screen and hit small targets. A screen reader tells you what is there, but a five-screen task like "message Sarah that I'm running late" is still dozens of precise gestures. Handy AI turns the sentence into those gestures, can read every step aloud, and stops when you tell it to.
Watch the 60-second demo on YouTube
You need an Android 11+ phone and an Anthropic API key (starts with sk-ant-; Anthropic bills you per use).
The APK on the website can lag behind main. At the time of writing it is 1.5.5 (Claude Opus 4.7); main is 1.5.6 (Claude Opus 5.5). Build from source for the latest.
This is the run in the screenshot above, copied from the app's chat log (v1.5.1 on a Pixel 10). Indented lines are a status row and the tool calls Claude made:
You: take a picture with the phone camera
Screen: 1080x2424
Claude: I'll go to the home screen and open the camera app to take a picture.
key({"action":"home"})
Claude: I can see the Camera app icon. I'll tap it.
tap({"x":336,"y":2035})
Claude: The camera is open in Photo mode. I'll tap the shutter button to take the picture.
tap({"x":540,"y":1810})
Claude: The picture has been taken - I can see the new thumbnail in the bottom-left preview
now showing the image of the office with the chair.
finish({"success":true,"summary":"Opened the Camera app and tapped the shutter button to take a picture. The new photo appears in the thumbnail preview."})
Claude: Opened the Camera app and tapped the shutter button to take a picture. The new photo
appears in the thumbnail preview.
More things to try:
| Say or type | Notes |
|---|---|
| "Message Sarah on WhatsApp that I'm running late." | If voice is on, you get a spoken warning and a pause before it taps Send |
| "Search Google Maps for sushi near me." | |
| "Read me the screen." | Claude calls the on-device OCR tool and the text is read aloud |
| "What did you do?" | Answered on the phone from this chat's log, no API call |
| "What can you do?" | Answered on the phone with example tasks, no API call |
read_screen_text / read_text_at run Google ML Kit OCR on the device.All settings are in the app (gear icon). Nothing is configured with environment variables at runtime.
| Setting | Default | What it does |
|---|---|---|
| Anthropic API key | none | Required. Saved from the key bar or Settings; must start with sk-ant- |
| Voice mode | Auto | Off, On, or Auto (speak only while a screen reader such as TalkBack is on) |
| Narration | Brief | How much of each step is spoken: Off, Brief, Detailed |
| Voice-warn before destructive actions | On | Spoken warning and 1.5 s pause; needs voice to be on |
| Vibration feedback | On | Patterns for started, done, needs attention, error |
| Easy Mode | Off | Single mic button UI |
| Named aliases | none | Added to the prompt so Claude can resolve them |
| High-contrast text | Off | See Limitations |
Agent constants live in code:
| Constant | Value | File |
|---|---|---|
| Model | claude-opus-5-5 | AgentLoop.kt (MODEL, the only place it is set) |
Effort / max_tokens per step | low / 8192 | AnthropicClient.kt, AgentLoop.kt |
| Max steps per task | 40 | AgentLoop.kt |
| Screenshots kept in the conversation | the task's first one plus the 4 most recent; older ones become a text note | AgentLoop.kt |
| Settle delay after each action | 700 ms | AgentLoop.kt |
| Retries | up to 4 attempts on HTTP 408, 429, 500, 502-504, 529 and network errors | AnthropicClient.kt |
Permissions
| Permission | Why |
|---|---|
INTERNET | Calls the Anthropic API |
VIBRATE | Haptic feedback |
| Accessibility service (you turn it on in Android settings) | Take screenshots, perform taps and swipes, set text in the focused field and press Enter, press Back / Home / Recents, show the accessibility shortcut button |
The accessibility service only acts while a task you started is running. It does not process accessibility events (the handler is empty). Its config also declares window-content access, which is used to find the focused text field.
What leaves your phone
| When | What | Sent to |
|---|---|---|
| Every step of a running task | A JPEG screenshot of the whole screen (notifications and anything else visible included), your task text, your named aliases, earlier steps of this task, action results, and any text the OCR tools read | api.anthropic.com, directly from the phone with your key, under Anthropic's API terms |
| Only if you use Set up via computer | Your API key, typed on your computer | Relayed to the phone through the author's server (dashob.com). The setup page says it is held in memory for at most 10 minutes and deleted when the phone collects it |
| Only if you pair in Settings > Cloudbot pairing | A device token, a random device ID and your phone's model name | The author's hub server, over a WebSocket |
Apart from the optional rows above, nothing is sent while no task is running. OCR runs on the device with Google ML Kit, which may send Google usage metrics under its own terms. Crash reporting (Sentry) is compiled in but only starts when a DSN is set at build time; the published APK has none.
What stays on your phone
EncryptedSharedPreferences (AES-256, key in the Android Keystore). If the Keystore is unusable on a device, it falls back to plain app-private storage.Safety. Claude is instructed not to enter passwords or payment details, and not to delete, buy, uninstall or send money unless you asked for that exact thing. That is an instruction to the model, not a sandbox: the service can tap anything you can. Watch what it does and use Stop.
you: "take a picture"
|
MainActivity / EasyModeActivity
| startAgent(key, task)
AgentAccessibilityService ---- TaskRunner (one task at a time, Stop = cancel)
|
AgentLoop, up to 40 steps:
1. takeScreenshot() (Android 11+ accessibility API)
2. POST /v1/messages (AnthropicClient: screenshot + history + tools)
3. Claude replies with a tool call (AgentProtocol parses it, AgentActions validates it)
4. run it: dispatchGesture / ACTION_SET_TEXT / global action / OCR
5. wait 700 ms, take a new screenshot, send it back as the tool result
... until Claude calls finish, Stop is pressed, or the step limit is hit
Tools Claude can call: tap, long_press, swipe, type_text, clear_text, key (back, home, recents, ime_enter), wait (up to 3 s), read_screen_text, read_text_at, finish. Coordinates are screen pixels; the screen size is given in the system prompt.
| Path | Role |
|---|---|
app/src/main/java/com/claudeagent/phone/AgentLoop.kt | The screenshot, Claude, action loop |
AgentProtocol.kt, AgentActions.kt, AgentTools.kt | Response parsing, history trimming, system prompt; tool input validation; tool schemas sent to Claude (pure Kotlin, unit tested) |
AnthropicClient.kt | OkHttp client for the Messages API with retries and immediate cancel |
AgentAccessibilityService.kt, TaskRunner.kt | Screenshots and gestures; runs one agent task at a time |
AccessibilityHelper.kt, ScreenOcr.kt | Text-to-speech, haptics, the destructive-action heuristic; ML Kit OCR |
MainActivity.kt, EasyModeActivity.kt, SettingsActivity.kt, KeySetupActivity.kt | UI |
LocalIntents.kt, NameAliases.kt, ChatStore.kt, ApiKeyStore.kt | On-device answers, aliases, chat history, key storage |
HubClient.kt, HubConnection.kt, HubPairActivity.kt | Optional pairing with the author's agent hub |
OnboardingActivity.kt, SupabaseAuth.kt, AuthStore.kt, EntitlementClient.kt, LemonSqueezyClient.kt, BillingConfig.kt | A trial and subscription mode that is currently switched off (its backend was deleted; see supabase/REBUILD.md) |
PanelClient.kt, PanelPairActivity.kt | Pairing with a retired dashboard; kept only so old pairings can be cleared |
docs/ | The gethandyai.app site, including the APK and the computer key-setup page |
playstore/ | Store listing assets, screenshots and demo videos |
Requirements: JDK 17 and the Android SDK (platform 35). Android Studio provides both.
git clone https://github.com/fainir/handy-ai.git
cd handy-ai
echo "sdk.dir=$HOME/Library/Android/sdk" > local.properties # your SDK path; or export ANDROID_HOME
./gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk
The debug build is signed with your local debug key, so uninstall a Play or website copy first (same package name, different signature). No secrets are needed: the optional values in local.properties.example (Supabase, Google sign-in, Sentry) fall back to placeholders and only affect the dormant features.
Release builds read signing details from a git-ignored keystore.properties (storeFile, storePassword, keyAlias, keyPassword), then ./gradlew assembleRelease bundleRelease.
./gradlew testDebugUnitTest # JVM unit tests: no device, no network, no API calls
./gradlew lintDebug
CI (.github/workflows/ci.yml) runs assembleDebug testDebugUnitTest lintDebug on every push and pull request. The unit tests cover response parsing, tool input validation, screenshot-history trimming, the system prompt, local intents, error messages, task cancellation and the hub WebSocket (against a local mock server).
/goal for every turn: sends Claude Code back when it stops early