手机远程控制台 2903077918-lgtm/DeepSeek-phone-harness
DeepSeek Harness手机远程控制 DeepSeek Harness:对话/模型切换/工具审批/终端/文件,4G/5G 任意网络可用
37/100
综合分
14
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:仓库根目录及浅层子目录均无 dsh 插件清单,无法用 dsh 插件安装命令安装。以下命令仍可尝试,但可能失败。
无法用 dsh 插件命令安装(仓库内无 dsh 插件清单)
git clone https://github.com/2903077918-lgtm/DeepSeek-phone-harness.git按该仓库 README 的原生方式安装;若作者另行发布了 DSH 插件包,请以其文档为准
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · ui
装得上吗
作者未把包发布到 npm,只能用源码安装
插件本身没问题,是分发方式不同
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 76 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库根目录及浅层子目录均无 dsh 插件清单,无法用 dsh 插件安装命令安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包DeepSeek-phone-harness(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/2 11:42:10
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 124 处,展示前 113 条)
- 读取本地文件build-en-new.mjs:25
const body = readFileSync(post.file, 'utf8'); - 写入本地文件build-en-new.mjs:34
writeFileSync(`${process.env.TEMP}/en-new-${i}.json`, JSON.stringify({ query })); - 执行外部命令固定命令check-comments.mjs:3
const TOKEN = execSync('gh auth token', { encoding: 'utf8' }).trim(); - 请求外部主机api.github.comcheck-comments.mjs:9
const r = await fetch('https://api.github.com/graphql', { - 发起网络请求check-comments.mjs:9
const r = await fetch('https://api.github.com/graphql', { - 执行外部命令固定命令check-engagement.mjs:4
const TOKEN = execSync('gh auth token', { encoding: 'utf8' }).trim(); - 请求外部主机api.github.comcheck-engagement.mjs:8
const r = await fetch('https://api.github.com/graphql', { - 发起网络请求check-engagement.mjs:8
const r = await fetch('https://api.github.com/graphql', { - 请求外部主机dev.tocheck-engagement.mjs:39
const r = await fetch('https://dev.to/api/articles/me/published?per_page=100', { headers: { 'api-key': DEVTO } }); - 发起网络请求check-engagement.mjs:39
const r = await fetch('https://dev.to/api/articles/me/published?per_page=100', { headers: { 'api-key': DEVTO } }); - 发起网络请求cloud-relay/api/index.ts:71
const response = await cloudRelay.fetch(request, env); - 发起网络请求cloud-relay/src/index.ts:29
async fetch(request: Request, env: Env): Promise<Response> { - 发起网络请求cloud-relay/src/index.ts:281
const assets = (env as unknown as { ASSETS?: { fetch(r: Request): Promise<Response> } }).ASSETS; - 发起网络请求cloud-relay/src/index.ts:285
const res = await assets.fetch(req); - 发起网络请求cloud-relay/src/relay.ts:48
async fetch(request: Request): Promise<Response> { - 发起网络请求cloud-relay/src/supabase.ts:34
const r = await fetch(`${this.base}/${table}?${qs.toString()}`, { headers: this.headers() }); - 发起网络请求cloud-relay/src/supabase.ts:46
const r = await fetch(`${this.base}/${table}?${qs.toString()}`, { headers: this.headers() }); - 发起网络请求cloud-relay/src/supabase.ts:52
const r = await fetch(`${this.base}/${table}`, { - 发起网络请求cloud-relay/src/supabase.ts:69
const r = await fetch(`${this.base}/${table}?${idColumn}=eq.${encodeURIComponent(id)}`, { - 发起网络请求cloud-relay/test-cloud-relay-service.mjs:18
return handler.fetch(r, { SUPABASE_URL: 'https://db.test', SUPABASE_SERVICE_ROLE_KEY: 'sd_ro' }); - 发起网络请求cloud-relay/test-cloud-relay-service.mjs:36
async fetch(url, init = {}) { - 发起网络请求cloud-relay/test-cloud-relay-service.mjs:83
if (url.pathname.includes('/rest/v1/')) return mem.fetch(url, init || {}); - 发起网络请求cloud-relay/test-cloud-relay-service.mjs:97
const preflight = await cloudRelay.fetch( - 发起网络请求cloud-relay/test-cloud-relay-service.mjs:103
const noDb = await cloudRelay.fetch(new Request('https://relay.test/v1/poll?deviceId=d'), {}); - 发起网络请求cloud-relay/test-cloud-relay-service.mjs:192
const noDbStatus = await cloudRelay.fetch(new Request('https://relay.test/v1/status'), {}); - 发起网络请求design/check-ui.js:128
r = await fetch(path, { - 读取本地文件design/integrate-pwa-icons.js:4
let html = fs.readFileSync(path, 'utf8'); - 读取本地文件design/integrate-pwa-icons.js:7
const svg = fs.readFileSync('C:/Users/Joey/Documents/phone-harness/design/icon-source-blackgold.svg', 'utf8'); - 读取本地文件design/integrate-pwa-icons.js:12
const png = fs.readFileSync('C:/Users/Joey/Documents/phone-harness/design/icon-512.png'); - 写入本地文件design/integrate-pwa-icons.js:52
fs.writeFileSync(path, html, 'utf8'); - 读取本地文件design/integrate-pwa-icons.mjs:4
let html = fs.readFileSync(path, 'utf8'); - 读取本地文件design/integrate-pwa-icons.mjs:7
const svg = fs.readFileSync('C:/Users/Joey/Documents/phone-harness/design/icon-source-blackgold.svg', 'utf8'); - 读取本地文件design/integrate-pwa-icons.mjs:12
const png = fs.readFileSync('C:/Users/Joey/Documents/phone-harness/design/icon-512.png'); - 写入本地文件design/integrate-pwa-icons.mjs:52
fs.writeFileSync(path, html, 'utf8'); - 读取密钥环境变量publish-devto.mjs:5
const TOKEN = process.env.DEVTO_TOKEN; - 读取本地文件publish-devto.mjs:64
const body = readFileSync(`docs/promotion/${f}`, 'utf8'); - 发起网络请求publish-devto.mjs:77
const r = await fetch(API, { - 读取本地文件scan-emoji.cjs:2
const c = fs.readFileSync('web/index.html', 'utf8'); - 发起网络请求src/approval-relay.js:180
resp = await fetch(baseUrl + '/api/respond', { - 写入本地文件src/audit.js:23
mkdirSync(path.dirname(file), { recursive: true }); - 写入本地文件src/audit.js:52
appendFileSync(file, line, encoding); - 写入本地文件src/cloud-register.mjs:36
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); - 发起网络请求src/cloud-register.mjs:67
const resp = await fetch(host + '/v1/devices/register', { - 读取本地文件src/cloud-register.mjs:78
try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return {}; } - 读取密钥环境变量src/config.js:14
if (process.env.DEEPSEEK_API_KEY) return process.env.DEEPSEEK_API_KEY; - 执行外部命令固定命令src/config.js:16
const regOut = execFileSync('reg', ['query', 'HKCU\\Environment', '/v', 'DEEPSEEK_API_KEY'], { encoding: 'utf8', windowsHide: true }); - 读取本地文件src/config.js:22
if (existsSync(envFile)) { - 读取本地文件src/config.js:23
const line = readFileSync(envFile, 'utf8').split('\n').find(l => l.startsWith('DEEPSEEK_API_KEY=')); - 读取本地文件src/config.js:32
if (existsSync(CONFIG_PATH)) { - 读取本地文件src/config.js:33
return JSON.parse(readFileSync(CONFIG_PATH, 'utf8')); - 写入本地文件src/config.js:36
writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2)); - 发起网络请求src/dsh-utils.js:19
const resp = await fetch(WEB_API_BASE + '/api/' + method, { - 执行外部命令来自配置/变量src/executor.js:28
const child = spawn(DSH_CMD, ['--profile', 'headless', task], { env, shell: true }); - 执行外部命令固定命令src/executor.js:40
execFileSync('taskkill', ['/PID', String(child.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true }); - 读取本地文件src/executor.js:149
if (!existsSync(SESSIONS_PATH)) return; - 读取本地文件src/executor.js:150
const arr = JSON.parse(readFileSync(SESSIONS_PATH, 'utf8')); - 写入本地文件src/executor.js:168
writeFileSync(SESSIONS_PATH, JSON.stringify([...registry.values()], null, 2)); - 发起网络请求src/executor.js:449
const resp = await fetch(WEB_API_BASE + '/api/commands/execute', { - 发起网络请求src/executor.js:585
const resp = await fetch(WEB_API_BASE + '/api/session.export?sessionId=' + encodeURIComponent(sid)); - 执行外部命令固定命令src/executor.js:796
? spawn('node', [bin, ...args], { cwd: dir, windowsHide: true }) - 执行外部命令来自配置/变量src/executor.js:797
: spawn(bin, args, { cwd: dir, windowsHide: true }); - 执行外部命令固定命令src/executor.js:861
const where = execFileSync('where', ['codex'], { encoding: 'utf8' }); - 读取本地文件src/executor.js:864
const content = readFileSync(cmdPath, 'utf8'); - 读取密钥环境变量src/executor.js:877
const env = String(process.env.GEMINI_API_KEY || '').trim(); - 读取本地文件src/executor.js:880
const cfg = JSON.parse(readFileSync(path.join(ROOT_DIR, 'config.json'), 'utf8')); - 发起网络请求src/executor.js:894
const resp = await fetch(url, { - 执行外部命令来自配置/变量src/executor.js:915
const out = execFileSync(cmd, Array.isArray(args) ? args : ['--version'], { encoding: 'utf8', timeout: 8000, windowsHide: true }); - 读取本地文件src/history.js:8
if (!existsSync(HISTORY_PATH)) return []; - 读取本地文件src/history.js:9
try { return JSON.parse(readFileSync(HISTORY_PATH, 'utf8')); } catch { return []; } - 写入本地文件src/history.js:14
writeFileSync(HISTORY_PATH, JSON.stringify(h.slice(0, 200), null, 2)); - 执行外部命令固定命令src/transport-lan.js:24
const child = spawn('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath, imagePath], { - 执行外部命令固定命令src/transport-lan.js:82
const child = spawn('cmd.exe', ['/d', '/s', '/c', 'chcp 65001 >nul & ' + cmd], { - 执行外部命令固定命令src/transport-lan.js:104
try { spawn('taskkill', ['/PID', String(job.child.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true }); } catch { } - 读取本地文件src/transport-lan.js:162
if (existsSync(relayFile)) { - 读取本地文件src/transport-lan.js:163
res.end(readFileSync(relayFile, 'utf8')); - 读取本地文件src/transport-lan.js:173
if (existsSync(consoleFile)) { - 读取本地文件src/transport-lan.js:174
res.end(readFileSync(consoleFile, 'utf8')); - 读取本地文件src/transport-lan.js:184
if (existsSync(relayFile)) { - 读取本地文件src/transport-lan.js:185
res.end(readFileSync(relayFile, 'utf8')); - 写入本地文件src/web-push.js:22
try { writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); } catch { } - 发起网络请求src/web-push.js:88
const resp = await fetch(endpoint, { - 读取本地文件src/web-push.js:106
if (!existsSync(filePath)) return; - 读取本地文件src/web-push.js:107
const arr = JSON.parse(readFileSync(filePath, 'utf8')); - 写入本地文件src/web-push.js:112
try { writeFileSync(filePath, JSON.stringify([...subs.values()], null, 2), 'utf8'); } catch { } - 读取密钥环境变量t-e2e-question.mjs:3
const TOK = process.env.PH_TOKEN || '请设置环境变量 PH_TOKEN'; - 发起网络请求t-e2e-question.mjs:11
const r = await fetch(BASE + path, { headers: h, ...opts }); - 发起网络请求t-e2e-question.mjs:25
const r = await fetch(BASE + '/api/dsh-continue', { - 读取本地文件test-approvals.mjs:6
const token = JSON.parse(readFileSync('C:/Users/Joey/Documents/phone-harness/config.json', 'utf8')).token; - 发起网络请求test-approvals.mjs:20
const a1 = await (await fetch(base + '/api/approvals', { headers: h })).json(); - 发起网络请求test-approvals.mjs:24
const bad = await (await fetch(base + '/api/approvals', { - 发起网络请求test-approvals.mjs:30
const noauth = await (await fetch(base + '/api/approvals', { headers: { 'content-type': 'application/json' } })).json(); - 读取本地文件test-core-modules.mjs:73
const lines = readFileSync(tmpFile, 'utf8').trim().split('\n').map((l) => JSON.parse(l)); - 删除本地文件test-core-modules.mjs:76
if (existsSync(tmpFile)) unlinkSync(tmpFile); - 读取本地文件test-core-modules.mjs:76
if (existsSync(tmpFile)) unlinkSync(tmpFile); - 读取本地文件test-e2e.mjs:6
const token = JSON.parse(readFileSync('C:/Users/Joey/Documents/phone-harness/config.json', 'utf8')).token; - 发起网络请求test-e2e.mjs:11
const status = await (await fetch(base + '/api/status', { headers })).json(); - 发起网络请求test-e2e.mjs:17
const execResp = await (await fetch(base + '/api/exec', { - 发起网络请求test-e2e.mjs:27
const hist = await (await fetch(base + '/api/history', { headers })).json(); - 发起网络请求test-goal-api.mjs:147
const resp = await fetch(`http://127.0.0.1:${port}/api/session.create`, { - 读取本地文件test-integration.mjs:6
const token = process.argv[2] || JSON.parse(readFileSync('C:/Users/Joey/Documents/phone-harness/config.json', 'utf8')).token; - 发起网络请求test-integration.mjs:14
const r = await fetch(base + path, { ...opts, headers: h }); - 发起网络请求test-integration.mjs:25
const page = await (await fetch(base + '/', { headers: { authorization: 'Bearer ' + token } })).text(); - 读取密钥环境变量test-utils/agent-ready.mjs:12
if (process.env.RELAY_TOKEN) return process.env.RELAY_TOKEN; - 读取本地文件test-utils/agent-ready.mjs:14
const cfg = JSON.parse(readFileSync(pathToFileURL(process.cwd() + '/config.json'))); - 发起网络请求test-utils/agent-ready.mjs:28
const r = await fetch(AGENT_BASE + '/api/status', { headers, signal: ctrl.signal }); - 读取本地文件verify-v2.mjs:4
const token = JSON.parse(readFileSync('C:/Users/Joey/Documents/phone-harness/config.json', 'utf8')).token; - 发起网络请求verify-v2.mjs:8
const page = await (await fetch('http://127.0.0.1:8788/', { headers: { authorization: 'Bearer ' + token } })).text(); - 发起网络请求verify-v2.mjs:11
const s = await (await fetch('http://127.0.0.1:8788/api/dsh-sessions?withCount=true', { headers: h })).json(); - 发起网络请求verify-v2.mjs:15
const ev = await (await fetch('http://127.0.0.1:8788/api/events?sessionId=' + (s.items?.[0]?.sessionId || '') + '&afterSeq=0', { headers: h })).json() - 发起网络请求verify-v2.mjs:20
const c = await (await fetch('http://127.0.0.1:8788/api/cancel', { method: 'POST', headers: h, body: JSON.stringify({ sessionId: 'x' }) })).json(); - 写入本地文件video/capture.mjs:10
mkdirSync(OUT, { recursive: true }); - 读取密钥环境变量video/capture.mjs:12
const TOKEN = process.env.PH_TOKEN || 'eaa8e4ef031fa3acb5c2b60e097408a7edd07d671f6457a04c19294514708b59'; - 写入本地文件video/capture.mjs:83
writeFileSync(OUT + 'layout.json', JSON.stringify(layout, null, 2));
扫描于 2026/11/2(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库
涉及外部主机:api.github.com、dev.to
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 远程控制对话
- 切换模型
- 工具审批
README
由 DeepSeek 最新模型翻译生成🐋 DeepSeek Phone Harness
把 DeepSeek Harness 装进口袋 —— 手机远程控制你的电脑智能体
DeepSeek Harness on your phone. Remote-control your desktop agent from anywhere — 4G/5G, no WiFi needed.
Node.js · 零依赖 · Cloudflare Workers · WebCrypto E2EE
▶ 点击上方图片观看 31 秒宣传片 · Phone in hand. Computer at your command. 手机在手,电脑随行
⭐ 觉得有用?点个 Star,就是对这个开源项目最大的支持
三分钟跑起来
git clone https://github.com/2903077918-lgtm/DeepSeek-phone-harness
cd DeepSeek-phone-harness && cp config.example.json config.json
node agent.mjs --mode=both
手机 Tailscale 连上电脑,打开 http://<电脑IP>:8788/,开工。任意网络(4G/5G/WiFi)都能用,不需要公网 IP。
这是什么?
展开完整文档(README 剩余 1 节)
🐋 DeepSeek Phone Harness 把 DeepSeek Harness 装进口袋 —— 手机远程控制你的电脑智能体 DeepSeek Harness on your phone. Remote-control your desktop agent from anywhere — 4G/5G, no WiFi needed. Node.js · 零依赖 · Cloudflare Workers · WebCrypto E2EE ▶ 点击上方图片观看 31 秒宣传片 · Phone in hand. Computer at your command. 手机在手,电脑随行 ⭐ 觉得有用?点个 Star,就是对这个开源项目最大的支持 三分钟跑起来 git clone https://github.com/2903077918-lgtm/DeepSeek-phone-harness cd DeepSeek-phone-harness && cp config.example.json config.json node agent.mjs --mode=both 手机 Tailscale 连上电脑,打开 http://<电脑IP>:8788/,开工。任意网络(4G/5G/WiFi)都能用,不需要公网 IP。 这是什么? DeepSeek Phone Harness 是一个手机端远程控制系统,让你在任何网络(4G/5G / WiFi / 公网)下,用手机操作电脑上的 DeepSeek Harness —— 发任务、看流式输出、批准工具调用、回答智能体提问、跑终端命令、翻文件、查任务记录,全都在手掌心里完成。 界面参考开源项目 codex-relay 的设计语言,对话体验对标 DeepSeek Harness Web GUI:模型选择、图片附件、思考过程折叠、工具调用卡片(带路径/状态/详情)、审批与提问卡,一样不少。 ✨ 核心特性 | 能力 | 说明 | | 💬 对话 | 多轮会话、Markdown 渲染、分步 step 卡片、会话历史 | | ⚡ 实时跟随 | SSE 长连接推送(对标 DSH events.mux),打开会话即实时收事件——消息/工具/统计自动刷新,非轮询 | | 🎛 模型/模式切换 | 顶栏胶囊 → 底部面板,多服务商 / 多模型即时切换(如 deepseek-v4-flash)| | 🖼 图片 OCR | 手机发图 → 电脑端 Windows 自带 OCR 转文本(免费、本地、不耗 token)拼进任务 | | 🧠 思考过程 | 智能体推理内容折叠展示,流式时自动展开 | | 🔧 工具卡片 | 每一步操作一张卡:图标 + 状态(执行中/完成/失败)+ 文件路径参数 + 点击展开完整参数与结果 | | 🛡 审批与提问 | 危险操作审批卡(允许/拒绝)、ask_user_question 提问卡(选项/自定义回答/跳过),不回答任务不卡死 | | 🪜 轨迹面板 | 对话/轨迹切换:ASSISTANT/TOOL 时间线 + 搜索 + Duration 列 | | ⚙️ 设置同步 | 繁忙时 Enter(排队/插话)、语言(中/英)、新会话默认权限、模型提供方增删改——真写入电脑端 DSH 设置 | | ⌨️ 终端 | 手机远程执行电脑命令,流式输出、可停止、支持 UTF-8 中文 | | 📋 任务列表 | 历史任务回看、展开 stdout/stderr、一键重跑、复制输出 | | 📁 文件与代码 | 浏览电脑目录、查看文件内容(代码界面)、打开 DSH 配置文件 | | 🗂 工作区/会话 | 多项目工作区切换、会话新建 / 重命名 / 删除 / 分支(长按或 ⋮ 操作面板)| | 🎨 视觉 | 对标 DSH 桌面端:中性灰胶囊 + 单一强调蓝、任务清单可收起、默认深色 | | 📡 任意网络 | Tailscale 4G/5G 直连电脑,或经 Cloudflare Worker 云端入口 | | 🔒 安全 | Bearer Token 鉴权、审批/提问需手机确认、E2EE 可选(云端通道) | 🏗 架构 ┌──────────────┐ HTTPS / Tailscale ┌─────────────────────────────┐ │ 手机浏览器 │ ──────────────────────────▶ │ Agent(电脑端, Node, 8788) │ │ relay.html │ │ ┌─────────────────────────┐ │ │ codex-relay │ │ │ transport-lan(HTTP+鉴权)│ │ │ 风格 UI │ ◀── SSE 推送 /api/events.stream ─│ │ executor(DSH RPC 封装) │ │ └──────────────┘ │ │ approval-relay(WS 中继) │ │ │ │ └───────────┬─────────────┘ │ │ 可选:Cloudflare Worker 静态托管 │ │ 127.0.0.1:3080 │ ▼ │ ▼ │ ┌──────────────┐ │ ┌─────────────────────────┐ │ │ relay.axyntara│ ◀── 手机直接访问 Worker ───── │ │ DeepSeek Harness 网关 │ │ │ .cn (Worker) │ │ │ (dsh web, 会话/工具) │ │ └──────────────┘ │ └─────────────────────────┘ │ └─────────────────────────────┘ - Agent:纯 Node.js 实现,零第三方依赖。HTTP 传输层(8788)+ DSH Web API RPC 封装(127.0.0.1:3080)+ 审批/事件中继(events.mux WebSocket)。 - 前端:单文件 relay.html,无框架,深色 codex-relay 设计系统(#191919 / 金色鲸鱼标识)。 - 云端:cloud-relay/ 为 Cloudflare Worker(可选),托管前端静态资源并支持 E2EE 任务通道(Supabase 可选)。 🚀 快速开始 前置条件 - 电脑已安装并运行 DeepSeek Harness Web(dsh web,监听 127.0.0.1:3080) - Node.js 22+(Agent 使用全局 fetch / WebSocket) 1. 配置并启动 Agent 1) 复制配置模板并填写访问令牌 cp config.example.json config.json 2) 启动(LAN 8788 + 云端轮询) node agent.mjs --mode=both 启动后终端会打印本机地址与 Token: deepseekharness-relay Agent v0.4.0 控制台: http://<本机IP>:8788 Token: <你的访问令牌> 2. 手机连接 1. 手机与电脑同一 Tailscale 网络(4G/5G 也可直连):打开 http://<电脑Tailscale IP>:8788/ 2. 或在任意网络访问云端入口:https://relay.axyntara.cn/ 3. 输入服务器地址 + 访问令牌 → 连接 → 选择工作区 → 开始对话 3. 云端部署(可选) cd cloud-relay wrangler deploy # 需要 Cloudflare 账号;静态资源来自 ../web 🗂 目录结构 phone-harness/ ├── agent.mjs # Agent 入口(--mode=lan|cloud|both) ├── src/ │ ├── transport-lan.js # 局域网 HTTP 传输层(8788,REST + 静态页) │ ├── executor.js # DSH RPC 封装:会话/历史/审批/模型/终端等 │ ├── approval-relay.js# events.mux WebSocket 中继(审批+提问+事件流) │ ├── dsh-utils.js # RPC/事件归一化工具 │ └── config.js # 端口 / 版本 / API Key 解析 ├── web/ │ ├── relay.html # ★ 手机端主界面(单文件,codex-relay 风格) │ ├── index.html # 与 relay.html 同步(云端根路径) │ └── console.html # 旧版局域网控制台(归档) ├── cloud-relay/ # Cloudflare Worker(静态托管 + 可选 E2EE 通道) └── t-e2e-question.mjs # 端到端测试脚本 🔐 安全说明 - 所有 API 均要求 Authorization: Bearer <token>,token 由 config.json 管理且 不入库(见 .gitignore)。 - 工具调用采用 审批制:危险操作会先在手机端弹出「需要授权」卡片,由你决定允许/拒绝。 - Agent 反问用户时必须手机回答(提问卡),否则任务会等待,不会擅自继续。 - 建议仅在 Tailscale 等私有网络暴露 8788;公网请经 Cloudflare Worker 并开启 E2EE。 🗺 Roadmap - [x] 对话 / 流式 / 模型选择 / 图片附件 - [x] 工具卡片(路径·状态·详情)/ 思考过程 / 审批 / 提问 - [x] 终端 / 任务列表 / 文件与代码 / 会话管理(含分支) - [x] SSE 实时跟随(长连接推送,替代轮询) - [x] 轨迹面板(ASSISTANT/TOOL + Duration + 搜索) - [x] 设置同步(Enter 行为 / 语言 / 默认权限 / 提供方 → DSH) - [x] 图片 OCR 转文本(免费本地不耗 token) - [x] 视觉对标 DSH 桌面端(中性灰 + 单一强调蓝) - [ ] 移动端 PWA(离线壳 + 推送) - [ ] 会话「继续在电脑端打开」 - [ ] DSH WebSocket-Remote 客户端(解锁权限切换 / 消息反馈 / commands) - [ ] 多设备 / 多账号 📄 License MIT © 2026 项目作者 DeepSeek Harness 手机远程控制 —— 让 Agent 随时随地在手边工作。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
2903077918-lgtm/DeepSeek-phone-harness
手机远程控制 DeepSeek Harness:对话/模型切换/工具审批/终端/文件,4G/5G 任意网络可用
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,350已汉化DSH
71.5
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,506已汉化DSH
71.1
AI 矢量设计工具ZSeven-W/openpencil
全球首个 AI 原生开源矢量设计工具。
★ 7,027已汉化DSH
71.1
这是你的仓库?认领条目