Appearance
它解决什么
"每天打开某个网页点一个按钮"这件事,现有做法各有过不去的坎:crontab 加手写脚本要把凭据写进文件或 env,失败只给你一行退出码,页面改版了你不会知道,直到某天发现连续 30 天没签到;浏览器插件定时则机器一锁屏就停;RPA 或 LLM 自动化平台为一天一次的点击引入常驻服务、向量库和模型调用,成本和不确定性都远超问题本身。
Automation 的取舍是:执行层就是 Playwright 脚本加 launchd,中间没有任何层。产品价值集中在两件事上——录制的门槛,和结果能不能自己看懂。
它不是什么
不是云服务,不是机器人平台,不是 LLM 代理,也不是通用脚本调度框架。macOS 本机跑,只监听回环地址。
五条原则(从代码里读出来的,不是愿望)
- 无事可做不等于失败。 脚本遇到"今天没有可领的东西"应当成功退出并写明原因,而不是报警。反过来同样成立:没跑不能伪装成"无事可做"——上一轮被强杀留下的锁会被接管,运行记录带上
lockStale: true,而不是每天报一个skipped加退出码 0。 - 失败必须能自己看懂。 每个错误带
code、人话error和hint;服务端异常直接指向具体日志文件。 - 凭据不出机器。 口令只进 macOS Keychain;登录态存在任务自己的
auth.json(权限 0600);界面和接口都不回显口令。 - 不提供任意命令执行。 接口只能操作登记表里已有的任务,没有 shell 入口。
- 默认值要能直接活。 零 npm 依赖就能起服务,前端构建产物随源码入库,一条
cp加一条npm start就能看到界面。
代码与数据的三区划分
这个划分决定了什么东西会进版本库,是它最主要的隐私机制:
| 区 | 内容 | 是否入库 |
|---|---|---|
manager/ lib/ docs/ | 通用引擎:后端、前端、共享模块。不含任何具体站点的适配代码 | 是 |
private/ | 你自己按站点写的 runner 与入口脚本(含目标站点域名、判定标记、本机路径) | 否,.gitignore 一行挡住整棵目录 |
var/ | 运行期个人数据:登记表、录制脚本与登录态、日志与失败取证截图、浏览器 Profile | 否,同上 |
排除规则写在入库的 .gitignore 里,而不是 .git/info/exclude——后者不随仓库走,重新克隆后就没了,再来一次 git add -A 就会把站点名和账号写进 git 历史,而历史是 .gitignore 事后清不掉的东西。所以这条边界靠 private/ 与 var/ 两个目录名成立,不依赖任何只存在于单台机器上的配置。
明确不背的责任
- 不针对任何第三方站点做合规评估。 本工具能自动化任何网页,但目标站点的服务条款是否允许脚本化访问,由使用者自己确认并承担后果。作者未做这项评估,也不为任何具体站点的用法背书。
- 示例只用内置演示站点。 仓内自带的本地假站点(
/demo/)专门用来演示录制与状态判定,不联网、不含任何真实站点。 - 只支持 macOS。 没有 Linux / Windows 路径,定时、凭据、进程托管都建立在 launchd 与 macOS Keychain 上。
- 不为团队服务。 多机同步、服务器部署是写进"非目标"的,不是待办。