memU Cursor 桥接任务完整指南:用定时 headlesscursor-agent将 Cursor 会话沉淀为记忆、技能与资源
【免费下载链接】memUPersonal memory across agents项目地址: https://gitcode.com/GitHub_Trending/mem/memU
本文是 memU 项目 Cursor 宿主适配器中「桥接任务」(bridging task)的完整技术指南。该任务是一个周期性的无头(headless)cursor-agent运行,按「prepare → self-evolve → commit」三步流水线,把用户在 Cursor Agent 会话中做的工作自动沉淀为 memU 的 memory 文件、skill 与资源提交。读完本文,你将掌握如何在 Unix(cron/launchd)与 Windows(Task Scheduler)上注册、验证并维护这条定时流水线,理解为什么 pipeline 提示词必须放在文件中而非 crontab 命令行里、为什么--trust是硬性要求、以及如何通过文件系统痕迹而非运行自述来确认任务真正生效。
本文主体基于仓库中的 Cursor 桥接任务文档,并结合其配套源码(Cursor 适配器 CLI、桥接流水线实现、Windows 调度后端 等)逐层展开。
任务身份:这篇文档是给谁看的
BRIDGING_TASK.md的 frontmatter 定义了任务身份:
- 当前任务名:
{{task_name}}(渲染后即memu-bridging-cursor,见 cli.py 中的 HostSpec) - 历史任务名:
{{former_task_names}} - 迁移与移除时需识别的全部名字:
{{all_task_names}}
这些{{token}}是受控渲染变量,由 host_cli.py 的render_doc在打印文档时注入,因此注册代码与文档文案不会各自漂移。当用户要求「设置(或修改)周期性 memU 桥接任务」时,Agent 应读取并遵循本文档——注意:你的目标是注册一个周期性无头 Cursor Agent 运行,而不是现在立即执行这条流水线。该文档既是INSTALL.md(memu-cursor docs install)完整安装流程的一部分,也可独立单独使用(memu-cursor docs task直接打印)。
一个需要提前说明的能力边界:memory 与 skill 在本地与云两种模式下都是持久的;在云模式下,当前服务会接收这条流水线提交的 workspace 资源,但暂时不会持久化或检索它们。
桥接任务做什么:prepare → self-evolve → commit 三步流水线
桥接任务在每次调度触发时执行三段式流水线:
- Prepare(代码)——
memu-cursor prepare扫描 Cursor Agent 会话中的新 turns,把当前 memU 的 recall 文件镜像到~/.memu/hosts/cursor/memory与~/.memu/hosts/cursor/skill,按内容哈希生成快照,并写出编号的任务指令文件到~/.memu/hosts/cursor/jobs/(1.txt、2.txt、…)。 - Self-evolve(真正的 Agent 工作)—— Agent 按数字升序逐个打开每个 job 文件并照做:把一个会话挖掘成用户memory、把一个会话挖掘成skill、描述会话触碰过的文件。任何 job 产出「什么也不做」都是允许且常见的结果。
- Commit(代码)——
memu-cursor commit将受追踪目录与第 1 步快照做 diff,把 Agent 实际创建或修改的内容提交回 memU。
只有步骤 1 和 3 是代码。步骤 2 是真正的 Agent 工作,因此定时运行的提示词必须指示 Agent 亲自去执行它,而不是用脚本外包掉。
从源码看,这条「记录缝」(record seam)的核心实现在 bridging/pipeline.py:prepare的返回值语义很明确——返回已准备的会话数,0 是正确且常见的结果(一个没有新会话的定时运行本来就无事可做)。prepare内部依次完成:切片新会话(prepare_transcripts)、按 keyset 分页镜像存储中的 recall 文件(ADR 0014)、在首次运行时引导内容快照、清理上次的 touched-file 日志、拉取任务模板并生成 job 文件,最后在num_sessions > 0时追加一个资源描述 job(编号2 * num_sessions + 1,见 pipeline.py#L128-L135)。
前置条件:两条硬性门槛
注册调度前必须满足:
- memU 已安装且
memu-cursor在PATH上。用memu-cursor doctor验证;若失败,先完成 INSTALL.md 的 Part 1。 cursor-agent能以无头方式运行。调度条目会用cursor-agent -p非交互式调用它,并允许其运行memu-cursor及在~/.memu/下写文件。Cursor IDE 并不提供这个二进制——PATH上的cursor启动器只是 GUI 打开器,不是 Agent CLI(这一点在 INSTALL.md Part 2.0 中有大量字段级证据:cursor -p只会得到 "Warning: 'p' is not in the list of known options")。cursor-agent是独立安装,INSTALL.mdPart 2.0 的「安装 + 裸环境验证」流程必须先通过。
注意cursor-agent在 Windows 安装后还有一个「陈旧环境」陷阱:原生安装器会把 CLI 放进%LOCALAPPDATA%\cursor-agent并写入注册表用户PATH,但所有在安装前启动的进程(Cursor IDE、它的集成终端、你的 shell)都保留启动时的环境,因此cursor-agent在这些会话里仍然 not-found——判断是否安装应以安装目录为准,而非某个安装前 shell 的PATH。
Step 1 — 敲定调度节奏
如果用户请求里没有指定调度,先询问用户。默认是每小时一次,cron 表达式0 * * * *(本地时区)。创建前必须与用户确认。
Step 2 — 注册定时运行(Unix:cron / launchd)
为什么绝不能把 pipeline 提示词内联进 crontab
这是整篇指南最重要的一条纪律:pipeline 提示词约 1.2 KB,而 cron 在把 crontab 行交给/bin/sh前会在约 1 KB 处截断——shell 收到的是一条引号被腰斩的命令,于是每次触发都瞬间死亡,报错unexpected EOF while looking for matching "'"只会被投递到/var/mail/$USER,除邮箱外无处可见,cursor-agent根本不会启动。这是 Windowsschtasks /TR长度限制(memU#539)的 Unix 同胞问题,修复思路相同:提示词住在文件里,crontab 行保持简短。
写出 bridge-prompt.txt
把 pipeline 提示词写入~/.memu/hosts/cursor/bridge-prompt.txt,逐字单行,内容如下(这是文档给出的 verbatim 原文):
Run the memU bridging pipeline. Do the four steps strictly in order; do not skip a step even if the previous one looks like it produced nothing. 1. LEFTOVERS. If ~/.memu/hosts/cursor/jobs/ already contains job files, they are unfinished work from an earlier run (a crash, or the install itself) — process them exactly as step 3 describes, then run: memu-cursor commit — and only then continue. 2. PREPARE. Run this exact command with bash: memu-cursor prepare — it regenerates ~/.memu/hosts/cursor/jobs/. If the command exits non-zero, stop and report the error. 3. SELF-EVOLVE. List ~/.memu/hosts/cursor/jobs/*.txt and process them in ascending numeric order (1.txt, then 2.txt, …). The count changes every run — always glob and sort. If there are no job files, skip to step 4. For each job file: read it and follow its instructions to the letter. Each job is self-contained and already carries the concrete paths it needs. Emitting no files for a job is a valid outcome; do not invent content. 4. COMMIT. Run this exact command with bash: memu-cursor commit — it commits whatever the jobs created or changed. If it exits non-zero, report the error. ON FAILURE. If step 2 or step 4 exited non-zero, run this once before you stop: memu-cursor report error --stage remember --detail "<a full account of what went wrong>" — that detail is all a memU engineer gets to work out what is broken on this machine, so be generous: which step, what you ran, what happened instead, what you already tried, and what you think the cause is. Write it as prose for a human, not as a transcript — do not paste the traceback or raw command output, which the CLI already reports on its own, and keep credentials, absolute paths, and memory or transcript text out of it. Ignore any failure of that command; it is never part of the run. Finish with a one-line summary: how many jobs ran (leftovers included) and what was committed.这段提示词的机器无关性在源码中被刻意保证:它不是手写字符串,而是由 scheduling/prompt.py 的bridging_pipeline_prompt按HostSpec(工作树 + 二进制名)参数化生成,同一份文本服务所有宿主;tests/test_scheduling_windows.py中还有断言保证它与你看到的这份文档提示词块完全一致。
提示词里值得注意的执行细节:
- LEFTOVERS 优先:jobs/ 里已有的 job 文件是更早一次运行(崩溃或安装本身)未完成的工作,必须先按步骤 3 处理并
commit,然后才继续——因为prepare会删除未处理的 job 文件,错过即永久丢失。 - 四步严格按序,即使前一步看起来什么都没产出也不许跳步。
- SELF-EVOLVE 必须 glob + 排序:job 数量每次运行都会变,永远按
1.txt, 2.txt, …升序处理。 - 失败只归责于步骤 2 和 4:步骤 2 或 4 非零退出时,用
memu-cursor report error --stage remember上报一次,--detail要写成给人类工程师读的散文(哪个步骤、你跑了什么、实际发生了什么、试过什么、你认为的成因),禁止粘贴 traceback 或原始命令输出(CLI 自己会报),也禁止包含凭据、绝对路径、memory 或 transcript 文本。
写出 bridge.sh 包装脚本并加执行权限
第二步是写~/.memu/hosts/cursor/bridge.sh并chmod +x。注意其中**--trust标志与cd进宿主工作树**:cursor-agent拒绝在不受信任的目录里做无头运行("Workspace Trust Required",退出码 1,Windows 上字段级验证于 memU#571,且这堵墙就在无头运行本身,所以 cron 同样受制)。信任落在 memU 自己的工作树上,绝不落在 cron 碰巧启动的目录上。永远不要用--yolo——那正是本指南拒绝的全量权限跳过开关:
#!/bin/sh # memU bridging for Cursor — invoked by cron. # The pipeline prompt lives in bridge-prompt.txt because cron truncates # crontab lines around 1 KB (see BRIDGING_TASK.md). DIR="$HOME/.memu/hosts/cursor" # Single-instance lock: an hourly tick can fire while a long backlog run is # still going; a second run would race it on jobs/ and double-commit. # mkdir is atomic; a stale lock older than 3h is reclaimed. Tradeoff: a # legitimate run longer than 3h loses its lock to the next tick and can # double-run — accepted deliberately, because the alternative (no reclaim) # lets one crashed run wedge the schedule forever. Do not "fix" one side # without weighing the other. LOCK="$DIR/.bridge.lock" if ! mkdir "$LOCK" 2>/dev/null; then if [ -n "$(find "$LOCK" -maxdepth 0 -mmin +180 2>/dev/null)" ]; then rmdir "$LOCK" 2>/dev/null mkdir "$LOCK" 2>/dev/null || exit 0 else echo "$(date '+%F %T') skipped: another bridging run is in progress" >> "$DIR/bridge.log" exit 0 fi fi trap 'rmdir "$LOCK" 2>/dev/null' EXIT INT TERM # Marks this invocation as the scheduled bridging run. The Cursor Agent # supplies CURSOR_CONVERSATION_ID inside its shell tools; prepare combines # the two signals to skip this run's own transcript. export MEMU_BRIDGING_RUN=1 # --trust scopes workspace trust to $DIR (memU's own tree), which is also # the working directory — headless cursor-agent dies without it. cd "$DIR" || exit 1 cursor-agent --trust -p "$(cat "$DIR/bridge-prompt.txt")" >> "$DIR/bridge.log" 2>&1脚本里的两个机制都值得展开:
- 单实例锁:
mkdir是原子操作;超过 3 小时的陈旧锁会被回收。这是刻意接受的取舍——超过 3 小时的合法长跑会输给下一个 tick 而可能双跑,但相反方案(不回收)会让一次崩溃的运行把调度永久卡死。文档明确告诫:不要只修一侧而不权衡另一侧。 MEMU_BRIDGING_RUN=1标记:它让这次调用被识别为「定时桥接运行」。其机制在 bridging/self_sessions.py 有完整实现与说明:桥接运行本身也是宿主 Agent 的一次会话,会被记进 memU 正在扫描的同一位置,若不排除就会形成循环——每次运行都给下次运行喂「新内容」、prepare永远报不了 0,而且 memU 自己的记账会话是磁盘上最新的 transcript,会排到最前、抢走真实对话的max_jobs名额(issue #606)。prepare只有在is_bridging_run判定成立时才认领当前会话;MEMU_BRIDGING_RUN环境变量和「cwd == 工作树」任一信号都足以判定(self_sessions.py#L51-L72),并且失败方向是安全的:无法识别就视为「人手动运行」,什么都不跳过。Cursor 侧的身份变量是CURSOR_CONVERSATION_ID(cli.py#L26),它同时是 transcript 目录与 JSONL 文件名,CursorTranscriptSource 用文件名 stem 把两侧精确映射;tests/test_cursor_self_sessions.py 验证了只有被标记的 OS 调度运行才会认领自己的会话。
crontab 第一行必须是 PATH
cron 以极简的/usr/bin:/bin运行;流水线需要的二进制(pipx 与 npm 安装会落在~/.local/bin与/opt/homebrew/bin)都不在其中,运行会在流水线开始前就死在command not found。注册时推导并在条目上方写入:
PATH=$(dirname "$(command -v memu-cursor)"):$(dirname "$(command -v cursor-agent)"):/usr/local/bin:/usr/bin:/bin机器相关的事实放在 crontab 里(机器事实就该在机器处),pipeline 提示词本身保持逐字住在自己的文件里。这行PATH是注册期推导、写死在 crontab 中的,INSTALL.md里那句env -i …探测命令(env -i HOME="$HOME" PATH="$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin" cursor-agent -p 'ping')只是安装前对常见安装位置的探测,不能替代这条注册期PATH行。
cron 条目
然后写入 cron 条目——默认即可(macOS 同样用 cron,仅当用户明确要求时才用 launchd,此时把 Label 设为{{task_name}})。cron 在命令字段不展开~,但会用/bin/sh执行该行,所以$HOME可用;写绝对路径同样没问题:
0 * * * * $HOME/.memu/hosts/cursor/bridge.sh # {{task_name}}提示词块是固定的,只有 cron 表达式是用户的选择;没有任何机器相关内容泄漏进提示词——流水线全部经由PATH命令调用。附带收益:这次运行的输出落进~/.memu/hosts/cursor/bridge.log(内联条目会把它丢弃),失败的一次 tick 由此留下可诊断的痕迹,而不是只有一封 cron 邮件。
Step 3 — 确认调度真正生效
你 shell 的PATH证明不了调度器的PATH。两个算数的检查:
env -i PATH=/usr/bin:/bin /bin/sh -c 'command -v memu-cursor'——这条命令失败恰恰说明条目为什么需要 PATH 行;有了 PATH 行,命令必须能从其命名的目录解析出来。- 硬检查:通过 cron 本身触发一次运行(临时把调度提前一分钟,或手工跑
bridge.sh:env -i PATH=... HOME="$HOME" /bin/sh -c),然后验证文件系统痕迹——会话游标与jobs/的时间戳是否前移、~/.memu/hosts/cursor/bridge.log是否增长——而不要相信运行自身的摘要。这是两份字段数据的结论:裸环境中的定时运行曾出现过在command not found的情况下仍报告 "completed successfully"。
向用户回报:调度注册在哪里、cron 用语言怎么描述。并说明:第一次运行要等到上一次运行之后出现新的 Cursor Agent 会话才有活可干。
Windows(Task Scheduler)专用路径
步骤 2–3 是 cron/launchd,仅限 Unix。在 Windows 上不要手写schtasks条目:pipeline 提示词约 1000 个带引号的字符,schtasks /TR会在第一个空格处把它劈开(memU#539);裸调度进程解析与鉴权的方式也和你 shell 不同(memU#538)。改用辅助命令——每次安装完全一致,按名字可移除:
memu-cursor schedule install # register the hourly task memu-cursor schedule verify # prove it resolves + authenticates memu-cursor schedule status # last run / next run memu-cursor schedule uninstall # remove itinstall会把提示词写入文件、生成一个读取它的小型 PowerShell 包装器(任何长文本都不触碰命令行),把cursor-agent的绝对路径烧进去,并以S4U主体注册名为{{task_name}}的任务——无窗口、无论你是否登录都运行、机器关机时错过的运行会在开机后补跑。--interval <minutes>改变节奏(默认 60)。
这条路径的底层实现是 scheduling/windows.py(memu-cursor schedule子命令在 host_cli.py#L701-L727 分发,且只在schedule_command配置了调用模板的宿主上出现)。值得了解的工程细节:
- 任务注册在
\memU\<name>命名空间下,卸载确定性强(windows.py#L42)。 -LogonType S4U无窗口、无需存储密码;-RunLevel Limited避免提权读到别的配置文件;-StartWhenAvailable补跑错过的运行;-WorkingDirectory设为宿主工作树,否则 Task Scheduler 默认从System32启动——带工作区信任闸门的cursor-agent --trust会把信任授予System32;-RepetitionDuration显式设为约 10 年,因为 Win10/11 默认会把重复限制在约一天、任务一天后悄悄死掉(正是 #539 的「装好但静默死亡」故障)。- 包装器还负责重建
PATH(Task Scheduler 不继承交互 shell 的)并用 UTF-8 BOM 编码以兼容非 ASCII 用户名(windows.py#L98-L127)。
Cursor 特有的事实,全部在真实 Windows 11 上字段验证过:
- 必须从安装
cursor-agent之后打开的终端里跑schedule install。安装器更新注册表用户PATH;更早启动的 shell(或 IDE)保留启动时环境,辅助命令会以 "not on PATH" 拒绝(INSTALL.md Part 2.0 的陈旧环境陷阱)。 - 调用自带
--trust。cursor-agent拒绝在不受信任目录中无头运行("Workspace Trust Required",退出码 1)——这在 session 0 里不可见。辅助命令的模板把--trust同时烧进安装期鉴权探测和定时运行,并把任务工作目录设为~/.memu/hosts/cursor,于是信任落在 memU 自己的工作树上——绝不落在System32(调度器默认 CWD)或安装命令所在目录。不要用--yolo替代。 - 凭据是 Cursor 账号会话。本机 IDE 已登录时,CLI 复用该会话——profile 支撑、已验证能存活进 S4U 的 session-0 运行。自定义供应商(BYOK)模型不能在 CLI 中用:定时运行按账号套餐计费,免费套餐即使
schedule verify显示绿色也会在额度上饿死——这是那道闸门唯一看不见的 entitlement 失败。
确认方式与 Step 3 相同——信文件系统痕迹,不信运行自己的摘要:运行后检查~/.memu/hosts/cursor/jobs/时间戳与会话 manifest 是否前移。
运维要点(Notes):五个必须理解的边界
原文档的 Notes 节是本任务长期可靠运行的关键约束,逐条展开:
- 已有 Unix 调度需要更新后的包装脚本。重新复制
bridge.sh(或重跑调度安装),让它导出MEMU_BRIDGING_RUN=1;没有这个标记,prepare会刻意把运行当作人手跑,不会认领自己的 Cursor 会话。Windows 包装器已导出该标记。tests/test_cursor_self_sessions.py中甚至有一条断言直接检查BRIDGING_TASK.md文档文本包含export MEMU_BRIDGING_RUN=1,防止文档与实现漂移。 - Leftovers 先于 prepare 处理。运行开始时已在磁盘上的 job 文件是未完成工作——中途死掉的运行,或安装自身的验证。
prepare会删除未处理的 job 文件,且 Cursor 已将会话标记为已见,那一刻被跳过的内容永远不会再被挖掘;先排空 leftovers 能把半成品周期变成有界的重做,而不是静默丢失。 - 幂等且增量。
prepare在~/.memu/hosts/cursor/.session_manifest.cursor.json里维护逐会话的行游标。结合 pipeline.py 的 commit 看,游标推进遵循「状态在持久成功后前进,而非意图」原则(issue #518):prepare 暂存的游标在 commit 成功后才提升,中途死掉的运行保留旧游标与旧快照,一切未完成的东西下次原样重来——有界重做,绝不静默丢失。 - 顺序是承重的。memory job 在 skill job 之前,资源描述 job 最后,永远按数字升序。这与
prepare的生成编号(每个会话产出 memory + skill 两个 job,资源 job 恒为2 * num_sessions + 1)严格对应。 - 工作树按宿主隔离。
~/.memu/hosts/cursor/下的一切都是该适配器运行范围的中间状态,其他 memU 宿主适配器永不与它竞争(host_cli.py#L12-L19 解释了多宿主工作树隔离的历史背景)。但它们共享的持久后端由~/.memu/config.env里的MEMU_MEMORY_MODE选择;本地模式用其中的MEMU_DB——这正是「一个宿主会话教给 memU 的,另一个宿主能检索到」的机制。 - 失败处理。只有步骤 1 和 3(
prepare/commit)的失败应当中止运行;步骤 2 中一个「什么也不做」的 job 是正常结果,不是错误。
工作树与命令面:从源码看整条流水线的形状
~/.memu/hosts/cursor/下的布局由 bridging/layout.py 的Layout类统一定义(prepare 与 commit 共享同一事实源,而非复制常量):jobs/(编号任务文件)、sessions/(本次切片出的 transcript)、memory/与skill/(recall 文件镜像)、.session_manifest.<host>.json(已提升的游标)与.pending后缀(prepare 暂存版)、.memory_manifest.json(内容哈希快照)、.self_sessions.<host>.json(桥接运行自身会话 id)、.bridging_run.<host>.json(周期起点标记)、.resource.tmp(追加式 touched 日志)与resources.md(验证后的描述文件)。
memu-cursor的命令面由共享的 host_cli.py 按HostSpec声明式构建,cli.py 只负责声明「Cursor 是什么」:transcript 根在~/.cursor/projects(每个项目一个目录,路径中/展平为-,每个会话一个 transcript 目录),指令注入目标是项目根AGENTS.md(Cursor 没有 CLI 可写的全局用户级指令文件,User Rules 在 IDE 设置里,故注入缝是每项目的,cli.py#L28-L32)。sessions.py 只处理agent-transcripts/**/*.jsonl(IDE 的 Composer 聊天在state.vscdbSQLite 里,不在读取范围),记录按 JSONL 每行一个 JSON 对象分类为消息/工具记录,无时间戳,故增量扫描完全由行数驱动。
一个与此文档配套的完整安装视角在 INSTALL.md:Part 1 安装 memU 并配置后端(memu-cursor config,绝不手写~/.memu/config.env)、Part 2 用memu-cursor docs task走本流程、Part 3 用memu-cursor install-instruction把检索指令注入各项目AGENTS.md,最后用memu-cursor report install/report error向 memU 汇报结果——记录缝与注入缝共享同一个~/.memu/config.env,由此证明它们必然共用同一后端。
至此,你已经掌握了 memU Cursor 桥接任务的完整图谱:三步骤流水线的职责划分、Unix 与 Windows 两条调度路径的注册细节与陷阱、以及支撑「提示词进文件」「信任落工作树」「自会话不自我挖掘」「痕迹验证替代自述」这些关键设计的源码依据。部署时请始终记住两条主线纪律:提示词永远放文件,crontab 行永远简短;验证永远看文件系统痕迹,永远不信运行自己的摘要。
【免费下载链接】memUPersonal memory across agents项目地址: https://gitcode.com/GitHub_Trending/mem/memU
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考