# https://github.com/darula-hpp/memgrep 项目说明书

生成时间：2026-07-12 10:56:44 UTC

## 目录

- [项目概览](#page-1)
- [记忆引擎架构](#page-2)
- [数据摄入管线](#page-3)
- [CLI 命令参考](#page-4)
- [MCP 协议集成](#page-5)
- [Telegram 远程代理](#page-6)
- [定时任务调度器](#page-7)
- [部署、配置与故障排查](#page-8)

<a id='page-1'></a>

## 项目概览

### 相关页面

相关主题：[记忆引擎架构](#page-2), [MCP 协议集成](#page-5), [定时任务调度器](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/darula-hpp/memgrep/blob/main/README.md)
- [package.json](https://github.com/darula-hpp/memgrep/blob/main/package.json)
- [CHANGELOG.md](https://github.com/darula-hpp/memgrep/blob/main/CHANGELOG.md)
- [src/index.ts](https://github.com/darula-hpp/memgrep/blob/main/src/index.ts)
- [src/session/store.ts](https://github.com/darula-hpp/memgrep/blob/main/src/session/store.ts)
- [src/integrations/telegram.ts](https://github.com/darula-hpp/memgrep/blob/main/src/integrations/telegram.ts)
- [src/integrations/cursor.ts](https://github.com/darula-hpp/memgrep/blob/main/src/integrations/cursor.ts)
</details>

# 项目概览

`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` 在逻辑上分为三层：入口层、集成层与存储层。

```mermaid
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` 分支的当前快照，引用形式遵循"路径:行号-行号"的内部约定，便于后续校对与回溯。

---

<a id='page-2'></a>

## 记忆引擎架构

### 相关页面

相关主题：[数据摄入管线](#page-3), [CLI 命令参考](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/vector-index.ts](https://github.com/darula-hpp/memgrep/blob/main/src/vector-index.ts)
- [src/embedder.ts](https://github.com/darula-hpp/memgrep/blob/main/src/embedder.ts)
- [src/chunker.ts](https://github.com/darula-hpp/memgrep/blob/main/src/chunker.ts)
- [src/index.ts](https://github.com/darula-hpp/memgrep/blob/main/src/index.ts)
- [src/memory/store.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/store.ts)
- [src/types.ts](https://github.com/darula-hpp/memgrep/blob/main/src/types.ts)
</details>

# 记忆引擎架构

## 概述与设计目标

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]()。

## 数据流与生命周期

一次完整的"写入—检索"流程如下：

```mermaid
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 视图为准。

---

<a id='page-3'></a>

## 数据摄入管线

### 相关页面

相关主题：[记忆引擎架构](#page-2), [CLI 命令参考](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/memory/ingest.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/ingest.ts)
- [src/memory/sources/types.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/sources/types.ts)
- [src/memory/sources/cursor.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/sources/cursor.ts)
- [src/memory/sources/claude.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/sources/claude.ts)
- [src/memory/sources/kiro.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/sources/kiro.ts)
- [src/cli/commands/ingest.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/ingest.ts)
</details>

# 数据摄入管线

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]()。

## 数据流与可靠性

摄入管线的一次典型执行遵循如下流程：

1. CLI 解析命令行，传入 `--source cursor,claude` 等参数并选定存储位置 资料来源：[src/cli/commands/ingest.ts:20-70]()。
2. 协调器按源列表逐个启用适配器，收集标准化条目 资料来源：[src/memory/ingest.ts:40-100]()。
3. 去重与时间排序后，写入会话存储；写入采用临时文件 + 原子重命名，避免半写状态 资料来源：[src/memory/ingest.ts:90-140]()。
4. 返回本次摄入的计数、跳过项与错误列表给 CLI 展示 资料来源：[src/cli/commands/ingest.ts:70-110]()。

在 v1.1.0 的迭代中，这条写入路径加入了**进程守卫与会话存储加固**，使得 Telegram / Cursor 在网络抖动、IDE 重连或长时间会话下能够复用既有会话句柄，而非每次全量重读。这直接改善了用户对长任务建立历史记忆索引时的稳定性，也是社区近期反馈最集中的改进之一——对应 `ingest.ts` 与各源适配器中对会话重建与重连容忍度的强化处理。

---

<a id='page-4'></a>

## CLI 命令参考

### 相关页面

相关主题：[记忆引擎架构](#page-2), [数据摄入管线](#page-3), [MCP 协议集成](#page-5)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/program.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/program.ts)
- [src/cli.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli.ts)
- [src/cli/commands/index.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/index.ts)
- [src/cli/commands/recall.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/recall.ts)
- [src/cli/commands/list.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/list.ts)
- [src/cli/commands/show.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/show.ts)
- [src/cli/options.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/options.ts)
- [src/cli/errors.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/errors.ts)
- [src/cli/middleware/logger.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/middleware/logger.ts)
</details>

# CLI 命令参考

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]()。

```mermaid
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]()。

---

<a id='page-5'></a>

## MCP 协议集成

### 相关页面

相关主题：[CLI 命令参考](#page-4), [Telegram 远程代理](#page-6), [定时任务调度器](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/memory/mcp.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/mcp.ts)
- [src/memory/mcp-server.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/mcp-server.ts)
- [src/memory/tools.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/tools.ts)
- [src/cli/commands/serve.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/serve.ts)
- [.cursor/mcp.json](https://github.com/darula-hpp/memgrep/blob/main/.cursor/mcp.json)
- [src/memory/cursor-agent-id.ts](https://github.com/darula-hpp/memgrep/blob/main/src/memory/cursor-agent-id.ts)
</details>

# MCP 协议集成

## 概述

`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` 进程内部作为 **服务端** 监听并响应。下图展示了从客户端请求到记忆存储的完整路径：

```mermaid
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 响应| A
```

`serve.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 启动命令，例如：

```json
{
  "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/releases/tag/v1.1.0)。

---

<a id='page-6'></a>

## Telegram 远程代理

### 相关页面

相关主题：[MCP 协议集成](#page-5), [部署、配置与故障排查](#page-8)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/commands/telegram.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/telegram.ts)
- [src/telegram/bot.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/bot.ts)
- [src/telegram/api.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/api.ts)
- [src/telegram/polling.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/polling.ts)
- [src/telegram/router.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/router.ts)
- [src/telegram/allowlist.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/allowlist.ts)
</details>

# 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](https://github.com/darula-hpp/memgrep/releases/tag/v1.1.0)。

## 模块组成与职责划分

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]() |

## 数据流：从消息到结果

一次完整的「用户发消息 → 收到回复」流程如下，模块之间的依赖关系保持单向，便于单独测试和替换：

```mermaid
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 的发布说明明确指出三点改进：

1. **跨重连的会话处理**：在长轮询断线、Bot Token 失效、网络抖动等情况下，能保持 offset 连续性，并在重连后恢复到正确的拉取点。资料来源：[v1.1.0 Release Notes](https://github.com/darula-hpp/memgrep/releases/tag/v1.1.0)、资料来源：[src/telegram/polling.ts:40-100]()。
2. **原子写与存储加固**：会话存储写入采用「写临时文件 → fsync → rename」的原子写模式，避免部分写入导致的 offset 损坏；同时收紧会话文件的权限与目录模式。资料来源：[src/telegram/bot.ts:20-60]()。
3. **进程守卫**：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]()。

---

<a id='page-7'></a>

## 定时任务调度器

### 相关页面

相关主题：[MCP 协议集成](#page-5), [部署、配置与故障排查](#page-8)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/jobs/types.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/types.ts)
- [src/jobs/executor.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/executor.ts)
- [src/jobs/cursor-executor.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/cursor-executor.ts)
- [src/jobs/schedule.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/schedule.ts)
- [src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts)
- [src/cli/commands/jobs.ts](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/jobs.ts)
</details>

# 定时任务调度器

## 概述与定位

`memgrep` 的 `定时任务调度器`（位于 `src/jobs/*` 目录）是项目中负责"按计划触发后台任务"的核心子系统。它承担两类主要负载：与 Telegram 长连接会话相关的轮询/消息分发，以及与 Cursor 编辑器相关的会话快照、检索、刷新操作。这两类负载普遍是"长时间运行、断线重连后需要继续"的工作，因此 v1.1.0 的发布说明特别强调了"More resilient Telegram/Cursor session handling across reconnects and long-running chats"以及"session store hardening"，而这些加固的直接受益者正是本调度器 资料来源：[README](https://github.com/darula-hpp/memgrep/blob/main/README.md:1-1) | [src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1)。

调度器以"常驻守护进程 + 执行器插件"的方式组织：守护进程负责进程生命周期、保活与重连；具体的任务语义由 `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](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/types.ts:1-1) | [src/jobs/schedule.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/schedule.ts:1-1) | [src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1)。

## 调度循环与生命周期

调度器的核心是一个"读取计划 → 计算下次触发 → 执行 → 落盘状态"的循环。下图给出了一次典型任务（例如 Telegram 轮询或 Cursor 刷新）从注册到完成的状态流转。

```mermaid
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](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/executor.ts:1-1) | [src/jobs/cursor-executor.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/cursor-executor.ts:1-1)。

## 守护进程与可靠性保障

`src/jobs/daemon.ts` 是调度器的"运行时外壳"，主要职责包括：

- **进程守卫（process guards）**：通过文件锁确保同一时刻只有一个 memgrep 守护进程运行，避免多实例相互覆盖 session store 资料来源：[src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1)。
- **信号处理**：响应 `SIGTERM` / `SIGINT`，将进行中的任务安全地完成或回滚，避免长任务被强杀导致状态不一致 资料来源：[src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1)。
- **原子写（atomic writes）**：每次执行结果都通过临时文件 + rename 的方式落盘，避免部分写入破坏 session store，对应 v1.1.0 提及的"session store hardening" 资料来源：[src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1) | [CHANGELOG](https://github.com/darula-hpp/memgrep/blob/main/CHANGELOG.md:1-1)。

## 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](https://github.com/darula-hpp/memgrep/blob/main/src/cli/commands/jobs.ts:1-1) | [src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1)。

## 与 v1.1.0 改进的关系

v1.1.0 中提到的"Telegram/Cursor 会话处理在重连和长时间聊天中更稳健"以及"原子写入、进程守卫、session store 加固"三类内部改进，其承载体正是本调度器：

- **更稳健的会话处理**由 `daemon.ts` 的信号处理与重连退避提供；
- **原子写入**主要应用于守护进程在每次任务完成后的 session store 落盘；
- **进程守卫**则保证多终端误启动时不会出现两份互不知情的调度器相互干扰。

因此，当社区讨论"为什么 v1.1.0 之后长时间运行更稳"时，答案就在 `src/jobs/*` 这一组文件的行为契约里 资料来源：[CHANGELOG.md](https://github.com/darula-hpp/memgrep/blob/main/CHANGELOG.md:1-1) | [src/jobs/daemon.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/daemon.ts:1-1) | [src/jobs/executor.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/executor.ts:1-1)。

---

<a id='page-8'></a>

## 部署、配置与故障排查

### 相关页面

相关主题：[Telegram 远程代理](#page-6), [定时任务调度器](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/darula-hpp/memgrep/blob/main/README.md)
- [.env.example](https://github.com/darula-hpp/memgrep/blob/main/.env.example)
- [.gitignore](https://github.com/darula-hpp/memgrep/blob/main/.gitignore)
- [package.json](https://github.com/darula-hpp/memgrep/blob/main/package.json)
- [src/jobs/launchd.ts](https://github.com/darula-hpp/memgrep/blob/main/src/jobs/launchd.ts)
- [src/telegram/launchd.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/launchd.ts)
- [src/fs/atomic-write.ts](https://github.com/darula-hpp/memgrep/blob/main/src/fs/atomic-write.ts)
- [src/telegram/session-store.ts](https://github.com/darula-hpp/memgrep/blob/main/src/telegram/session-store.ts)
</details>

# 部署、配置与故障排查

本文档面向运维与开发者，介绍 `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` 字段统一管理。典型流程包括：

1. 安装依赖：`npm install`
2. 类型检查与构建：`npm run build`
3. 启动：`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 会话处理”相对应。

资料来源：[src/telegram/launchd.ts]()

### 部署流程概览

| 步骤 | 操作 | 关键文件 |
|------|------|----------|
| 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`”的模式：

1. 将数据写入同目录下的临时文件（如 `session.tmp`）。
2. 通过 `fs.rename` 原子替换目标文件。
3. 在写入前后进行 `fsync`，确保落盘。

这种模式可防止半写状态文件被守护进程重新加载。

资料来源：[src/fs/atomic-write.ts]()

### Session Store 加固

`src/telegram/session-store.ts` 是会话状态的中心化组件。v1.1.0 的“session store hardening”意味着：

- 增加文件锁，防止多进程并发写入。
- 引入校验和或版本号字段以便检测损坏。
- 在加载失败时回退到上一个有效快照。

资料来源：[src/telegram/session-store.ts]()

## 故障排查（Troubleshooting）

### 常见问题与处理

1. **Bot 无响应**
   - 检查 `.env` 中的 Token 是否正确。
   - 通过 `launchctl list | grep memgrep` 确认进程在运行。
   - 查阅 `README.md` 中的运行要求。

   资料来源：[README.md]()

2. **会话频繁重连**
   - 多由网络抖动或会话文件损坏引起。
   - 检查 `session-store` 是否生成新快照。
   - 必要时清空会话目录并重新登录。

   资料来源：[src/telegram/session-store.ts]()

3. **launchd 服务未启动**
   - 确认 plist 文件位于 `~/Library/LaunchAgents/`。
   - 查看 `launchctl load` 输出及 `/var/log/com.apple.xpc.launchd/`。
   - 重新执行 `src/jobs/launchd.ts` 中的注册流程。

   资料来源：[src/jobs/launchd.ts]()

4. **写入导致状态丢失**
   - 确认 `atomic-write` 流程未被绕过。
   - 检查磁盘空间与文件权限。

   资料来源：[src/fs/atomic-write.ts]()

### 社区反馈

v1.1.0 发布说明明确提到对“Telegram/Cursor 会话处理”的鲁棒性增强，涵盖重连与长时间聊天场景，并加入原子写入、进程守卫与会话存储加固。这些改进直接对应本节列出的故障模式，升级到 v1.1.0 通常可缓解上述问题。

资料来源：[v1.1.0 Release Notes](https://github.com/darula-hpp/memgrep/releases/tag/v1.1.0)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：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

<!-- canonical_name: darula-hpp/memgrep; human_manual_source: deepwiki_human_wiki -->
