npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arkkwang/pi-cron

v0.1.1

Published

Lightweight local scheduler for the Pi CLI

Readme

English | 简体中文

pi-cron

面向官方 Pi CLI 的本机轻量调度器:配置热更新、任务去重、不重叠执行与超时控制。

独立 Node 轮询进程,不依赖 Pi 的 scheduler 插件;源码附带 Bash 入口;每次到期调用 PATH 中的 pi,参数原样传递,不再定义模型、provider 等包装字段。

启动

Windows 使用 Git Bash;macOS 使用 Bash。两端均需 Node.js 22.19+、npm,以及 PATH 中可用的 pi。

推荐通过 npm 安装(不会安装 Pi、启动服务或创建任务):

npm install -g @arkkwang/pi-cron
pi-cron ls -f /path/to/tasks.json
pi-cron start -f /path/to/tasks.json

精简 Linux 镜像还需安装 procps(例如 Debian/Ubuntu 的 apt-get install procps),为进程树终止提供 ps。只有 Node 和 Pi 的容器不足以支持超时处理。

主要用于自动执行 Agent 任务,任务参数仍是原生 Pi CLI 参数。源码运行:

cd pi-cron
npm ci
bash pi-cron ls -f /path/to/tasks.json     # 只读列出任务和最近记录
bash pi-cron start -f /path/to/tasks.json  # 前台常驻

必须用 -f 显式指定配置,没有默认路径;相对路径以调用者当前工作目录为基准。包不附带私人任务或 runtime 文件。可用 bash /absolute/path/to/pi-cron/pi-cron ... 从任意目录调用,保留当前工作目录。

只在前台运行,不自动设置开机启动或后台服务。切换前请停用旧调度器,避免重复执行。依赖 PATH 中的官方 Pi CLI(@earendil-works/pi-coding-agent),无需修改 Pi 本身。

只有 ls 和 start 两个命令。子命令与 -f 顺序不限,例如 ./pi-cron -f ../../tasks.json ls 与 ./pi-cron ls -f ../../tasks.json 等价。ls 按每个任务一段纯文本展示,不输出表格;不获取单例锁,不创建或修改 runtime;调度器运行时也可查询。列表的 lastStatus 是磁盘中保存的最近状态,不代表进程仍然存活;nextRun 是按当前配置算出的下一次计划时间,nextRun/lastRun 均按本机时区展示,不保证一定执行。start 启动前也会校验配置。

两份数据文件

-f 指定的 tasks.json 是任务数组,唯一的配置来源。示例(自行保存到包目录之外):

[
  {
    "id": "daily-check",
    "cron": "0 9 * * *",
    "enabled": true,
    "timeoutSeconds": 420,
    "args": ["--model", "provider/model", "--thinking", "medium", "--print", "--", "执行每日检查"]
  }
]
  • id、五段 cron、args 必填;id 会出现在日志与 runtime 记录里,用人类可读的短标识(如 daily-check),不要用 UUID;cron 时间按本机时区解释。
  • enabled 默认 true;timeoutSeconds 默认 1800 秒。所有对外超时配置均以秒为单位。
  • cwd 可选,相对路径以 tasks.json 所在目录为基准;省略则用该目录。支持绝对路径,但共享配置应避免机器专属盘符路径。不展开 ~ 或环境变量。
  • args 就是 Pi CLI 参数数组。非交互任务请包含 --print;prompt 前可用 -- 结束选项解析。无需配置 command 或 Node/Pi 安装路径。
  • 配置在启动时读取并校验;之后每次轮询比对文件的修改时间与大小,变了就重新读取解析:保存即生效,增删任务、启用停用、改时间都不需要重启。重载成功日志只在解析后的配置指纹变化时输出;原样重存、touch 或仅修改缩进不记录,字段顺序变化仍视为变化。运行中读到非法或读不到的文件时保留上一份可用配置,在 stderr 报一次错(同一份坏文件不会每秒刷屏),不退出;修好保存后自动生效。ls 每次读取磁盘上的配置。

