# pi-keepaware **Repository Path**: zxh126/pi-keepaware ## Basic Information - **Project Name**: pi-keepaware - **Description**: Keep the host from idle sleeping while a pi process is running (pi extension, pervigil-based). - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-24 - **Last Updated**: 2026-10-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # pi-keepawake [![npm](https://img.shields.io/npm/v/pi-keepawake.svg)](https://www.npmjs.com/package/pi-keepawake) [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [English](./README.md) | **简体中文** > 一个 [pi](https://pi.dev) 扩展:**只要还有 pi 进程在运行,电脑就不会进入睡眠/休眠**。 > 熄屏(显示器休眠)和锁屏照常工作,不做任何干预。 零配置:装好就生效。MIT 许可。 --- ## 特性 - **进程级语义**:从 `session_start` 持有到 `session_shutdown`,也就是「pi 还开着就拦睡眠」。 每个 pi 进程各持一把独立的 OS 断言,由操作系统聚合 —— 开 3 个 pi,关掉 2 个,机器照样不睡。 - **只拦系统睡眠**:不加 `ES_DISPLAY_REQUIRED`(Windows)、不加 `-d`(macOS)、 不拦 `idle` / `handle-lid-switch`(Linux)。**熄屏可以,锁屏可以**。 - **零配置**:无 flag、无环境变量、无命令。 - **fail-safe**:容器里、没有 PowerShell、平台不支持时,pi 照常运行,只在 TUI 里警告一次。 - **跨平台**:Windows / macOS / Linux 都走系统自带机制,不需要管理员权限、没有 native addon、不需要 node-gyp。 - **可观测**:TUI footer 显示 `☕ keep-awake`;底层 helper 进程和命令行都能直接查(见下文)。 - **不残留**:正常退出、Ctrl-C、`process.exit()` 都会释放;OS 原语被杀后会自动重挂。每次 reload / 会话切换之后的 `session_start` 会先清扫「同一 pi 进程内上一个运行时」遗留的 helper, 所以 reload 不会多留一把锁。 ## 安装 需要 Node.js ≥ 20(pi 自带)。 ### 1. 从 npm 安装(推荐) ```bash pi install npm:pi-keepawake ``` ### 2. 从 Gitee 安装 ```bash pi install git:gitee.com/zxh126/pi-keepaware ``` 以上两种方式 pi 都会自动安装依赖(`pervigil`)。装完 `pi list` 能看到它,`/reload` 生效。 需要钉死版本时写全:`pi install npm:pi-keepawake@1.0.0`。 ### 3. 手动放进用户扩展目录 ```bash git clone https://gitee.com/zxh126/pi-keepaware "$HOME/.pi/agent/extensions/keep-awake" cd "$HOME/.pi/agent/extensions/keep-awake" && npm install ``` Windows 对应路径是 `%USERPROFILE%\.pi\agent\extensions\keep-awake`。 pi 会自动发现 `extensions/` 下所有含 `index.ts` 的子目录。 > 本地目录形式的包 pi **不会**替你装依赖,所以这一步的 `npm install` 不能省。 ### 4. 只试用一次 ```bash pi -e npm:pi-keepawake pi -e git:gitee.com/zxh126/pi-keepaware pi -e ./pi-keepawake # 本地路径,需先 npm install ``` ### 卸载 ```bash pi remove npm:pi-keepawake pi remove git:gitee.com/zxh126/pi-keepaware ``` 或者直接删掉 `~/.pi/agent/extensions/keep-awake` 目录。 ## 它到底做了什么 扩展本身只负责「什么时候持有/释放」;真正和操作系统打交道的是 [pervigil](https://www.npmjs.com/package/pervigil)(零依赖、无 native addon、MIT)。 | 平台 | 机制 | 具体参数 | | --- | --- | --- | | Windows | 一个 PowerShell 子进程调用 `SetThreadExecutionState`,然后阻塞住保住该线程 | `ES_CONTINUOUS \| ES_SYSTEM_REQUIRED`(**没有** `ES_DISPLAY_REQUIRED`) | | macOS | `caffeinate(1)` | `-i`(**没有** `-d`) | | Linux | `systemd-inhibit(1)`,没有 systemd 时退回 `/sys/power/wake_lock` | `--what=sleep --mode=block`(**没有** `idle`、`handle-lid-switch`) | 生命周期: ``` session_start ──▶ acquire ──▶ [ 整段会话都持有 ] ──▶ session_shutdown ──▶ release │ └─ helper 意外死亡 ⇒ primitiveDied ⇒ 自动重挂(最多 5 次) ``` 补充说明: - 不用改电源计划(`powercfg`)、不用 presentation mode、不模拟输入 —— 所以锁屏和屏保都不会被顶掉。 - 用户**主动**点「睡眠/休眠」不会被阻止,这是系统断言的语义,也是本扩展刻意保留的行为。 - 容器里(`/.dockerenv`、`container` 环境变量等)pervigil 直接 no-op,不会报错。 ## 验证它在工作 最直观的:pi 的 footer 出现 `☕ keep-awake`。 命令行验证(用系统自身的视角看断言是否存在): **Windows**(PowerShell,无需管理员) ```powershell Get-CimInstance Win32_Process -Filter "Name='powershell.exe' OR Name='pwsh.exe'" | Where-Object { $_.CommandLine -like '*Pervigil*' } | Select-Object ProcessId, ParentProcessId, @{ n = 'flags'; e = { @( if ($_.CommandLine -match 'ES_SYSTEM_REQUIRED') { 'ES_SYSTEM_REQUIRED' } if ($_.CommandLine -match 'ES_DISPLAY_REQUIRED') { 'ES_DISPLAY_REQUIRED' } ) -join ',' } } ``` pi 运行期间应该恰好出现一个 helper,`flags` 为 `ES_SYSTEM_REQUIRED`(**不含** `ES_DISPLAY_REQUIRED`); pi 退出后它应该消失。 > `powercfg /requests` 也能看到 request,但它**需要管理员权限**,普通终端里跑会直接报错。 **macOS** ```bash pmset -g assertions | grep -i caffeinate ``` **Linux** ```bash systemd-inhibit --list | grep -i pi ``` ## 已知限制 - **Windows 上常驻一个 PowerShell 进程**(实测 WorkingSet ≈ 74 MB / Private ≈ 59 MB)—— 这是「整个会话都持有」这个语义的直接成本,pi 退出时回收。 - Linux 需要 systemd 用户会话(`systemd-inhibit`)或可写的 `/sys/power/wake_lock`;否则降级为 no-op 并警告一次。 - 不阻止合盖休眠(Linux 的 `handle-lid-switch` 未加入 inhibitor)、不阻止用户主动睡眠。 - 仅本仓库在 **Windows 11 实机**上验证过(helper 出现/释放、多进程聚合、helper 被杀后重挂、硬杀不残留)。 macOS / Linux 的代码路径按 pervigil 的语义核对过,但**没有实机运行记录**。 - pi 被以无法被捕获的方式强杀(TerminateProcess / OOM)时,扩展自身的清理钩子不会执行; 本机上实测 helper 会随父进程一起消失,另外扩展在每次 `session_start` 时会顺手清理 「父进程是本进程」的遗留 helper(reload 未能走 `session_shutdown` 的情况)以及「父进程已死」的 历史 helper 作为兜底;其他存活进程的 helper 一律不动。 ## 开发 ```text pi-keepawake/ ├── index.ts # 扩展本体(唯一源码) ├── package.json # pi 清单:pi.extensions -> ./index.ts,依赖 pervigil ├── LICENSE # MIT ├── README.md # 英文版 └── README.zh-CN.md # 本文件 ``` - 扩展运行在 pi 进程内,走 pi 的 jiti loader,**不需要编译**。 - 只有 `pervigil` 一个运行时依赖;pi 提供的 `@earendil-works/*` 包只用 `import type`,不进 `dependencies`。 - 改完在 pi 里 `/reload` 即可生效;想临时试装可以 `pi -e <本地路径>`。 涉及的关键 pi 事件:`session_start`(创建 wake lock 控制器并 acquire)、 `session_shutdown`(释放并清 footer 状态)。运行期复用 pervigil 的 `primitiveDied` / `degraded` 事件做重挂与告警。 发布流程(维护者):改 `package.json` 的 `version` → 提交 → 推 Gitee → `npm publish --registry=https://registry.npmjs.org` (本机 `.npmrc` 的默认 registry 指向 npmmirror 镜像,只影响安装、发布必须显式指定官方源)。 ## 依赖与致谢 - [pervigil](https://github.com/rejifald/pervigil) — 跨平台 sleep inhibitor(MIT,作者 Oleksandr Zhuravlov)。 - [pi](https://pi.dev) — 扩展宿主。 ## License [MIT](./LICENSE) © 2026 zxh126