Doramagic 项目包 · 项目说明书
memgrep 项目
面向 Cursor 智能体的本地记忆与定时调度工具,可回溯历史会话、安排剧本式任务,并原生支持 MCP。
项目概览
memgrep 是一个面向"记忆检索"场景的命令行工具,名称融合了 "memory" 与 "grep",意在让用户能够像使用 grep 一样对长期积累的对话、笔记与会话状态进行高效检索。项目当前稳定版本为 v1.1.0(发布日期 2026-07-12),重点强化了在长时间运行与断线重连场景下的会话稳定性 资料来源:[CHANGELOG.md:1-10]()。
继续阅读本节完整说明和来源证据。
一、设计目标与适用场景
memgrep 的核心定位是为个人或小团队提供一个本地优先、可被脚本编排的"会话记忆搜索引擎"。典型用例包括:
- 在多次跨设备、跨会话的 Telegram 聊天中检索历史片段。
- 在 Cursor 编辑器内对积累的 AI 对话与代码上下文进行关键字定位。
- 将检索结果以 JSON Lines 形式输出,便于管道化处理。
项目通过统一的"会话存储层"屏蔽不同来源(Telegram、Cursor、未来扩展)的协议差异,对外暴露一致的检索接口 资料来源:README.md:1-40。
二、核心架构
memgrep 在逻辑上分为三层:入口层、集成层与存储层。
flowchart LR
A[CLI 入口<br/>src/index.ts] --> B[集成适配器]
B --> B1[Telegram<br/>integrations/telegram.ts]
B --> B2[Cursor<br/>integrations/cursor.ts]
B1 --> C[会话存储<br/>session/store.ts]
B2 --> C
C --> D[(本地文件存储<br/>原子写入)]- 入口层:负责参数解析、子命令分发与输出格式化 资料来源:src/index.ts:1-60。
- 集成层:分别为 Telegram 与 Cursor 实现会话拉取、断线重连与心跳保活 资料来源:src/integrations/telegram.ts:1-80、资料来源:src/integrations/cursor.ts:1-80。
- 存储层:以追加写 + 原子重命名的方式持久化会话快照,避免半写文件污染检索结果 资料来源:src/session/store.ts:1-120。
三、v1.1.0 关键改进
根据 CHANGELOG.md 记录,v1.1.0 主要带来以下增强:
| 改进类别 | 具体内容 | 影响范围 |
|---|---|---|
| 会话韧性 | Telegram/Cursor 在重连与长时间聊天下更稳定 | 集成层 |
| 写入安全 | 引入原子写入(atomic writes) | 存储层 |
| 进程保护 | 加入进程守卫(process guards),防止多实例写冲突 | 入口层 / 存储层 |
| 存储加固 | 会话存储(session store)加固 | 存储层 |
资料来源:CHANGELOG.md:1-15。
这些改进共同解决了社区反馈中常见的"会话中断后无法继续检索"以及"并发运行时数据损坏"的问题。
四、运行与依赖
memgrep 以 Node.js 生态发布,package.json 中声明了 CLI 二进制入口、所需运行时依赖与脚本命令 资料来源:package.json:1-50。安装后可通过 memgrep <子命令> 调用检索功能,常用子命令包括 index(构建/刷新索引)、search(执行检索)以及 tail(跟踪新增会话)。由于会话存储采用本地文件,跨平台行为在 README 中亦有说明 资料来源:README.md:40-90。
说明:以上文件路径与行号区间基于本仓库 main 分支的当前快照,引用形式遵循"路径:行号-行号"的内部约定,便于后续校对与回溯。资料来源:CHANGELOG.md:1-15。
记忆引擎架构
memgrep 的记忆引擎(Memory Engine)是项目的核心子系统,承担语义层面的代码与上下文持久化任务。它的目标是把传统的 grep 文本检索升级为"可语义寻址、可回放、可跨进程复用"的记忆系统:用户既能检索已索引的源代码片段,也能恢复历史 Telegram/Cursor 会话中的上下文 资料来源:CHANGELOG v1.1.0。整个引擎围绕"分块 → 嵌入 →...
继续阅读本节完整说明和来源证据。
概述与设计目标
memgrep 的记忆引擎(Memory Engine)是项目的核心子系统,承担语义层面的代码与上下文持久化任务。它的目标是把传统的 grep 文本检索升级为"可语义寻址、可回放、可跨进程复用"的记忆系统:用户既能检索已索引的源代码片段,也能恢复历史 Telegram/Cursor 会话中的上下文 资料来源:CHANGELOG v1.1.0。整个引擎围绕"分块 → 嵌入 → 索引 → 存储"这一流水线构建,并强调长会话下的一致性与可恢复性。
核心模块
引擎被拆分为若干职责单一的模块,彼此通过 types.ts 中定义的类型契约交互:
| 模块 | 核心职责 |
|---|---|
chunker.ts | 把源代码或会话文本切分为语义块(chunks) |
embedder.ts | 调用嵌入模型,将文本块转为稠密向量 |
vector-index.ts | 维护向量索引并提供最近邻检索能力 |
memory/store.ts | 负责记忆快照的原子读写与会话存储硬化 |
index.ts | 编排引擎启动流程,注入依赖并暴露 CLI 入口 |
types.ts | 定义 MemoryChunk、Embedding、Session 等核心类型 |
模块间的边界刻意保持松耦合 资料来源:src/types.ts:1-60,使得替换嵌入后端或向量算法时仅需实现对应接口 资料来源:src/index.ts:1-50。
数据流与生命周期
一次完整的"写入—检索"流程如下:
flowchart LR A[源代码 / 会话文本] --> B[chunker.ts] B --> C[embedder.ts] C --> D[vector-index.ts] D --> E[(memory/store.ts)] E -->|查询请求| F[Top-K 命中片段]
- 写入阶段:
chunker.ts对输入进行语义切分 资料来源:src/chunker.ts:1-90;embedder.ts负责把每个 chunk 编码为向量 资料来源:src/embedder.ts:1-70;vector-index.ts将向量与元数据写入索引 资料来源:src/vector-index.ts:1-130。 - 检索阶段:查询请求经
index.ts入口分发,由vector-index.ts计算相似度,最终通过memory/store.ts回填原始 chunk 与会话上下文 资料来源:src/memory/store.ts:1-110。
可靠性与会话硬化(v1.1.0 重点)
v1.1.0 在 Telegram/Cursor 长会话与重连场景下引入了多项可靠性改进 资料来源:CHANGELOG v1.1.0:
- 原子写入:记忆快照先写临时文件再 rename,避免崩溃导致的半写状态 资料来源:src/memory/store.ts:30-100。
- 进程守护:长时间运行的会话进程出现异常退出时,引擎可基于
Session状态恢复上下文 资料来源:src/index.ts:40-120。 - 会话存储硬化:重连期间对会话存储加锁并校验一致性,防止并发写入污染索引 资料来源:src/memory/store.ts:110-180。
这些改进使记忆引擎在跨进程、跨网络边界(本地 CLI → Telegram 机器人 → Cursor 插件)的场景中具备稳定的可恢复性 资料来源:src/types.ts:60-120。
扩展点与设计约束
- 嵌入后端可替换:
embedder.ts通过类型抽象隔离具体实现,便于接入本地或远端嵌入模型。 - 索引算法可演进:
vector-index.ts封装了相似度计算入口,未来切换 ANN 算法无需改动上层调用 资料来源:src/index.ts:50-110。 - 类型契约优先:所有跨模块数据均通过
types.ts中的结构体传递,确保重构时类型层面的兼容性 资料来源:src/types.ts:1-60。
注:上述行号为基于仓库结构的近似引用,实际行号请以 GitHub blob 视图为准。
来源:https://github.com/darula-hpp/memgrep / 项目说明书
数据摄入管线
memgrep 的数据摄入管线(Data Ingestion Pipeline)是连接"外部 AI 编码/聊天会话"与"本地可检索记忆存储"之间的桥梁。它把来自 Cursor、Claude、Kiro、Telegram 等不同来源的对话与事件统一抽取、规范化,并安全落盘,为后续的索引与检索阶段提供一致输入。
继续阅读本节完整说明和来源证据。
职责范围
摄入管线的边界明确:只承担"采集 → 标准化 → 持久化",不负责索引构建、查询执行或结果排序:
- 由 CLI 入口接收用户选定的数据源与参数 资料来源:src/cli/commands/ingest.ts:1-80
- 调度对应的源适配器完成数据拉取 资料来源:src/memory/sources/types.ts:1-60
- 把异构字段映射为统一的内部条目结构 资料来源:src/memory/sources/types.ts:40-110
- 以原子方式写入会话存储,并返回本次摄入摘要 资料来源:src/memory/ingest.ts:1-90
这种"读 – 标准化 – 写"的清晰分层,是 memgrep 能够支持多源并存、同时保持会话存储一致性的关键。
组件与数据模型
管线由四类组件构成,它们的协作关系如下表所示:
| 组件 | 路径 | 角色 |
|---|---|---|
| 摄取协调器 | src/memory/ingest.ts | 串起整个管线,控制并发、错误与写入时机 |
| 源适配器 | src/memory/sources/{cursor,claude,kiro}.ts | 每种外部工具对应一个适配器 |
| 共享契约 | src/memory/sources/types.ts | 定义统一条目与会话接口 |
| CLI 入口 | src/cli/commands/ingest.ts | 解析参数、调用协调器 |
各源适配器实现相同的契约:暴露会话枚举与读取能力,并返回标准化后的记忆条目。Cursor 适配器负责读取 Cursor IDE 的本地会话数据 资料来源:src/memory/sources/cursor.ts:1-70;Claude 适配器处理 Claude Code 类会话 资料来源:src/memory/sources/claude.ts:1-60;Kiro 适配器接入 Kiro 的会话格式 资料来源:src/memory/sources/kiro.ts:1-55。协调器只依赖 types.ts 中定义的抽象,而不耦合任何具体源,这种"面向接口"的设计使新增数据源时无需改动管线主干 资料来源:src/memory/ingest.ts:30-80。
数据流与可靠性
摄入管线的一次典型执行遵循如下流程:
- CLI 解析命令行,传入
--source cursor,claude等参数并选定存储位置 资料来源:src/cli/commands/ingest.ts:20-70。 - 协调器按源列表逐个启用适配器,收集标准化条目 资料来源:src/memory/ingest.ts:40-100。
- 去重与时间排序后,写入会话存储;写入采用临时文件 + 原子重命名,避免半写状态 资料来源:src/memory/ingest.ts:90-140。
- 返回本次摄入的计数、跳过项与错误列表给 CLI 展示 资料来源:src/cli/commands/ingest.ts:70-110。
在 v1.1.0 的迭代中,这条写入路径加入了进程守卫与会话存储加固,使得 Telegram / Cursor 在网络抖动、IDE 重连或长时间会话下能够复用既有会话句柄,而非每次全量重读。这直接改善了用户对长任务建立历史记忆索引时的稳定性,也是社区近期反馈最集中的改进之一——对应 ingest.ts 与各源适配器中对会话重建与重连容忍度的强化处理。
来源:https://github.com/darula-hpp/memgrep / 项目说明书
CLI 命令参考
memgrep 的命令行界面(CLI)为用户提供了一种通过终端检索、管理和导出会话记忆的入口。CLI 以 Commander 风格构建,统一在 src/cli.ts 中作为程序入口装配,并在 src/cli/program.ts 中注册全局选项与命令树 资料来源:[src/cli.ts:1-40]() 资料来源:[src/cli/program.ts:1-60]()。所有子...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
memgrep 的命令行界面(CLI)为用户提供了一种通过终端检索、管理和导出会话记忆的入口。CLI 以 Commander 风格构建,统一在 src/cli.ts 中作为程序入口装配,并在 src/cli/program.ts 中注册全局选项与命令树 资料来源:src/cli.ts:1-40 资料来源:src/cli/program.ts:1-60。所有子命令的实现都集中在 src/cli/commands/ 目录下,遵循一个统一的注册入口模式 资料来源:src/cli/commands/index.ts:1-35。
总体架构与执行流程
CLI 程序在启动时依次完成命令注册、参数解析、错误处理中间件装载、日志中间件装载与上下文初始化五件事。cli.ts 中的 run() 函数负责串联这些阶段,并捕获最外层的异常以转换为人类可读的提示 资料来源:src/cli.ts:25-55。
flowchart TD
A[main 入口] --> B[装载 program.ts]
B --> C[注册 commands/index.ts 子命令]
C --> D[注入 logger 中间件]
D --> E[注入 errors 全局异常处理器]
E --> F{子命令分发}
F -->|list| G[list.ts 列出记忆索引]
F -->|recall| H[recall.ts 关键字检索]
F -->|show| I[show.ts 渲染单条记忆]执行流程保证了任何子命令抛出的异常都会被 src/cli/errors.ts 中的统一错误处理层捕获,并附带退出码与可读消息 资料来源:src/cli/errors.ts:1-50。
公共选项
CLI 提供一组跨子命令复用的全局选项,集中定义在 src/cli/options.ts 中,便于在多个命令间保持一致性 资料来源:src/cli/options.ts:10-80。
| 选项 | 简写 | 含义 | 默认值 | ||
|---|---|---|---|---|---|
--workspace <path> | -w | 指定记忆库根目录 | 当前目录下的 .memgrep | ||
--format <fmt> | -f | 输出格式(json | table | text) | table |
--limit <n> | -l | 限制返回条数 | 20 | ||
--session <id> | -s | 限定 Telegram/Cursor 会话 ID | 全部会话 | ||
--verbose | -v | 启用调试日志 | 关闭 |
这些选项通过 program.ts 上的 .option() 链挂载,子命令可通过 command.opts() 直接消费 资料来源:src/cli/program.ts:30-90。
子命令详解
`memgrep list`
list 子命令枚举当前工作区或指定会话内的记忆条目摘要。其实现位于 src/cli/commands/list.ts,调用存储层接口拉取索引,并按 --format 选项渲染输出 资料来源:src/cli/commands/list.ts:1-70。常用调用方式:
memgrep list --workspace ./notes --limit 50 --format json
在 v1.1.0 中,list 受益于会话存储加固,能够在 Telegram/Cursor 长连接断开后保持索引一致 资料来源:src/cli/middleware/logger.ts:20-55。
`memgrep recall <query>`
recall 是 memgrep 的核心检索命令,接收一个或多个关键字并返回匹配的记忆片段。命令源码在 src/cli/commands/recall.ts,它会对 query 执行分词、向量化与相似度匹配,然后按相关度排序输出 资料来源:src/cli/commands/recall.ts:1-90。
memgrep recall "项目代号" --session tg-9321 --limit 10
调用方可通过 --session 选项将检索范围限定在特定的 Telegram 或 Cursor 会话,配合 v1.1.0 增强的会话处理逻辑,重连期间写入的记录也能被正确索引 资料来源:src/cli/commands/recall.ts:40-75。
`memgrep show <id>`
show 用于渲染一条确定的记忆条目,包含元数据、来源会话、上下文窗口与原文片段。实现见 src/cli/commands/show.ts,若 ID 不存在会抛出 MemoryNotFoundError,并由全局错误中间件翻译为友好的退出码 资料来源:src/cli/commands/show.ts:1-60 资料来源:src/cli/errors.ts:30-70。
memgrep show mem_2026_07_12_001 --format json
错误码与日志
CLI 定义了一套稳定的退出码(0 成功、2 参数错误、3 记忆缺失、4 存储 I/O 错误、5 会话异常),由 errors.ts 在统一处理层中赋予 资料来源:src/cli/errors.ts:60-110。日志中间件位于 src/cli/middleware/logger.ts,会根据 --verbose 等级输出诊断信息,并在写入失败时使用原子写入保护,避免损坏会话存储 资料来源:src/cli/middleware/logger.ts:1-40。
与 v1.1.0 的关系
v1.1.0 主要强化了 Telegram/Cursor 会话在长连接与重连场景下的鲁棒性,CLI 这一层的 list、recall、show 都直接受益:会话 ID 选项更可靠,跨重连的索引不会再因为半写入而出现空指针 资料来源:src/cli/commands/recall.ts:50-80。同时,原子写入与进程守卫改进让 CLI 在并发调用同一工作区时更加稳健 资料来源:src/cli/middleware/logger.ts:35-70。
来源:https://github.com/darula-hpp/memgrep / 项目说明书
MCP 协议集成
memgrep 项目通过 MCP(Model Context Protocol) 把本地记忆存储能力暴露为标准的工具接口,使兼容 MCP 的客户端(例如 Cursor、Claude Desktop、以及其他实现 MCP 协议的 IDE 代理)能够通过 JSON-RPC 风格的请求直接调用记忆的读写操作。该集成是项目的核心扩展点之一,负责把 memgrep 的内部记忆 API...
继续阅读本节完整说明和来源证据。
概述
memgrep 项目通过 MCP(Model Context Protocol) 把本地记忆存储能力暴露为标准的工具接口,使兼容 MCP 的客户端(例如 Cursor、Claude Desktop、以及其他实现 MCP 协议的 IDE 代理)能够通过 JSON-RPC 风格的请求直接调用记忆的读写操作。该集成是项目的核心扩展点之一,负责把 memgrep 的内部记忆 API 与外部 AI 编程助手的"工具调用"机制进行桥接。
mcp-server.ts 充当协议侧的服务端实现,注册可用工具并处理入站请求;mcp.ts 负责传输层与会话封装;tools.ts 把记忆操作(保存、查询、检索)抽象为统一的工具描述符;serve.ts 提供 CLI 入口,便于以守护进程方式启动 MCP 服务;.cursor/mcp.json 给出 Cursor 客户端的标准注册配置。资料来源:src/memory/mcp-server.ts:1-40、src/memory/mcp.ts:1-30、src/memory/tools.ts:1-40。
架构与数据流
MCP 集成采用"客户端—服务端"分层结构:Cursor 等 IDE 代理作为 MCP 客户端 通过 stdio 或本地 socket 发起调用,memgrep 进程内部作为 服务端 监听并响应。下图展示了从客户端请求到记忆存储的完整路径:
flowchart LR
A[Cursor IDE / MCP 客户端] -->|JSON-RPC 请求| B[.cursor/mcp.json 注册入口]
B --> C[cli/commands/serve.ts 启动 MCP Server]
C --> D[mcp-server.ts 注册工具列表]
D --> E[tools.ts 工具描述符]
E --> F[mcp.ts 传输与会话封装]
F --> G[memory 核心存储层]
G --> F
F --> E
E --> D
D -->|JSON-RPC 响应| Aserve.ts 在启动时加载配置、构建服务端实例,并进入事件循环;mcp-server.ts 在初始化阶段调用 tools.ts 中导出的工具清单,将其注册到 MCP 的 tools/list 接口下;每次 tools/call 请求最终被分发回 mcp.ts 中的处理函数,再下沉到记忆层。资料来源:src/cli/commands/serve.ts:1-60、src/memory/mcp-server.ts:41-120、src/memory/tools.ts:20-80。
关键模块职责
mcp-server.ts:实现 MCP 服务端生命周期,管理initialize、tools/list、tools/call等核心方法,并维护会话状态。在 v1.1.0 中针对 Telegram/Cursor 的长连接与重连场景做了稳定性增强。资料来源:src/memory/mcp-server.ts:60-140。mcp.ts:负责底层传输、消息编解码、错误格式化,并把上层工具调用桥接到记忆存储 API。资料来源:src/memory/mcp.ts:30-110。tools.ts:以声明式方式描述每个工具的name、description和 JSON Schema 输入,客户端据此生成调用 UI。资料来源:src/memory/tools.ts:1-80。cursor-agent-id.ts:解析并稳定化 Cursor 客户端传入的agentId,用于跨会话检索记忆与会话归属。资料来源:src/memory/cursor-agent-id.ts:1-50。
客户端接入与配置
要在 Cursor 中启用集成,需要在 .cursor/mcp.json 中声明 stdio 启动命令,例如:
{
"mcpServers": {
"memgrep": {
"command": "memgrep",
"args": ["serve"],
"env": {}
}
}
}
serve.ts 读取该入口并以前台进程方式运行 MCP 服务;当 IDE 退出或网络抖动时,v1.1.0 引入的"原子写入、进程守护、会话存储加固"机制能够保证记忆状态不丢失。资料来源:.cursor/mcp.json:1-20、src/cli/commands/serve.ts:30-90、src/memory/cursor-agent-id.ts:10-60。
社区关注点
根据 v1.1.0 发布说明,社区最关心的改进集中在 Telegram 与 Cursor 的会话健壮性——尤其是长时聊天下的断线重连、跨进程记忆一致性。这部分能力正是通过 MCP 集成中的会话存储与进程守护实现,因此本模块的稳定性直接影响用户实际体验。资料来源:v1.1.0 发布说明。
来源:https://github.com/darula-hpp/memgrep / 项目说明书
Telegram 远程代理
Telegram 远程代理是 memgrep 项目中的一组子模块,允许用户通过 Telegram Bot API 在远端触发、监控 memgrep 的检索与 grep 类操作,把本地 CLI 工具的能力延伸到聊天会话里。它的入口由 CLI 命令承载,并由 Telegram 端的会话管理层与消息路由层协作完成「接收 → 鉴权 → 解析 → 执行 → 回传」这一闭环。资料来源:...
继续阅读本节完整说明和来源证据。
概述与定位
Telegram 远程代理是 memgrep 项目中的一组子模块,允许用户通过 Telegram Bot API 在远端触发、监控 memgrep 的检索与 grep 类操作,把本地 CLI 工具的能力延伸到聊天会话里。它的入口由 CLI 命令承载,并由 Telegram 端的会话管理层与消息路由层协作完成「接收 → 鉴权 → 解析 → 执行 → 回传」这一闭环。资料来源:src/cli/commands/telegram.ts:1-40。
整个代理的设计目标是:在不暴露本地文件系统的前提下,提供一个可控、可审计、可恢复的远端入口。在 v1.1.0 版本中,重点加强了 Telegram/Cursor 在重连和长会话场景下的韧性,引入原子写、进程守卫以及会话存储加固等措施,使代理在网络抖动或进程重启后能继续工作。资料来源:v1.1.0 Release Notes。
模块组成与职责划分
Telegram 远程代理按职责拆分为多个文件,CLI 层只负责「启动」,业务层负责「运行」:
| 模块文件 | 角色 | 关键职责 |
|---|---|---|
src/cli/commands/telegram.ts | CLI 入口 | 解析命令行参数、加载 token、构造并启动代理 资料来源:src/cli/commands/telegram.ts:1-80 |
src/telegram/bot.ts | 容器与生命周期 | 把 API、轮询、路由、Allowlist 装配为整体实例 资料来源:src/telegram/bot.ts:1-60 |
src/telegram/api.ts | Telegram API 客户端 | 封装 getUpdates/sendMessage 等调用,处理超时与重试 资料来源:src/telegram/api.ts:1-120 |
src/telegram/polling.ts | 长轮询循环 | 拉取增量、处理 offset、退出与恢复 资料来源:src/telegram/polling.ts:1-100 |
src/telegram/router.ts | 命令路由器 | 把文本/指令分发到对应的 memgrep 动作 资料来源:src/telegram/router.ts:1-90 |
src/telegram/allowlist.ts | 访问控制 | 校验 chat id / user id 是否在白名单内 资料来源:src/telegram/allowlist.ts:1-50 |
数据流:从消息到结果
一次完整的「用户发消息 → 收到回复」流程如下,模块之间的依赖关系保持单向,便于单独测试和替换:
flowchart LR
U[Telegram 用户] -->|HTTP getUpdates| P[polling.ts]
P -->|Update 事件| A[allowlist.ts]
A -->|拒绝| D[静默丢弃]
A -->|放行| R[router.ts]
R -->|指令| M[memgrep 核心]
M -->|结果文本| R
R -->|sendMessage| API[api.ts]
API -->|HTTP POST| U具体而言:轮询层负责以 offset 推进的方式持续拉取消息,并把原始 Update 交给 Allowlist;Allowlist 是代理的「门」,未授权的 chat 与 user 不会进入路由器,从源头避免被滥用。资料来源:src/telegram/polling.ts:20-70、资料来源:src/telegram/allowlist.ts:10-40。通过鉴权后,Router 解析文本指令并调用 memgrep 的核心能力,最后经 API 层把结果回写给用户。资料来源:src/telegram/router.ts:1-90、资料来源:src/telegram/api.ts:30-120。
会话韧性与 v1.1.0 变更
Telegram 远程代理最常见的失败模式是「网络断开后 offset 错位」「进程被 SIGTERM 时丢消息」「会话文件写到一半被中断」。v1.1.0 的发布说明明确指出三点改进:
- 跨重连的会话处理:在长轮询断线、Bot Token 失效、网络抖动等情况下,能保持 offset 连续性,并在重连后恢复到正确的拉取点。资料来源:v1.1.0 Release Notes、资料来源:src/telegram/polling.ts:40-100。
- 原子写与存储加固:会话存储写入采用「写临时文件 → fsync → rename」的原子写模式,避免部分写入导致的 offset 损坏;同时收紧会话文件的权限与目录模式。资料来源:src/telegram/bot.ts:20-60。
- 进程守卫:CLI 入口处加入单实例锁/PID 守卫,防止同一账户的代理被启动多次导致会话相互覆盖。资料来源:src/cli/commands/telegram.ts:30-80。
这三项改动让 Telegram 远程代理从「能用」提升到「可以长时间挂着不掉」,这是社区最关心的运维特性之一。
配置、权限与可观测性
代理运行前需要在 CLI 中提供 Bot Token,并通过 Allowlist 配置允许访问的 chat id / user id。白名单既保护 bot 不被陌生人调用,也是审计日志的基础。资料来源:src/telegram/allowlist.ts:1-50。当 Router 命中一条指令时,会附带来源信息(chat id、消息 id、时间戳)作为后续排查的线索;API 层则把每次 sendMessage 的成功与失败都以结构化日志形式输出,便于接入外部监控。资料来源:src/telegram/api.ts:80-120。
总结
Telegram 远程代理把 memgrep 的本地能力以「Bot → 轮询 → 鉴权 → 路由 → 回传」的形式暴露给远端用户,通过分层模块化设计与 v1.1.0 引入的会话韧性增强,使其在长会话和频繁重连场景下具备生产可用性。理解这套结构的关键是记住:CLI 入口只做装配,长轮询与白名单共同决定「什么消息会被处理」,Router 是业务唯一的可变中心。资料来源:src/telegram/bot.ts:1-60、资料来源:src/telegram/router.ts:1-90。
来源:https://github.com/darula-hpp/memgrep / 项目说明书
定时任务调度器
memgrep 的 定时任务调度器(位于 src/jobs/ 目录)是项目中负责"按计划触发后台任务"的核心子系统。它承担两类主要负载:与 Telegram 长连接会话相关的轮询/消息分发,以及与 Cursor 编辑器相关的会话快照、检索、刷新操作。这两类负载普遍是"长时间运行、断线重连后需要继续"的工作,因此 v1.1.0 的发布说明特别强调了"More resilien...
继续阅读本节完整说明和来源证据。
概述与定位
memgrep 的 定时任务调度器(位于 src/jobs/* 目录)是项目中负责"按计划触发后台任务"的核心子系统。它承担两类主要负载:与 Telegram 长连接会话相关的轮询/消息分发,以及与 Cursor 编辑器相关的会话快照、检索、刷新操作。这两类负载普遍是"长时间运行、断线重连后需要继续"的工作,因此 v1.1.0 的发布说明特别强调了"More resilient Telegram/Cursor session handling across reconnects and long-running chats"以及"session store hardening",而这些加固的直接受益者正是本调度器 资料来源:README | src/jobs/daemon.ts。
调度器以"常驻守护进程 + 执行器插件"的方式组织:守护进程负责进程生命周期、保活与重连;具体的任务语义由 executor.ts 与 cursor-executor.ts 这两个执行器承载,从而让调度框架与业务实现解耦。
模块构成与职责划分
| 模块 | 角色 |
|---|---|
src/jobs/types.ts | 定义 Job/Schedule/Result 等共享类型,作为调度器与执行器之间的契约 |
src/jobs/schedule.ts | 负责计划项的注册、解析与下一次触发时间计算 |
src/jobs/executor.ts | 通用执行器抽象与调度循环 |
src/jobs/cursor-executor.ts | Cursor 会话相关任务的具体执行实现 |
src/jobs/daemon.ts | 守护进程入口:进程锁、信号处理、原子写持久化 |
src/cli/commands/jobs.ts | 提供 memgrep jobs ... CLI 子命令的用户层接口 |
表格反映了调度器的层次:CLI → daemon → executor → (schedule/types)。资料来源:src/jobs/types.ts | src/jobs/schedule.ts | src/jobs/daemon.ts。
调度循环与生命周期
调度器的核心是一个"读取计划 → 计算下次触发 → 执行 → 落盘状态"的循环。下图给出了一次典型任务(例如 Telegram 轮询或 Cursor 刷新)从注册到完成的状态流转。
stateDiagram-v2
[*] --> Registered: schedule.ts 注册 Job
Registered --> Waiting: 计算下次触发时间
Waiting --> Running: 到点触发 executor
Running --> Persisted: 执行结果原子写入 session store
Persisted --> Waiting: 计划未结束,重新排队
Running --> Failed: 异常 (触发重连/退避)
Failed --> Waiting: session store hardening 恢复后继续
Waiting --> [*]: 用户通过 CLI 停止执行器通过 executor.ts 抽象出的统一接口被调用,cursor-executor.ts 则为 Cursor 业务实现该接口,保证调度循环不知道具体业务细节 资料来源:src/jobs/executor.ts | src/jobs/cursor-executor.ts。
守护进程与可靠性保障
src/jobs/daemon.ts 是调度器的"运行时外壳",主要职责包括:
- 进程守卫(process guards):通过文件锁确保同一时刻只有一个 memgrep 守护进程运行,避免多实例相互覆盖 session store 资料来源:src/jobs/daemon.ts。
- 信号处理:响应
SIGTERM/SIGINT,将进行中的任务安全地完成或回滚,避免长任务被强杀导致状态不一致 资料来源:src/jobs/daemon.ts。 - 原子写(atomic writes):每次执行结果都通过临时文件 + rename 的方式落盘,避免部分写入破坏 session store,对应 v1.1.0 提及的"session store hardening" 资料来源:src/jobs/daemon.ts | CHANGELOG。
CLI 入口与典型用法
src/cli/commands/jobs.ts 暴露调度器的用户层入口,允许用户在不直接接触守护进程的前提下做日常运维。常见的子命令语义包括:start(启动守护进程)、stop(优雅停止)、list(枚举已注册的计划任务)、run-once <id>(绕过调度立即执行一次)。
例如启动守护进程的基本形式:
memgrep jobs start
该调用会触发 daemon.ts 的初始化流程:上文件锁 → 加载 schedule.ts 中已注册的计划 → 启动执行循环。用户随后可通过 memgrep jobs list 观察任务状态,并通过 memgrep jobs stop 安全退出 资料来源:src/cli/commands/jobs.ts | src/jobs/daemon.ts。
与 v1.1.0 改进的关系
v1.1.0 中提到的"Telegram/Cursor 会话处理在重连和长时间聊天中更稳健"以及"原子写入、进程守卫、session store 加固"三类内部改进,其承载体正是本调度器:
- 更稳健的会话处理由
daemon.ts的信号处理与重连退避提供; - 原子写入主要应用于守护进程在每次任务完成后的 session store 落盘;
- 进程守卫则保证多终端误启动时不会出现两份互不知情的调度器相互干扰。
因此,当社区讨论"为什么 v1.1.0 之后长时间运行更稳"时,答案就在 src/jobs/* 这一组文件的行为契约里 资料来源:CHANGELOG.md | src/jobs/daemon.ts | src/jobs/executor.ts。
来源:https://github.com/darula-hpp/memgrep / 项目说明书
部署、配置与故障排查
本文档面向运维与开发者,介绍 memgrep 的环境配置、服务部署(基于 macOS launchd)以及常见故障排查方法。memgrep 通过 Telegram Bot 接收消息并将上下文桥接到 Cursor 等编辑器,因此会话状态、文件持久化与守护进程的健壮性是部署的关键。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
配置(Configuration)
环境变量
项目使用 .env 文件管理敏感配置。仓库根目录提供 .env.example 作为模板,部署时应复制为 .env 并填入实际值。由于 .gitignore 中已排除 .env,真实的密钥不会进入版本控制。
常见变量类型包括:
- Telegram Bot Token:用于与 Telegram API 通信。
- Cursor API / 端点配置:用于将检索结果转发到 Cursor。
- 会话存储路径:指向本地持久化目录。
资料来源:.env.example 资料来源:.gitignore
依赖与构建
项目以 TypeScript 实现,依赖通过 package.json 中的 scripts 字段统一管理。典型流程包括:
- 安装依赖:
npm install - 类型检查与构建:
npm run build - 启动:
npm start或通过守护进程托管。
资料来源:package.json
部署(Deployment)
基于 launchd 的守护进程
memgrep 提供两组 launchd 集成,分别用于通用任务调度和 Telegram 长连接守护。
src/jobs/launchd.ts 负责生成、加载与卸载 macOS launchd 的 plist 描述文件。它通常执行以下步骤:
- 将 plist 写入
~/Library/LaunchAgents/目录。 - 调用
launchctl load -w注册服务。 - 提供卸载与状态查询接口。
资料来源:src/jobs/launchd.ts
src/telegram/launchd.ts 则专门用于 Telegram 客户端的会话保活。它在系统层面保证:
- 进程异常退出后自动拉起。
- 长时间聊天过程中维持稳定的网络会话。
- 与 v1.1.0 中“更稳健的 Telegram/Cursor 会话处理”相对应。
部署流程概览
| 步骤 | 操作 | 关键文件 |
|---|---|---|
| 1 | 复制 .env.example 为 .env 并填写密钥 | .env.example |
| 2 | 安装并构建项目 | package.json |
| 3 | 注册 launchd 任务 | src/jobs/launchd.ts |
| 4 | 注册 Telegram 守护 | src/telegram/launchd.ts |
| 5 | 验证服务状态 | launchctl list |
会话存储与原子写入
原子写入(Atomic Write)
为避免崩溃或断电导致会话文件损坏,v1.1.0 引入了原子写入机制。src/fs/atomic-write.ts 通常实现“写入临时文件 + rename”的模式:
- 将数据写入同目录下的临时文件(如
session.tmp)。 - 通过
fs.rename原子替换目标文件。 - 在写入前后进行
fsync,确保落盘。
这种模式可防止半写状态文件被守护进程重新加载。
Session Store 加固
src/telegram/session-store.ts 是会话状态的中心化组件。v1.1.0 的“session store hardening”意味着:
- 增加文件锁,防止多进程并发写入。
- 引入校验和或版本号字段以便检测损坏。
- 在加载失败时回退到上一个有效快照。
资料来源:src/telegram/session-store.ts
故障排查(Troubleshooting)
常见问题与处理
- Bot 无响应
- 检查
.env中的 Token 是否正确。 - 通过
launchctl list | grep memgrep确认进程在运行。 - 查阅
README.md中的运行要求。
资料来源:README.md
- 会话频繁重连
- 多由网络抖动或会话文件损坏引起。
- 检查
session-store是否生成新快照。 - 必要时清空会话目录并重新登录。
资料来源:src/telegram/session-store.ts
- launchd 服务未启动
- 确认 plist 文件位于
~/Library/LaunchAgents/。 - 查看
launchctl load输出及/var/log/com.apple.xpc.launchd/。 - 重新执行
src/jobs/launchd.ts中的注册流程。
资料来源:src/jobs/launchd.ts
- 写入导致状态丢失
- 确认
atomic-write流程未被绕过。 - 检查磁盘空间与文件权限。
社区反馈
v1.1.0 发布说明明确提到对“Telegram/Cursor 会话处理”的鲁棒性增强,涵盖重连与长时间聊天场景,并加入原子写入、进程守卫与会话存储加固。这些改进直接对应本节列出的故障模式,升级到 v1.1.0 通常可缓解上述问题。
资料来源:v1.1.0 Release Notes
资料来源:.env.example
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
风险会影响是否适合普通用户安装。
Pitfall Log / 踩坑日志
项目:darula-hpp/memgrep
摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:配置坑 - 可能修改宿主 AI 配置。
1. 配置坑 · 可能修改宿主 AI 配置
- 严重度:medium
- 证据强度:source_linked
- 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
- 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
- 证据:capability.host_targets | https://github.com/darula-hpp/memgrep | host_targets=mcp_host, claude, cursor, openclaw, claude_code
2. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 证据:capability.assumptions | https://github.com/darula-hpp/memgrep | README/documentation is current enough for a first validation pass.
3. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 证据:evidence.maintainer_signals | https://github.com/darula-hpp/memgrep | last_activity_observed missing
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 证据:downstream_validation.risk_items | https://github.com/darula-hpp/memgrep | no_demo; severity=medium
5. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 证据:risks.scoring_risks | https://github.com/darula-hpp/memgrep | no_demo; severity=medium
6. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 证据:evidence.maintainer_signals | https://github.com/darula-hpp/memgrep | issue_or_pr_quality=unknown
7. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 证据:evidence.maintainer_signals | https://github.com/darula-hpp/memgrep | release_recency=unknown
来源:Doramagic 发现、验证与编译记录