@yesongh/quota-beat
v0.1.13
Published
macOS-only CLI to kick Claude Code and Codex at a fixed time every day
Maintainers
Readme
quota-beat
在每天固定时间唤醒 Mac 并激活 Claude Code 和 Codex,即使 Mac 处于睡眠状态。
为什么需要它
Claude Code 的配额每 5 小时重置一次,从当天首次使用开始计算。在固定的早间时刻(如 07:00)发送一个最小请求,就能把重置周期锁定在可预测的时间窗口:
| 时段 | 重置时间 | | |---|---|---| | 上午 | 07:00 | 全新配额,游刃有余 | | 下午 | 12:00 | 午休回来,不急不忙 | | 傍晚 | 17:00 | 再来一轮 |
如果不锚定首次使用时间,重置周期会随每天的实际使用随机漂移。quota-beat 会自动唤醒 Mac 并发出首次请求,即使 Mac 处于睡眠状态。
前置条件
- macOS(依赖
launchd和pmset) - Node.js >= 18
- 已安装并认证 Claude Code CLI 和/或 Codex CLI
sudo权限(pmset repeat wakeorpoweron需要)
安装
npm install -g @yesongh/quota-beat这个包会安装两个命令别名:qbeat(推荐)和 quotabeat。
升级
npm install -g @yesongh/quota-beat@latest快速开始
# 设置每天 07:00 激活(默认时间)
qbeat install
# 或者自定义时间
qbeat install --time 06:00
# 查看当前配置
qbeat status命令
qbeat --version
显示当前已安装的 qbeat 版本并退出。
qbeat install [--time HH:MM]
注册 launchd 定时任务和 pmset 唤醒计划。
- 时间格式为 24 小时制
HH:MM,默认07:00。 - 重复运行
install会覆盖现有配置。 - 需要
sudo权限来设置pmset。
qbeat status
显示当前配置的时间。直接从已安装的 launchd plist 文件读取,不依赖任何状态文件。
qbeat kick
立即执行一次所有可用 provider(Claude Code、Codex)的激活。不会修改任何计划。
qbeat uninstall
移除 launchd 任务和所有 quota-beat 创建的 pmset 唤醒条目。不会卸载全局安装的 qbeat 命令别名。
自动更新提示
当你在交互式终端里运行 qbeat 时,它会大约每天检查一次 npm 上是否有更新版本。
如果发现新版本,qbeat 会提示你是否执行 npm install -g @yesongh/quota-beat@<resolved-version>。
qbeat --version 只会输出当前安装版本,不会执行这一步检查。
后台定时路径永远不会执行更新检查,也不会弹出提示。
实现说明和这次发布中遇到的问题见 docs/self-update-pattern.md。
工作原理
┌─────────────────────────────────────────────────────┐
│ pmset repeat wakeorpoweron(配置时间前 1 分钟) │
│ ↓ Mac 从睡眠中唤醒 │
│ launchd 触发已安装的 quota-beat 定时任务 │
│ ↓ │
│ 1. 等待网络就绪(最多 30 秒) │
│ 2. 激活所有可用 provider(Claude Code、Codex) │
│ 3. 追加 kick 调用日志 │
└─────────────────────────────────────────────────────┘pmset repeat wakeorpoweron每天在每个配置时间前 1 分钟唤醒 Mac。launchd在配置的精确时间触发已安装的 quota-beat 定时任务。- 工具检查网络连通性(DNS 查询
api.anthropic.com和api.openai.com,最多重试 30 秒)。 - 向每个可用的 provider 发送最小请求 — Claude Code(
claude -p "Reply with exactly OK.",使用你配置的默认模型)和/或 Codex(codex exec --ephemeral --skip-git-repo-check -c model_reasoning_effort=low "Reply with exactly OK.")— 来激活配额。 - 每次 kick 调用都会追加到
~/.quota-beat/logs/kick.jsonl,便于事后核查。
架构
五个零依赖模块:
| 模块 | 职责 |
|---|---|
| src/cli.mjs | 命令路由、参数解析、install/status/kick/uninstall 流程 |
| src/help.mjs | 根帮助文本、子命令帮助文本、用法提示 |
| src/update.mjs | 交互式 npm 版本检查、缓存管理、提示与自更新执行 |
| src/scheduler.mjs | launchd plist 生成与解析、pmset 唤醒调度与清理 |
| src/kick.mjs | Provider 定义、网络就绪检查、CLI 执行(Claude Code、Codex) |
关键设计决策:
- plist 中使用绝对 Node 路径 —
launchd运行在最小PATH环境下,无法可靠找到用户安装的 Node。plist 嵌入了安装时通过process.execPath捕获的绝对路径。 - 收敛的 pmset 清理 — quota-beat 只取消自己管理的
wakeorpoweronrepeat 规则,不会做更大范围的pmset重置。 - 无状态文件 —
status以已安装的 plist 作为唯一数据来源。
详细执行流程参见 docs/architecture.md。
日志
launchd 的标准输出和错误日志保存在:
~/.quota-beat/logs/launchd.stdout.log
~/.quota-beat/logs/launchd.stderr.log每次 provider kick 调用还会追加一条 JSON Lines 记录到:
~/.quota-beat/logs/kick.jsonl每条记录包含 provider 字段(claude 或 codex)、调用是否成功、退出码,以及 stdout/stderr 的简短摘要。
常见问题
qbeat status 显示 "Not installed"
重新运行 qbeat install --time HH:MM。
升级到最新已发布版本
运行 npm install -g @yesongh/quota-beat@latest。
Node 路径变了(比如切换了 nvm 版本)
重新运行 qbeat install --time HH:MM 以捕获新的 process.execPath。
pmset 需要 sudo
install 和 uninstall 需要 sudo 来管理唤醒计划。可以先运行 sudo -v,或为 pmset 配置免密 sudoers 条目。
不要用 sudo qbeat install
请用普通登录用户执行 qbeat install --time HH:MM。qbeat 会在内部只为 pmset 那一步提权,而 launchd 注册必须留在你的用户 gui/<uid> 域里。
验证 launchd 任务是否已加载
launchctl print gui/$(id -u)/com.quota-beat.kick验证 pmset 唤醒计划
pmset -g sched开发
# 运行测试
npm test
# 完整 macOS 验证
sudo -v
node bin/qbeat.mjs install --time 07:00
node bin/qbeat.mjs status
pmset -g sched
launchctl print gui/$(id -u)/com.quota-beat.kick
node bin/qbeat.mjs uninstall许可证
MIT
