Cursor AI Agent任务完成通知工具:提升开发效率的智能提醒方案
1. 项目概述与核心价值如果你和我一样每天大部分时间都泡在 Cursor 编辑器里让 AI Agent 帮你写代码、重构项目或者生成文档那你肯定遇到过这个场景你给 Agent 下达了一个复杂的指令然后切到浏览器或者另一个窗口去处理别的事情时不时地回头看一眼进度条。有时候Agent 已经悄无声息地完成了任务而你却浑然不知白白浪费了等待的时间。或者更糟的是你同时在多个项目里开了多个 Agent它们陆续完成工作你却分不清哪个是哪个还得一个个点开确认。这种体验上的小割裂累积起来其实挺影响效率的。cursorfinishsound这个项目就是为了解决这个“最后一公里”的体验问题而生的。它的核心功能非常简单直接当 Cursor 的 AI Agent 完成你交给它的最后一项任务时自动触发一个通知。这个通知可以是两种形式一声轻柔的提示音或者一个用语音合成技术TTS念出当前项目文件夹名称的“机器人播报”。想象一下你正在写邮件耳边突然传来一个声音清晰地念出“backend-api”你就立刻知道是那个处理用户认证的 Agent 已经搞定了无需任何视线切换。对于需要同时管理多个并行开发任务或者在“深度工作”与“等待 Agent”状态间频繁切换的开发者来说这个小工具带来的心流保护和工作上下文的无缝衔接价值远超其代码量。这个项目本质上是一个轻量级的 Python 包它巧妙地利用了 Cursor 编辑器的“Rules for AI”功能将自定义的 Python 脚本注入到 Agent 的工作流末尾。其技术栈非常精简核心是 Python 的标准库subprocess和os用于执行系统命令和获取文件路径语音播报功能依赖于经典的、跨平台的开源语音合成引擎espeak而提示音则使用了 Python 的winsoundWindows或playsound库。整个设计遵循了 Unix 哲学——“做一件事并把它做好”没有复杂的依赖和配置开箱即用。2. 环境准备与深度安装指南安装cursorfinishsound的过程本身不复杂但为了确保它在你的工作流中稳定可靠地运行我们需要对几个关键环节进行深入配置。很多“能用但不好用”的问题都源于安装时的小疏忽。2.1 系统级依赖的精准安装项目依赖espeak进行文本转语音。在 Ubuntu/Debian 及其衍生系统上安装命令很简单sudo apt-get update sudo apt-get install espeak -y注意这里我强烈建议在执行安装前先运行sudo apt-get update。这能确保你的包管理器索引是最新的避免因仓库信息过期而安装到旧版本或不兼容的版本。espeak虽然稳定但不同版本在语音清晰度和参数支持上可能有细微差别。对于 macOS 用户可以通过 Homebrew 安装brew install espeak而对于 Windows 用户情况稍微特殊一些。espeak有 Windows 版本但通常不推荐通过包管理器安装。更稳妥的做法是直接访问 espeak 项目页面 下载预编译的二进制文件并将其所在目录例如C:\Program Files\eSpeak\command_line\添加到系统的PATH环境变量中。这样Python 的subprocess模块才能在任何位置调用到espeak命令。添加PATH后务必重启你的命令行终端或 Cursor 编辑器以使环境变量生效。2.2 Python 环境与包依赖管理项目要求 Python 3.x。首先用以下命令确认你的 Python 版本python3 --version # 或 python --version接下来是安装 Python 包依赖。项目根目录下的requirements.txt文件通常内容很简单可能只包含playsound等库。但这里有一个非常重要的最佳实践使用虚拟环境。我强烈建议你不要在全局 Python 环境中安装这些依赖。因为不同项目可能需要不同版本的库全局安装容易引发冲突。为cursorfinishsound单独创建一个虚拟环境是更清洁、更安全的选择。# 1. 进入你计划放置 cursorfinishsound 的目录例如你的工具目录 cd ~/my_dev_tools # 2. 克隆仓库 git clone https://github.com/eliaspfeffer/cursorfinishsound.git cd cursorfinishsound # 3. 创建虚拟环境以 venv 模块为例 python3 -m venv venv # 4. 激活虚拟环境 # Linux/macOS source venv/bin/activate # Windows venv\Scripts\activate # 5. 在激活的虚拟环境中安装依赖 pip install -r requirements.txt激活虚拟环境后你的命令行提示符通常会发生变化前面会显示(venv)这表明你正处在一个隔离的 Python 环境中。关键一步来了你需要确保 Cursor 的 AI Agent 也在同一个虚拟环境中运行你的脚本。否则Agent 会使用系统默认的 Python 环境从而找不到已安装的playsound等包导致脚本执行失败。如何做到这一点这取决于你如何调用 Agent。一个可靠的方法是在 Cursor 的“Rules for AI”中使用虚拟环境 Python 解释器的绝对路径来执行脚本。例如你的规则可以这样写Always play /absolute/path/to/cursorfinishsound/venv/bin/python /absolute/path/to/cursorfinishsound/soundname.py when you have finished the last job, before you stop generating.注意这里我们不再直接执行.py文件而是通过指定虚拟环境中的python解释器来执行它。这是保证依赖一致性的最稳妥方法。2.3 Cursor 规则配置的细节与原理将规则添加到 Cursor 是集成的最后一步也是最容易出错的一步。打开 Cursor点击 Agent 窗口右上角的齿轮图标进入设置找到 “Rules for AI” 部分。你需要添加的规则文本是Always play /absolute/path/to/your/cursorfinishsound/soundname.py when you have finished the last job, before you stop generating.这里有三个必须注意的细节绝对路径你必须将/absolute/path/to/your/cursorfinishsound/替换成你电脑上cursorfinishsound文件夹的真实、完整路径。相对路径在 Cursor Agent 的执行上下文中很可能无法正确解析。在 Linux/macOS 上你可以在终端中进入该文件夹然后输入pwd命令获取绝对路径。在 Windows 上你可以在文件资源管理器的地址栏复制路径可能需要稍作修改如将\替换为/或\\。规则语义这条规则的意思是“总是Always在完成最后一项工作后、停止生成前播放play指定的脚本”。play这个动词在这里是 Cursor 规则语法的一部分它意味着“执行这个外部命令或脚本”。这条规则会被注入到 Agent 每次任务循环的末尾。脚本选择你可以选择soundname.py播报文件夹名或sound.py仅播放提示音。根据你的喜好和办公环境决定。在开放办公区突然响起的机器人语音可能会打扰同事此时提示音是更礼貌的选择。配置完成后保存设置。下次你启动一个新的 AI Agent 并让它执行任务时这条规则就会生效。你可以先让 Agent 执行一个简单的任务比如“写一个打印 hello world 的函数”来测试通知是否正常工作。3. 核心模块解析与定制化改造理解了安装和配置我们深入到代码层面看看这两个核心脚本sound.py和soundname.py是如何工作的以及如何根据你的个人喜好进行定制。3.1sound.py跨平台的轻柔提示音sound.py的核心任务是播放一个简短、不刺耳的声音。它的实现需要处理不同操作系统的差异。# sound.py 示例逻辑 import sys import os def play_gentle_notification(): 播放一个轻柔的提示音。 try: if sys.platform win32: # Windows: 使用 winsound 播放系统提示音 import winsound winsound.MessageBeep(winsound.MB_ICONASTERISK) # 星号提示音较为柔和 else: # Linux/macOS: 使用 playsound 播放一个本地音频文件 # 假设项目根目录下有一个 ‘notification.wav’ 文件 from playsound import playsound sound_file os.path.join(os.path.dirname(__file__), notification.wav) playsound(sound_file) except Exception as e: # 静默失败避免干扰主流程 print(fCould not play sound: {e}, filesys.stderr) if __name__ __main__: play_gentle_notification()实现要点与定制Windows 路径winsound.MessageBeep()可以接受不同的常量参数如MB_ICONHAND关键停止、MB_ICONQUESTION疑问。你可以替换MB_ICONASTERISK来尝试不同的系统提示音找到最合你心意的那一个。非 Windows 系统这里默认使用playsound库播放一个名为notification.wav的音频文件。你需要确保这个文件存在于项目根目录。你可以用任何音频编辑软件如 Audacity制作或下载一个简短的、令人愉悦的提示音例如一个轻柔的“叮”声或木琴音时长最好在0.5秒以内避免过长打扰。错误处理代码用try...except包裹并在失败时打印错误信息到标准错误流 (sys.stderr)。这是非常必要的因为如果播放声音失败例如找不到音频文件我们不希望这个次要功能导致整个 Agent 结束流程崩溃。静默失败或记录日志是最佳实践。3.2soundname.py语音播报当前工作目录这是项目的特色功能。soundname.py脚本会获取当前工作目录的文件夹名并通过espeak用语音读出来。# soundname.py 示例逻辑 import subprocess import os import sys def say_folder_name(): 使用 espeak 说出当前工作目录的父文件夹名称。 try: # 获取当前工作目录 cwd os.getcwd() # 提取当前目录的直系父文件夹名 parent_folder os.path.basename(cwd) if not parent_folder: parent_folder Root or Unknown # 处理根目录等情况 # 构建 espeak 命令 # -a 参数设置音量0-200默认是100这里设为50更柔和 # -s 参数可以设置语速单词每分钟默认是160可根据需要调整 command [espeak, -a, 50, -s, 150, parent_folder] # 执行命令 subprocess.run(command, checkTrue, stdoutsubprocess.DEVNULL, stderrsubprocess.DEVNULL) except FileNotFoundError: print(Error: espeak command not found. Please ensure espeak is installed and in your PATH., filesys.stderr) except subprocess.CalledProcessError as e: print(fError running espeak: {e}, filesys.stderr) except Exception as e: print(fAn unexpected error occurred: {e}, filesys.stderr) if __name__ __main__: say_folder_name()核心机制解析获取目录os.getcwd()返回的是当前工作目录Current Working Directory。当 Cursor Agent 执行你的项目任务时这个目录通常就是你打开的项目根目录。提取文件夹名os.path.basename()从一个路径字符串中提取最后一部分。对于/home/user/projects/my-awesome-api它返回my-awesome-api。调用系统命令subprocess.run()是执行外部命令的标准方式。我们将命令和参数如-a 50放在一个列表里传递这比拼接字符串更安全可以避免 shell 注入等安全问题。checkTrue确保如果espeak命令执行失败返回非零状态码会抛出CalledProcessError异常。我们将标准输出和错误重定向到DEVNULL是为了避免espeak的任何输出污染 Cursor Agent 的信息流。深度定制选项音量 (-a)-a 50表示50%的音量。如果你觉得声音太小或太大可以调整这个值范围0-200。我个人的经验是在安静的办公室30-40 足够如果戴着耳机可以调到60-80。语速 (-s)-s 150表示每分钟说150个单词。默认160可能有点快特别是对于长的项目名。你可以调到120-140让播报更清晰。-s 100会非常缓慢和清晰。声音 (-v)espeak支持多种语言和声音。你可以尝试-v en英语、-v de德语等甚至有些版本支持-v mb-en1男性声音或-v f5女性声音5号。用命令espeak --voices可以查看所有可用声音。处理复杂项目名如果你的项目名包含下划线、连字符如my-awesome_api_v2espeak的播报可能会有点奇怪。一个进阶的定制思路是在脚本中对parent_folder字符串进行预处理比如将下划线替换为空格parent_folder parent_folder.replace(_, )。这样读出来就是“my awesome api v2”听起来更自然。4. 高级集成方案与实战心得基础用法已经能覆盖大部分场景但如果你希望这个工具更紧密地融入你的开发工作流或者解决一些特定问题可以考虑以下进阶方案。4.1 多项目管理与上下文区分当你同时在多个项目窗口中使用 Cursor 时每个窗口的 Agent 都会播报自己所在的项目名。这本身就是一个完美的上下文区分。但有时你可能在一个大项目里同时进行多个不相关的任务比如同时开发前端组件和修复后端BUG并且为每个任务开了独立的 Agent。由于它们都在同一个项目目录下播报的名字是一样的就无法区分。解决方案你可以修改soundname.py脚本让它播报更具体的信息。例如结合 Cursor 的 Agent 指令或者一个简单的环境变量。环境变量法在启动某个特定任务的 Agent 前在终端里设置一个临时环境变量。export TASK_NAMEFix_User_Auth_BUG # 然后在这个终端里启动 Cursor或者确保 Cursor 能继承这个环境变量然后在soundname.py中import os task_name os.environ.get(TASK_NAME) if task_name: folder_to_speak f{os.path.basename(os.getcwd())} - {task_name} else: folder_to_speak os.path.basename(os.getcwd()) # 然后用 folder_to_speak 去播报这样播报的内容就会是my-awesome-api - Fix_User_Auth_BUG。轻量级标记文件法在项目子目录下创建一个特定的空文件如.agent_task_marker然后在脚本中检查当前工作目录或其父目录中是否存在这个文件并据此调整播报内容。这种方法更“持久”但需要手动管理标记文件。4.2 错误排查与日志记录虽然我们做了错误处理但有时通知不工作你需要知道原因。一个增强健壮性的方法是引入简单的日志记录。你可以修改脚本将关键信息如获取到的目录、执行的命令、发生的错误写入一个日志文件而不是仅仅打印到stderr这部分输出在 Cursor 中可能看不到。import logging import os from datetime import datetime def setup_logging(): log_dir os.path.expanduser(~/cursor_agent_logs) os.makedirs(log_dir, exist_okTrue) log_file os.path.join(log_dir, ffinish_sound_{datetime.now().strftime(%Y%m%d)}.log) logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(log_file), logging.StreamHandler() # 同时输出到控制台Cursor可能捕获到 ] ) return logging.getLogger(__name__) logger setup_logging() def say_folder_name(): try: cwd os.getcwd() parent_folder os.path.basename(cwd) logger.info(fCurrent working directory: {cwd}) logger.info(fFolder to speak: {parent_folder}) # ... 其余代码 ... subprocess.run(command, checkTrue, stdoutsubprocess.DEVNULL, stderrsubprocess.DEVNULL) logger.info(espeak command executed successfully.) except Exception as e: logger.error(fFailed to speak folder name: {e}, exc_infoTrue)这样当出现问题时你可以去~/cursor_agent_logs目录下查看日志精准定位是路径问题、espeak命令问题还是其他运行时异常。4.3 与系统通知中心集成macOS/Linux对于追求极致体验的用户你可能希望提示不仅仅是一段语音或声音还能在系统通知中心显示一条横幅。这可以通过在 Python 脚本中调用系统命令来实现。macOS可以使用osascript命令发送 AppleScript 指令来显示通知。def send_macos_notification(title, message): script fdisplay notification {message} with title {title} subprocess.run([osascript, -e, script])你可以在play_gentle_notification或say_folder_name函数成功执行后调用这个函数发送一条如“Agent 任务完成于 [项目名]”的通知。Linux (使用notify-send)许多 Linux 桌面环境如 GNOME, KDE都支持notify-send命令。def send_linux_notification(title, message): subprocess.run([notify-send, title, message])将系统通知与声音/语音结合提供了视觉和听觉的双重保障确保你不会错过任何完成信号。5. 常见问题与排查技巧实录在实际部署和使用cursorfinishsound的过程中我遇到并总结了一些典型问题。这里列出一个速查表帮助你快速定位和解决。问题现象可能原因排查与解决方案完全没有声音或语音1. Cursor 规则路径错误。2. Python 脚本执行权限问题Linux/macOS。3. 虚拟环境未激活或路径不对。1.检查绝对路径在终端中手动执行一次规则中的完整命令看是否能成功播放声音。例如/path/to/venv/bin/python /path/to/cursorfinishsound/sound.py。2.检查权限确保.py文件有可执行权限 (chmod x sound.py)或者通过 Python 解释器执行。3.确认虚拟环境确保规则中指向的 Python 解释器路径是你的虚拟环境中的python。提示“ModuleNotFoundError: No module named ‘playsound’”Python 依赖包未在 Agent 执行脚本的环境中安装。1.激活虚拟环境在终端中进入项目目录激活虚拟环境 (source venv/bin/activate)然后运行pip list确认playsound已安装。2.修正规则路径确保 Cursor 规则中使用的 Python 是虚拟环境中的那个绝对路径。3.全局安装不推荐作为临时测试可以pip install playsound进行全局安装。语音播报不清晰、语速过快或无声1.espeak未安装或不在PATH中。2.espeak命令参数音量、语速设置不当。3. 系统音量静音或过低。1.验证 espeak在终端直接运行espeak hello world看是否有语音输出。如果没有重新安装或将其目录加入PATH。2.调整参数修改soundname.py中的-a音量和-s语速参数值找到适合你听觉的设置。3.检查系统音频确保电脑扬声器或耳机正常工作且音量合适。播报的文件夹名不是项目名当前工作目录 (os.getcwd()) 不是项目根目录。Agent 可能在执行过程中切换了子目录。这是一个已知的 Cursor Agent 行为。Agent 有时会在项目子目录中执行操作。你可以尝试修改脚本向上追溯多层目录或者使用一个更稳定的方式获取项目根目录例如查找.git文件夹的所在目录如果项目是 Git 仓库。pythonbrimport osbrdef get_project_root(start_path.):br current_path os.path.abspath(start_path)br while True:br if os.path.isdir(os.path.join(current_path, .git)):br return current_pathbr parent_path os.path.dirname(current_path)br if parent_path current_path: # 到达根目录br breakbr current_path parent_pathbr return os.path.abspath(start_path) # 回退到起始目录brproject_root get_project_root(os.getcwd())brfolder_name os.path.basename(project_root)br规则添加后Agent 完成任务时无任何反应1. Cursor 规则未保存或未生效。2. 规则语法可能有误。3. Agent 可能被配置为忽略外部命令。1.重启 Cursor有时更改规则后需要重启 Cursor 才能完全生效。2.检查规则格式确保规则是纯文本没有多余的空格或换行符。可以尝试先写一条简单的测试规则如执行echo done。3.检查 Agent 设置确认没有其他全局或项目级的规则覆盖或禁用了这条规则。Windows 下提示音太尖锐或不喜欢winsound.MessageBeep()使用的默认提示音类型不合适。尝试更换winsound.MessageBeep()的参数。例如winsound.MessageBeep(winsound.MB_ICONEXCLAMATION)感叹号winsound.MessageBeep(winsound.MB_ICONQUESTION)问号或者可以统一使用playsound库播放自定义的.wav文件这样跨平台体验更一致。我个人最常遇到的坑是“路径问题”和“虚拟环境问题”。我的经验是永远使用绝对路径并明确指出使用虚拟环境中的 Python 解释器。在配置完成后务必通过“手动在终端执行规则中的完整命令”来进行验收测试。如果手动执行成功但在 Cursor 中失败那问题大概率出在 Cursor 规则本身的语法或上下文环境上这时就需要仔细检查规则文本和 Cursor 的日志如果有的话。这个项目虽然小巧但它精准地解决了一个高频痛点。将它配置妥当后你几乎会忘记它的存在直到每一次任务完成时那一声及时的提醒让你无需再分心等待。这种流畅感正是高效开发工具应该提供的。