tasks.runtime.json 在配置文件旁自动创建、仅由调度器写入,不随包分发:按任务 ID 保存最后触发时间、状态、起止时间、退出码及最多 4000 字符的输出尾部。时间戳为本机时区的 ISO 8601,带偏移(如 2026-09-30T11:30:00.489+08:00);读取兼容 Z 结尾的历史 UTC 记录。不保存完整历史,也不是通知渠道。写入使用临时文件加 rename,避免半份 JSON;损坏的 runtime 会阻止启动,不会偷偷清空去重记录。不要手动修改运行中的 runtime。

固定规则

  • 每秒轮询,分钟精度;同一任务同一分钟最多触发一次,包括同分钟重启。
  • 热更新只替换任务定义:已在运行的任务不打断,跑到结束;删掉或停用的任务在本次运行结束后不再触发;改 args/timeoutSeconds 下次运行生效。重载不重置去重记录,所以本分钟已触发过的任务不会因重载再触发一次;新增任务若 cron 命中当前分钟且本分钟未跑过,会立即执行。
  • 停机、休眠错过的分钟跳过,不补跑。若在计划分钟内启动,仍会执行该分钟的任务。
  • 同任务不重叠,重叠的触发直接跳过;不同任务可并行。
  • 先持久化触发记录,再启动 Pi;启动失败或进程中断不自动重试。不承诺 exactly-once。
  • 到期执行前立即输出 starting 日志,包含实际时间、任务 ID 和计划触发时间;结束日志包含实际时间、结果和退出码。日志与 runtime 中的时间戳均为本机时区 ISO 8601(带偏移)。starting 表示开始尝试启动 Pi,不代表模型已开始处理。
  • 超时尝试终止任务进程树并记录 timeout。终止失败会报错并停止新调度,等待任务结束或人工处理,不假报成功。
  • SIGINT/SIGTERM 停止新调度,等待当前任务结束(其超时仍有效)。终端关闭/强制结束不保证走完优雅退出。
  • 重启时遗留的 running 标为 unknown:无法证明旧进程已退出。异常终止后,人工确认旧任务已结束再启动,避免遗留进程重复执行。
  • 用本机 127.0.0.1:17391 的监听占位保证单实例,不提供网络 API,也无需额外锁文件;端口被占用会明确失败。
  • 暂不支持一次性任务、重试队列和原会话投递。

依赖与验证

只复用 croner 的时间计算,不使用其调度引擎;cross-spawn 处理跨平台 PATH/命令启动;tree-kill 处理 Windows/macOS/Linux 的进程树终止差异。本项目不维护 Windows 专用分支。进程库内部会使用各系统的原生命令,不代表依赖一个仅支持 Windows 的方案。

npm test

测试将调度时钟固定在同一分钟,避免跨分钟误报;通过测试 preload 将单例监听映射到 OS 分配的临时端口,同一用例的后续进程复用该端口验证互斥与重启,不占用生产端口,也不要求停止常驻调度器。等待执行结果前先确认启动成功,提前退出时直接报告进程输出。日志专用用例禁用任务,覆盖原样重存、格式变化、实际字段变化、损坏配置及恢复,并观察多个轮询周期确认没有重复日志;真实子进程和定时器在综合用例中照常运行。测试仅运行 pi --version / pi --help,不调用模型或发送通知;覆盖到期计算、去重、非法配置、超时单位、实际启动与失败、配置热更新(非法配置保留旧值且只报一次)、单例、输出截断、重启去重及损坏状态文件。

已在 Windows Git Bash + Node 22 实测;macOS/Linux 尚未实测。每秒轮询先比对配置文件的时间戳与大小,只有变化时才重新读取解析;其余时间只检查内存中的任务是否到期。

边界与安全

每台机器只允许一个实例(固定本地端口 17391),同目录配置共用 tasks.runtime.json。不同配置不是独立实例隔离单元。

任务以当前用户权限运行 Pi,可能修改文件、调用工具并产生模型费用。仅运行可信任务配置;runtime 保存的输出尾部可能包含敏感内容,不应提交或公开。不提供沙箱、自动重试、补跑、完整历史或 exactly-once 保证。

相关项目

  • pi-snap:帮助人和 Agent 快速定位会话问题。
  • pi-subagent:派发、观察和继续指挥子 Agent。

License

MIT