为暂停、受阻或提前停止的 Codex Goal 自动续跑,提供 macOS 菜单栏应用和 Codex 插件两种形态。
English ·
Important
Codex GoalPulse 是非官方社区项目,与 OpenAI 不存在隶属、赞助或背书关系。“Codex”仅用于说明项目兼容的产品。
| 形态 | 支持平台 | 适用场景 | 实现 |
|---|---|---|---|
| macOS 菜单栏应用 | macOS 13+ | 睡前先配置所有本地 Goal,并处理后续断网或 Desktop 中断 | 独立进程定时扫描并通过 Desktop IPC 恢复 |
| Codex 插件 | macOS、Windows | Codex 正常触发 Stop,但本地 Goal 仍未完成 |
官方生命周期 Hook 直接创建下一次续跑 Turn |
插件位于 plugins/codex-goal-pulse。突发断网没有产生 Stop 事件时,仍需要菜单栏应用进行进程外扫描。
插件不会遇到“暂停后才发现 Session,只能套用默认 3 次”的问题:UserPromptSubmit Hook 会在任务开始时保存当前 Session 的 Prompt 配置;未显式配置时才使用默认 3 次。插件本身不做后台全量扫描。
macOS 用户可以使用菜单栏应用,也可以选择插件;Windows 用户使用 Codex 插件。不要在同一个 Session 上同时启用两种自动续跑方式。
长时间运行的 Codex 目标可能因临时断网、手动停止或后端中断变成 blocked、进入 paused。GoalPulse 启动时就读取全部本地 Goal,并默认每 5 秒刷新一次;因此 Goal 仍在运行时就会出现在持久列表中,用户可以提前设置次数。新发现的 Session 默认只提醒,不会因为历史状态被自动启动;用户手动选择次数后,它才会在后续暂停或受阻时按剩余次数激活目标,再把“继续”事件交给已经运行的 Codex Desktop Session。只有 Desktop 返回真实 Turn ID 和 inProgress 才算恢复成功并扣除一次。
它不会读取 Codex 窗口、查找按钮文字、移动鼠标或调用 macOS 辅助功能 API。
- 原生 Swift 菜单栏应用,菜单栏数字和面板都显示持久监控列表中的 Session 总数。
- 启动、手动刷新以及此后按面板设置的间隔扫描全部 Goal;不论当前状态都立即加入持久列表,默认每 5 秒一次,可选 2、5、10、15、30 或 60 秒。
- Session 加入后,即使恢复、完成、从当前数据库结果消失或应用重启也会继续保留;在卡片上右键选择 从监控列表移除 会隐藏当前状态,后续再次暂停或受阻时仍会重新加入。
- 状态变化只更新菜单栏图标和数字;面板仅在用户点击图标时打开,避免打断当前工作。
- 点击其他位置会收起面板;点击 退出 GoalPulse 会停止本次登录会话的监控。
- 紧凑的原生面板,直接路由触控板/鼠标滚轮事件,并显示长列表滚动条。
- 可拖动 Goal 调整顺序;拖动期间后台刷新不会重建列表,顺序在刷新和重新启动后继续保留。
- 手动刷新显示原生旋转进度和完成状态。
- 菜单栏应用中新发现的 Session 默认只提醒,需要手动选择恢复 1–10 次或无限次;选择框显示的是“上限”而不是剩余次数,卡片会单独显示剩余次数和“次数用尽”。选择其他上限,或在已经消耗次数后重新选择当前上限,都会重新计满;应用重启、目标改名或运行进展仍沿用原来的剩余次数。
- 只读访问本地
~/.codex/goals_*.sqlite数据库。 - 遇到 Codex 轮换 SQLite WAL/SHM 时会短暂重试;界面保留上次成功状态,连续三轮读取失败后才显示错误。
- 通过 Codex Desktop 的本机 IPC 直接调用现有 Session,不启动隐藏的任务执行后端。
- 状态辅助进程只发送
thread/goal/set,随后立即退出;它不会调用thread/resume,也不会加载 Session 的工作目录。 - 等待网络恢复;列表内 Session 每次再次暂停都会在下一轮扫描恢复,只有 Desktop 返回正在执行的真实 Turn 后才扣除一次并显示“执行中”。
- GoalPulse 不回答或授予任何新权限请求,权限交互仍留在 Codex Desktop。
- 没有遥测、远程监听、浏览器自动化,也不需要辅助功能授权。
flowchart LR
A["按设置间隔扫描全部本地 Goal(默认 5 秒)"] --> B{"发现新的本地 Session?"}
B -- "是" --> C["立即以只提醒加入持久列表,等待用户配置"]
B -- "否" --> D{"列表内 Session 暂停且仍有剩余次数?"}
C --> D
D -- "否" --> A
D -- "是" --> E{"网络可用?"}
E -- "否" --> A
E -- "是" --> F["thread/goal/get 再次确认状态"]
F --> G["状态辅助进程发送 thread/goal/set → active"]
G --> H["关闭状态辅助进程"]
H --> I["打开对应 Codex Desktop Session"]
I --> J["本机 IPC 发送 thread-follower-start-turn"]
J --> K["校验真实 Turn ID 并扣除一次"]
K --> A
恢复链路如下:
thread/goal/set { "threadId": "THREAD_ID", "status": "active" } # 状态辅助进程;仅 paused / blocked
thread-follower-start-turn { "conversationId": "THREAD_ID", "turnStartParams": { "input": [{ "type": "text", "text": "Continue working toward the existing Goal from its current state." }] } } # Codex Desktop IPC
GoalPulse 依赖 Codex 当前的本地实现细节。Codex 更新后,协议或数据库结构可能变化,详见兼容性与限制。
| 运行方式 | 环境要求 |
|---|---|
| macOS 菜单栏应用 | macOS 13 Ventura 或更高版本;Codex 桌面端(或带内置 Codex 后端的 ChatGPT 桌面端)和目标模式。 |
| Codex 插件(macOS) | 支持插件与 Hook 的 Codex;python3 可从终端直接运行。 |
| Codex 插件(Windows) | 支持插件与 Hook 的 Codex;Python 3 和 py 启动器可用,py -3 --version 能正常执行。 |
从源码构建菜单栏应用还需要 Xcode Command Line Tools。插件不依赖 Swift,也不需要 macOS 辅助功能权限。
每个版本的 Release 至少包含两个独立文件:
| 文件 | 用途 |
|---|---|
CodexGoalPulse-VERSION.zip |
macOS 菜单栏应用和安装脚本。 |
CodexGoalPulse-Plugin-VERSION.zip |
可在 macOS 或 Windows 安装的 Codex 插件 Marketplace 包。 |
- 从 Releases 下载最新的
CodexGoalPulse-VERSION.zip。 - 解压后按住 Control 点击 Install.command,选择“打开”。
- 点击菜单栏里的 GoalPulse 图标,查看持久 Session 列表、拖动排序、设置次数,或右键移除。
安装脚本会把应用复制到 ~/Applications、注册当前用户的 LaunchAgent,并设为登录后启动。主动退出后不会被强制拉起,下次登录时重新启动。本地构建的压缩包使用临时签名;后续发布流程可接入 Developer ID 签名与公证。
推荐直接从 GitHub Marketplace 源安装:
codex plugin marketplace add kongtaoxing/CodexGoalPulse
codex plugin add codex-goal-pulse@codex-goal-pulse也可以从 Releases 下载 CodexGoalPulse-Plugin-VERSION.zip,解压后把其中目录的绝对路径传给 Codex:
codex plugin marketplace add /ABSOLUTE/PATH/CodexGoalPulse-Plugin-VERSION
codex plugin add codex-goal-pulse@codex-goal-pulse安装后在 Codex 中打开 /hooks,检查并信任 GoalPulse Hook,然后新建任务。配置方式见插件说明。同一个 Session 建议只启用一种自动续跑方式。
git clone REPOSITORY_URL
cd codex-goal-pulse
make build应用生成在:
build/Codex GoalPulse.app
常用开发命令:
make ci # 本地运行与 GitHub macOS CI 相同的验证和打包入口
make test # 构建并运行纯本地自检
make test-plugin # 验证 Codex Hook、次数持久化和插件结构
./scripts/test-protocol.sh # 用本地假状态后端和假 Desktop IPC 验证完整恢复链路
./scripts/test-memory.sh # 长时间轮询内存回归测试
./scripts/verify.sh # 检查签名、plist、链接库和敏感 API
make package # 在 dist/ 生成发布压缩包
make package-plugin # 在 dist/ 生成 Codex 插件压缩包
make release-assets # 一次生成版本一致的应用和插件两个 Release 文件
./scripts/render-preview.sh推送前建议直接运行 make ci。GitHub Actions 的 macOS Job 也调用这个入口,避免本地命令和远端 CI 漂移;如果本机安装了 act,脚本还会以 dry-run 模式校验 Workflow。act 不会模拟 AppKit/macOS Runner,真正的构建和测试仍由本机原生工具链完成。插件另外在 GitHub 的 Windows Runner 上执行原生 Python 回归测试。
Swift 实现已拆分为 App、Core、Engine、Persistence、Protocol、Support 和 UI 七个目录;Codex 插件独立放在 plugins/codex-goal-pulse,与菜单栏应用共用仓库但分别打包。各模块职责、依赖方向和扩展规则见 ARCHITECTURE.md。
可执行文件位于应用包的 Contents/MacOS/CodexGoalPulse。
| 参数 | 行为 |
|---|---|
--check |
只读检查并显示将执行的动作,不恢复目标。 |
--once |
真实恢复最新且符合条件的一个待处理目标。 |
--ui-only |
只显示菜单栏界面,不自动恢复。 |
--interval SECONDS |
全量扫描间隔,默认 5 秒,可设为 1–300 秒;菜单栏面板提供常用值。 |
--cooldown SECONDS |
Desktop 启动失败后的重试间隔,默认及最少均为 5 秒。 |
--max-attempts COUNT |
新 Session 的恢复上限,默认 0(只提醒)。 |
--json |
配合 --check 输出机器可读报告。 |
--self-test |
不依赖 Codex 或网络的确定性自检。 |
--thread-id ID |
只检测指定 Session。 |
--verify-session-start ID |
在 Codex Desktop 中启动指定 Session,并输出真实 Turn ID。 |
--once 会真实发送恢复事件;--check 和 --ui-only 不会。
- 发送
active前会再次确认目标仍处于原来的blocked或paused状态。 - 状态辅助进程从不加载 Session;若 Desktop IPC 启动失败,会把 Goal 状态回滚并且不计次数。
- 所有 Turn 都由现有 Codex Desktop 后端启动;GoalPulse 不保留独立任务执行进程。
- 数据库中的
active只显示为“已激活”;只有 Desktop IPC 返回真实Turn ID和inProgress后才显示“执行中”。 - “执行中”会继续用 Session rollout 的
task_started/task_complete证据核对,避免把暂停或空闲 Session 误报为运行。 - 新发现的每个本地 Goal 都会立即进入列表,但默认
0次(只提醒);只有用户手动选择次数后才会自动恢复,在运行期间设置的策略会原样沿用到后续暂停。 - 不恢复用量受限或预算受限的目标。
- 有限策略会累计 Desktop 确认成功启动的恢复次数,达到上限后停止尝试。
- 无限次不限制恢复次数;手动移除会忽略当前状态,但后续出现新的暂停或受阻事件仍会重新加入。
- 运行进展和再次暂停不会清零恢复次数;用户选择其他上限,或再次选择已经使用过的当前上限时,才重新从
0计数。 - GoalPulse 不代替 Codex Desktop 处理命令、文件修改或其他授权请求。
- 将某目标设为
0次即“只提醒”。 - Session 顺序、监控列表、当前事件的移除标记、扫描间隔和剩余次数都保存在本机;新 Session 默认排在已保存顺序之前。
- 升级和重启不会重置明确选择的策略。由于 1.1.0 无法区分“旧默认 3 次”和“用户手动选择 3 次”,升级到 1.1.1 时这类旧记录会一次性改为只提醒;需要自动恢复的 Session 请重新选择次数。
自动续跑可能消耗模型额度,也会在该 Codex 任务原有权限范围内继续执行动作。长时间离开电脑前,请先检查每个目标的次数上限。
| 数据 | 位置 |
|---|---|
| Codex 目标状态(只读) | ~/.codex/goals_*.sqlite |
| GoalPulse 监控列表、当前状态移除标记及剩余次数 | ~/Library/Application Support/CodexGoalPulse/state.json |
| Goal 显示顺序及扫描间隔 | ~/Library/Preferences/io.github.codexgoalpulse.plist |
| 服务日志 | ~/Library/Logs/CodexGoalPulse.log |
| LaunchAgent | ~/Library/LaunchAgents/io.github.codexgoalpulse.plist |
| 插件策略和已用次数 | Codex 分配的 PLUGIN_DATA/state.json |
目标标题和 ID 始终留在本机,除非你主动分享日志或截图。仓库里的公开截图全部由虚构样本数据生成。
运行发布包中的 Uninstall.command。应用和 LaunchAgent 会被移除;日志和重试设置会保留用于排查,也可手动删除。
- 合盖、注销、关机或系统睡眠都会暂停本机监控。
- GoalPulse 只处理桌面端写入本地数据库的目标。
- 当前接入点是状态专用 app-server、本机 Desktop IPC 和本地目标数据库,而不是稳定的公开 Goal API。
- 插件只在 Codex 生命周期事件中运行;突发断网、进程退出或崩溃没有产生
Stop时,不会在后台继续扫描。 - Codex 更新后可能需要发布兼容版本。提交问题时请注明 Codex 和 macOS 版本,但不要上传真实目标数据库。
请阅读 CONTRIBUTING.md、SECURITY.md 和路线图。所有贡献采用 MIT License。

