CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
项目概述
lemonPCRM — lemonAI 出品的 Local-First AI 个人人脉管理系统(Personal CRM)。以人为中心、以对话为链接,通过知识图谱管理微信、LinkedIn、X 等多平台社交关系,将每个联系人与其社媒动态、会议纪要、文件、照片全面关联。
AI 对话与编排层基于 ACP 协议驱动本地 Claude CLI 进程,提供单 Agent 执行和 Master → Sub-Agent 多轮编排能力。Node.js + Express,无数据库依赖(使用 Node 22.5+ 内置 node:sqlite),数据完全本地化。
常用命令
npm run setup # 首次初始化:cp .env.example .env + pnpm install
npm start # 生产模式(node server/index.js)
npm run dev # 开发模式(node --watch server/index.js,热重载)
./dev.sh # 杀掉端口占用进程 + npm run dev(推荐开发用)
无测试框架,无 lint 脚本。使用 pnpm workspaces(packageManager: pnpm@10.28.1)。
架构
技术栈
- 后端:Node.js (≥18) + Express,pnpm workspace monorepo
- 数据库:Node 22.5+ 内置
node:sqlite(DatabaseSync),位于server/db/lemon_crm.db - AI:Claude CLI(本地子进程,
--dangerously-skip-permissions自动批准) - 文件解析:mammoth(.docx)、pdf-parse(.pdf)
目录速查
| 目录 | 说明 |
|---|---|
packages/acp-core/ |
ACP 协议层:Protocol / Transport / Launcher 三层抽象 + ClaudeCliProtocol / AcpProtocol |
packages/agent-core/ |
Agent 运行时(ESM):目录驱动的 Agent、AgentBus、AgentRegistry、AgentScaffold |
server/index.js |
Express 入口(路由 + 静态前端) |
server/src/core/ |
编排引擎:orchestrator、master-session、agent-manager、session-pool、stream-executor、prompt-builder、parser、runtime-resolver |
server/src/engine/ |
进程层:run-registry、command-queue、process-guard、idle-timer、failover-error |
server/src/tools/ |
Master 工具:call-agent-tool、tool-registry、graph/(图谱 MCP 工具集) |
server/src/standalone-entry.js |
编程 API:runMasterSession / runOrchestration / runSingleAgent |
server/routes/ |
API 路由:master-chat、config、graph、wechat、import、analysis、photo |
server/services/ |
conversation-logger、file-parser、memory-service、claude-chat-service、wechat/、linkedin/、meeting/、photo/、x/ |
server/db/GraphStore.js |
本地知识图谱存储层(SQLite):Person / Organization / Project / Event / Asset 节点 + KNOWS / BELONGS_TO / PARTICIPATED 等边 |
frontend/ |
静态前端(单 HTML 文件,由 server/index.js 托管) |
server/config/backends.json |
ACP Launcher / Client 定义 |
server/config/agents.json |
静态 Agent 注册表(可选,也可由 system/agents/ 目录发现) |
API 路由
| 路径 | 说明 |
|---|---|
POST /api/master/chat |
Master Agent 多轮对话(SSE) |
POST /api/master/upload |
文件上传注入对话 |
GET /api/master/sessions |
列出活跃 session |
DELETE /api/master/sessions/:id |
关闭 session |
GET/PUT /api/config/items/:key |
读写配置文件 |
GET /api/health |
健康检查 |
GET /api/graph/nodes |
列出图谱节点(?type=Person&limit=100) |
GET /api/graph/nodes/:id |
查询单个节点(含边) |
POST /api/graph/nodes |
创建/更新节点 |
GET /api/graph/search?q=关键词 |
全文搜索 |
POST /api/graph/edges |
创建关系边 |
GET /api/graph/path?from=id&to=id |
查询关系路径 |
POST /api/wechat/import-contacts |
导入微信联系人到图谱 |
POST /api/wechat/import-chat |
导入微信聊天记录 |
GET /api/wechat/contacts?q=搜索 |
查询微信联系人 |
GET /api/wechat/sessions |
最近会话列表 |
POST /api/import/... |
多平台数据导入 |
POST /api/analysis/... |
图谱分析(关系链路、聚类等) |
POST /api/photo/... |
照片服务(人脸聚类、向量检索) |
配置文件
| 文件 | 说明 |
|---|---|
.env |
PORT(默认 3010)、HOST、CORS_ORIGINS 等 |
server/config.js |
端口、CORS、目录路径的运行时配置对象 |
server/config/backends.json |
ACP Launcher 定义(command、args、protocol) |
server/config/agents.json |
静态 Agent 注册(可选) |
关键架构模式
ACP 协议四层结构
Application (AgentManager)
↓
Protocol (ClaudeCliProtocol 直接 spawn / AcpProtocol JSON-RPC)
↓
Transport (ProcessTransport stdio / PipeTransport / WebSocketTransport)
↓
Launcher (ProcessLauncher spawn / NoneLauncher 无操作)
runtime-resolver.js 根据 backends.json + agents.json 配置自动推断使用哪一层。
ClaudeCliProtocol 调用方式:
- 生成命令:
claude --input-format stream-json --output-format stream-json --verbose --include-partial-messages --dangerously-skip-permissions - 输入格式:
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]}} - 输出:NDJSON 事件流
- 单进程跨多轮复用(session reuse)
Mock 模式:设置 LEMONBOSS_CLAUDE_MODE=mock 可读取 fixture 文件而不启动真实进程,用于调试。
Master → Sub-Agent 调度流程
- 用户消息 →
MasterSession.handleMessage() PromptBuilder组装系统提示(含工具描述 + 可用 Agent 列表)- Claude 响应中的工具调用用
[TOOL_CALL: tool_name] {...json...} [/TOOL_CALL]格式标记 ToolRegistry.parseToolCalls()解析后交给AgentManager.callAgent()SessionPool按agentName:client:deploy:workDir[:scope]为 key 复用已有 session- 工具结果注回对话,最多循环 10 轮(
SAFETY_MAX_LOOPS=15)
Orchestrator 额外提供格式自动修正(MAX_REPAIRS=5)与结果验证(ResultTracker)。
Agent 发现与记忆
- Agent 优先从
system/agents/目录发现(目录驱动),agents.json作为静态补充 - 每个 Agent 的记忆存储在其目录下的
memory/子目录,纯文件系统 AgentScaffold用于创建新 Agent 目录结构
知识图谱(GraphStore)
server/db/GraphStore.js 使用 node:sqlite(Node 22.5+ DatabaseSync),无需额外依赖。
- 节点类型:Person、Organization、Project、Event、Asset
- 边类型:KNOWS、BELONGS_TO、PARTICIPATED、CONTAINS、MENTIONED_IN、ASSOCIATED
- 分析状态:
analysis_status字段跟踪节点是否已被 AI 分析(none / pending / done) - Master 工具:
server/src/tools/graph/提供create_person、get_person、link_persons、search_graph、get_relationship_path等工具供 AI 调用
微信集成架构
server/services/wechat/ 提供从 Mac 和 Pixel 双端点与微信交互的能力:
- 发送消息(实际工作链路):
am broadcast com.hermes.wechat.SEND_MSG→HermesAccessibilityService(lsposed-wechat-sendmsg 模块内)→ 启动微信 LauncherUI → 点搜索按钮 → 搜索toUserDisplayName(必须传 nickname,如"火星人")→ 点搜索结果 → 找bkk容器内的 EditText 输入文本 → 点bql发送按钮。纯 UI 自动化,绕开所有反射 / hook 失败。 - 消息跟踪:
android-wechat-tracker-sqlcipher.js直接轮询解密后的EnMicroMsg.db(SQLCipher) - 自动回复:
auto-reply.js结合 tracker + broadcast,在 Pixel 上独立运行 - 数据导入:
wechat-importer.js/wechat-reader.js将联系人和聊天记录导入知识图谱
[!WARNING] 关于其他两条已废弃的发送路径
- LSPosed 反射 API(
HermesWeChatModule.sendTextMessageDirect):监听同一广播但走u01.r1.a → m1.a()。Send result: true是误报——builder.a()后主线程异步提交触发 null 异常被 swallow,消息不进message表。- Frida daemon 队列(
android-wechat-sender-frida.js+wechat_plain/scripts/frida-daemon/frida_daemon.js):Frida 17 + 微信 8.0.72 注入大体积 bundle 触发反调试,微信进程崩溃,已废弃。 这两条路径的命名让人误解;真正能把消息推进 message 表的只有 A11y service。[!IMPORTANT] A11y service 启用方式
enabled_accessibility_services系统设置易被关闭。检查与重新启用:adb shell "settings get secure enabled_accessibility_services" adb shell "su -c 'settings put secure enabled_accessibility_services com.hermes.wechat.xposed/com.hermes.wechat.xposed.accessibility.HermesAccessibilityService; settings put secure accessibility_enabled 1'"
详见 server/services/wechat/README.md。
注意事项
server/src/standalone-entry.js的loadConfig()优先读backends.json+agents.json,无需数据库。prompt-builder.js的getSystemStateXML()只返回时间戳(公司/OKR 层已移除)。- Agent 目录内放
SKILL.md文件会绕过协议封装,直接作为系统提示使用。 server/index.js包含控制字符净化中间件:Agent 通过 curl 发送的 JSON body 可能含原始换行符,若解析失败会自动清理\x00-\x1F控制字符后重试。
!WARNING Master Agent 必读:在
Bashtool 中使用含多重双引号的复杂命令(如curl -d '{"id":"lemonv"}')时,JSON 转义容易崩溃并陷入死循环。 解决方案:任何需要提交 JSON Payload 的操作,先写入/tmp/*.json文件,再通过curl -d @/tmp/payload.json发送。