服用注意 ・ 适用于你入睡后仍需保持戒备的机器。
现在是凌晨3点。你已入睡。但智能体没有——它仍在处理你几小时前启动的一个会话中思考着,而你已合上盖子,仿佛一只无法完全闭合的眼皮。Caffeinate 和 Amphetamine 是兴奋剂:它们让机器永远保持通电状态,无论是否有人在使用。Adrafinil 是一种促清醒剂。它只有在智能体获取它时才会起作用,仅在该工作持续期间让合盖的 Mac 保持唤醒,并在最后一个会话释放时立即解除。它只为工作而唤醒——然后你们一同入睡。♡
仅当 AI 智能体在工作时才让 Mac 保持唤醒。
Adrafinil 是一个 macOS 菜单栏应用,仅当 AI 编程智能体有活跃会话时阻止系统睡眠——包括合盖睡眠。当没有智能体工作时,睡眠行为不受影响:合上盖子,Mac 正常睡眠。
这与 caffeinate 或 Amphetamine 等始终唤醒的实用工具相反。Adrafinil 仅在智能体(如 Claude Code、Codex、Cursor……)处于任务中时介入,并在工作完成那一刻立即退出。
⚠️ 特权级睡眠控制。覆盖合盖睡眠需要 root 权限。Adrafinil 将其隔离在一个小巧且经过审计的辅助程序中,该辅助程序仅暴露 setSleepBlocked(Bool) ——所有策略都运行在一个无特权的守护进程中。它利用标准的 IOPMAssertion 来控制空闲睡眠,并在验证设备上更干净的私有 IOPMrootDomain 路径无法让无显示器的合盖 Mac 保持唤醒后,使用 pmset disablesleep 控制合盖睡眠。详见 Docs/ARCHITECTURE.md §2。
功能特性
- 感知智能体,而非始终开启。仅当 ≥1 个智能体会话持有断言时才会阻止睡眠。零会话 → 正常睡眠,包括合盖。
- 对 9 种智能体的钩子集成。一键安装程序将 Adrafinil 接入以下智能体的钩子系统:Claude Code、Codex、Cursor、Gemini CLI、Aider、Hermes、OpenCode、Cline 和 Pi。
- 亚 50 毫秒 CLI。adrafinil 的 acquire/release 通过智能体钩子调用,与守护进程往返一次耗时不超过 50 毫秒,因此不会拖慢智能体的工作流。
- 基于引用计数的断言。重叠的会话会干净地叠加;只有当最后一个会话释放时,休眠才会解除阻塞。
- 热切断。若合盖状态下皮肤/CPU 温度超过阈值,所有断言将被强制释放,避免装在包里的 Mac 因过热自毁。
- 空闲释放。拥有断言的进程已死亡或连续 N 分钟 CPU 空闲时,断言会被自动丢弃。
- 进程嗅探(可选)。即使未安装钩子,守护进程在检测到已知的智能体二进制程序运行时,也能自动获取断言。
- 合盖提示音 + 开盖摘要。合盖时会发出一声提示音,确认断言已持有(屏幕已关,故无通知);重新开盖后会显示你离开期间运行了哪些内容、峰值温度以及热切断是否触发。
- 干净卸载。移除它在所有智能体配置中添加的每一个钩子条目。
系统要求
- macOS Tahoe 26.4。我正是在此版本上构建和测试的;它很可能也能在更早的 26.x 版本上运行,但我未在那上面测试过。
- 构建需要 Xcode 26+,并启用 Swift 6 严格并发。
- 标准安装需要管理员权限(特权助手通过 SMAppService 安装)。非管理员安装路径会将 CLI 放在 ~/.local/bin 而非 /usr/local/bin。
下载
下载 Adrafinil——一份已签名、已公证的磁盘映像。打开它,将 Adrafinil 拖入“应用程序”文件夹,然后启动。首次启动时会一次性请求管理员权限以注册特权助手。需要 macOS 26.4 或更高版本。
更倾向于自行构建?请参阅“构建”部分。
构建
git clone https://github.com/kageroumado/adrafinil.git
cd adrafinil
open Adrafinil.xcodeproj在 Xcode 中,选择 Adrafinil 方案并运行。你需要设置一个开发团队用于代码签名——守护进程(LaunchAgent)和助手(LaunchDaemon)被嵌入应用包中,并在应用启动时向系统注册。(源代码中未固化 Team ID;XPC 调用者检查会在运行时读取你自己的签名团队,因此用任意开发者 ID 重新构建后,其自身组件无需修改代码即可获得授权。)
对于不依赖本地签名身份的无头编译检查:
xcodebuild -project Adrafinil.xcodeproj -scheme Adrafinil -configuration Debug \ -destination 'generic/platform=macOS' \ CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY='' build
共享逻辑作为独立的 Swift 包进行构建和测试:
cd AdrafinilShared swift test
工作原理
智能体不会直接与 Adrafinil 通信。每个智能体的钩子系统会调用捆绑的 CLI:
adrafinil acquire <session-key> --tool claude-code --reason "long build" # when a turn starts adrafinil release <session-key> # when the agent goes idle
保持锁定是活动范围的,而非会话范围的:Claude Code 在 UserPromptSubmit 时获取,在 Stop 时释放,因此 Mac 仅在智能体实际工作时保持唤醒——当会话打开但空闲时,提示状态下可以让 Mac 正常休眠。
守护进程按会话键进行引用计数,并在计数非零时请求辅助程序阻止休眠。
智能体还可以通过带时间限制的保持锁定,让 Mac 为超出其回复时效的后台任务(如长时间的构建或部署)保持唤醒——要么直接调用 adrafinil hold,要么对于支持 MCP 的智能体,通过 Adrafinil MCP 提供绑定的 MCP 工具:
adrafinil hold --for 30m --reason "deploy" # keep awake up to 30 min, then auto-release adrafinil mcp # speak the Model Context Protocol on stdio (for agents)
其他子命令:status、install-hooks、uninstall-hooks、daemon-status、version。
架构
四个产品跨越三个权限层级(完整细节,包括 Xcode 项目布局,见 Docs/ARCHITECTURE.md):
┌──────────────────────────────────────────────────────────────┐
│ Adrafinil.app (menu bar app, user-facing) │
│ • Status item, settings, installer GUI, lid-open summary │
└─────────────────────────────┬────────────────────────────────┘
│ XPC
▼
┌──────────────────────────────────────────────────────────────┐
│ AdrafinilDaemon (LaunchAgent, runs as user, always-on) │
│ • Reference-counted assertion registry │
│ • Process watchers (kqueue NOTE_EXIT + periodic sweep) │
│ • Thermal monitor (SMC) • Lid-state monitor (IORegistry) │
│ • Lid-close chime • CLI socket at …/Adrafinil/cli.sock │
└─────────────────────────────┬────────────────────────────────┘
│ XPC (privileged Mach service)
▼
┌──────────────────────────────────────────────────────────────┐
│ AdrafinilHelper (SMAppService LaunchDaemon, root) │
│ • The ONLY component that touches sleep-blocking APIs │
│ • setSleepBlocked(Bool) + read-only state/version │
│ • Verifies caller's code-signing requirement │
└──────────────────────────────────────────────────────────────┘
adrafinil (CLI, ships inside the .app, symlinked onto PATH)
• acquire / release / hold / mcp / status / install-hooks / uninstall-hooks
• Connects to the daemon socket; <50ms round-trip
- AdrafinilShared——一个跨所有目标共享的 Swift 包:数据模型(AgentKind、Assertion)、IPC 有线格式、AssertionRegistry、CallerVerifier、钩子安装规范以及 CLI 参数解析器。单元测试就在这里。
- Helper 保持简单,便于审计。它不持有策略——引用计数、温控、空闲和盖子逻辑全部位于守护进程中。特权接口是一个单一的变体端点加上只读内省。
- 守护进程是事实来源。应用是纯视图层;它可以自由退出和重新启动,而不会影响已持有的断言。
值得注意的怪癖
- 公共 IOPM 断言无法阻止合盖休眠。使用公共类型(以及 caffeinate)的 IOPMAssertionCreateWithName 不会让合盖的 Mac 保持唤醒。Adrafinil 的 v1 版本使用 pmset disablesleep 1,这很粗暴(也会禁用空闲休眠),并且必须在关机时清除,否则会泄漏——Helper 在重新应用状态之前,会在重生时重置为 disablesleep 0。
- 守护进程处理程序在任意队列上运行。XPC 和套接字回调可能到达任意调度队列,因此断言注册表和共享状态会相应地进行同步。在修改守护进程时,要小心处理并发问题。
- CLI 有严格的延迟预算。acquire/release 处于每个智能体会话的热路径上,因此使用静态查找(如 `AgentKind.allBinaryNames`)以及轻量的套接字协议,而不是完整的 XPC 来连接 CLI 与守护进程。
许可证
MIT。你可以自由使用,不提供任何担保。
致谢
由 @kageroumado 构建,发布于 kagerou.glass。名称灵感来源于阿屈非尼(adrafinil)——一种促进清醒的前药——因为这款应用只在实际有任务需要处理时才会保持你的机器保持唤醒状态。