本文档基于 mvp-spec.md、implementation-plan.md、acceptance.md 和 src/ 当前实现,描述 mobile-code 的运行架构、模块边界和安全约束。
简化链路:手机 Telegram -> Hermes Agent -> mobile-code CLI -> Claude Code -> 开发项目仓库
flowchart LR
user["用户手机 Telegram"]
bot["Telegram Bot"]
hermes["Hermes Gateway\nlaunchd 常驻在 Mac"]
mobile["mobile-code CLI\n~/.local/bin/mobile-code -> dist/mobile-code.js"]
claude["Claude Code CLI\nclaude -p"]
repo["目标 Git 仓库\nalias -> repo path"]
state["~/.mobile-code\nconfig / logs / jobs / locks / job-counter"]
tgapi["Telegram Bot API\n主动推送任务结果"]
remote["Git remote\norigin/mobile/<job>"]
user -->|"自然语言或显式命令"| bot
bot --> hermes
hermes -->|"terminal tool 调用"| mobile
mobile -->|"按 alias 进入仓库"| repo
mobile -->|"spawn detached __worker"| mobile
mobile -->|"执行 claude -p"| claude
claude -->|"读写文件 / 跑测试"| repo
mobile <--> state
mobile -->|"任务结果 sendMessage"| tgapi
tgapi --> user
mobile -->|"push 子命令才触发"| remote
核心边界:
- Hermes 负责 Telegram 入口和命令路由,不负责真正写代码。
mobile-code负责项目别名解析、权限档、锁、job、分支、日志、commit/push。- Claude Code 才是真正执行代码阅读、修改、测试的 agent。
- 任务执行结果由 detached worker 直接推回 Telegram,不依赖 Hermes 长时间等待。
flowchart TB
subgraph cli["dist/mobile-code.js"]
entry["src/cli.ts\ncommander 入口"]
projects["src/projects.ts\nalias -> repo"]
tiers["src/tiers.ts\n权限档 -> claude flags"]
config["src/config.ts\n读取 ~/.mobile-code/config"]
jobs["src/jobs.ts\n原子 job id + metadata"]
lock["src/lock.ts\n每仓库互斥锁"]
worker["src/worker.ts\n__worker 后台执行"]
telegram["src/telegram.ts\nTelegram 推送 + retry"]
paths["src/paths.ts\n运行时路径"]
end
subgraph commands["用户可见命令"]
ping["ping"]
echo["echo"]
probe["detach-probe"]
read["看 / 查 / 读 / 分析 / 总结\nTier 1"]
edit["改 / 修 / 做 / 实现 / 新增\nTier 2"]
commit["提交 / commit"]
push["推送 / push"]
log["日志 / log"]
end
subgraph runtime["外部运行时"]
claude["claude -p"]
git["git"]
target["目标仓库工作区"]
state["~/.mobile-code"]
tgapi["Telegram Bot API"]
end
commands --> entry
entry --> projects
entry --> config
entry --> jobs
entry --> lock
entry --> worker
entry --> git
entry --> paths
worker --> tiers
worker --> claude
worker --> git
worker --> telegram
worker --> jobs
worker --> lock
telegram --> tgapi
projects --> target
jobs --> state
lock --> state
paths --> state
sequenceDiagram
autonumber
actor User as 用户手机
participant Hermes as Hermes Gateway
participant Foreground as mobile-code 前台进程
participant State as ~/.mobile-code
participant Worker as detached __worker
participant Git as git / 目标仓库
participant Claude as claude -p
participant Telegram as Telegram Bot API
User->>Hermes: 改 alias 项目,处理某个任务
Hermes->>Foreground: mobile-code 改 alias <task>
Foreground->>State: 记录 invocations.log
Foreground->>State: 读取 config,生成 job id,写 jobs/<job>.json
Foreground->>State: 获取 repo lock
Foreground-)Worker: spawn detached, stdio -> logs/<job>.log, unref
Foreground-->>Hermes: 已受理 job#<id>,查日志 mobile-code log <id>
Hermes-->>User: 秒回受理信息
Worker->>State: status = running, pid = worker pid
Worker->>Git: git checkout -b mobile/<job>
Worker->>Claude: claude -p --output-format json --allowedTools ...
Claude-->>Worker: JSON result / stdout / exit code
Worker->>Git: git diff --stat, git diff --name-only, ls-files --others
Worker->>State: 更新 status, endedAt, changedFiles, summary
Worker->>Telegram: sendMessage 四段式通知
Telegram-->>User: ✅ / ❌ / 超时结果
Worker->>State: release repo lock
这个两进程模型是核心设计:Hermes 的 terminal 调用只等待前台进程秒回,真正耗时的 Claude Code 任务在 detached worker 中完成,并由 worker 自己推送结果。
stateDiagram-v2
[*] --> accepted: 前台进程创建 job metadata
accepted --> running: worker 启动并更新 pid
running --> succeeded: claude exitCode = 0
running --> failed: claude 非零退出或异常
running --> timed_out: 超过 WORKER_TIMEOUT
succeeded --> notified: 推送 Telegram 成功或写失败兜底日志
failed --> notified: 推送 Telegram 成功或写失败兜底日志
timed_out --> notified: 推送 Telegram 成功或写失败兜底日志
notified --> released: 释放仓库锁
released --> [*]
每个 job 对应:
~/.mobile-code/jobs/<job>.json:结构化元数据。~/.mobile-code/logs/<job>.log:完整执行日志。mobile/<job>:目标仓库中的工作分支。~/.mobile-code/locks/<repo>.lock:运行期间的仓库互斥锁。
flowchart LR
phone["Telegram 话术"]
readonly["看 / 查 / 读 / 分析 / 总结"]
editable["改 / 修 / 做 / 实现 / 新增"]
save["提交"]
ship["推送"]
tier1["Tier 1\npermission-mode plan\n只读工具"]
tier2["Tier 2\npermission-mode acceptEdits\n可改不可提交"]
commit["git status\n git add -A\n git commit"]
push["git push\n无 upstream 时 set-upstream"]
branch["mobile/<job> 分支"]
pr["GitHub PR / 远程合并"]
phone --> readonly --> tier1 --> branch
phone --> editable --> tier2 --> branch
phone --> save --> commit --> branch
phone --> ship --> push --> pr
安全约束:
- Tier 1 只读,适合看结构、总结、分析,不允许修改文件。
- Tier 2 可编辑,但不允许 Claude 直接
git commit、git push、rm、sudo、curl、ssh。 - commit 和 push 是独立子命令,必须由用户从 Telegram 单独确认。
- 每个任务都在
mobile/<job>分支上执行,不直接改主分支。 push只推当前分支到远程;合并应在 GitHub PR 验收后完成。
| 文件 | 职责 |
|---|---|
src/cli.ts |
命令入口、前台 job 创建、detached worker 启动、commit/push/log |
src/worker.ts |
后台执行 Claude Code、开分支、收集摘要/diff/test、推 Telegram、释放锁 |
src/projects.ts |
项目别名到本地仓库路径的映射 |
src/tiers.ts |
Tier 1/Tier 2 权限档和 prompt 后缀 |
src/jobs.ts |
原子 job id、job metadata 读写 |
src/lock.ts |
每仓库锁、陈旧锁回收 |
src/telegram.ts |
Telegram Bot API 推送、代理、截断、重试、失败兜底 |
src/config.ts |
~/.mobile-code/config 解析和权限检查 |
src/paths.ts |
~/.mobile-code 运行时目录定义 |
