Install
openclaw skills install @bonniegeng-max/future-journal每日三分钟的书写工具——生成一本可离线填写的电子手账:先描(或照着打)一句引导句,再用过去时写下今天希望发生的事,最后挑一个心情词。49 天一轮、每周一个主题,含 49 句原创引导句库、质量闸门与页面回归测试。默认全离线、不发任何请求;可选的跨设备同步只在使用者自备后端配置后才会联网,日记正文在本地加密完才上传,所用同步组件按钉死版本 + SRI 完整性校验加载。Generate an offline single-file daily journal page (49-day cycle, weekly themes, trace-or-type a guided sentence then write in the past tense) with a bundled original prompt library and quality gates. Use when the user wants a fillable diary or journal page, a 未来日记 / 提前日记 / 晨间日记 / 感恩日记 tool, a printable journal, or asks what sentence to write today. Not for 任务与待办管理、日程排程、心情打卡统计,也不做心理健康或危机干预——本工具只提供书写页与引导句,不诊断、不建议、不替用户做决定。适用于「想开始写未来日记」「想要一本能打印的手账」「今天该写哪一句」「想用过去时写愿望」「总往坏处想、想把自己拉回来」「想在平板上用触控笔描一句」「想电脑手机换着写」等场景。
openclaw skills install @bonniegeng-max/future-journal一个单页、离线、手机优先的电子手账。每天三分钟,三步:
49 天为一轮,每周换一个主题(小确幸 → 身体节奏 → 关系 → 作品 → 金钱 → 空间 → 未来已来的我)。
方法与节奏参考山田弘美、滨田真由美所著的日记实践书。本工具不是该书的官方产品, 49 句引导句全部为原创,书中正文内容未被使用。
| 文件 | 作用 |
|---|---|
assets/index.html | 完整的手账页面。单文件、双击即可打开;不配同步时全程离线、不发任何请求 |
references/DESIGN.md | 暖纸手账设计系统 + 无障碍基线。改页面前先读这个 |
scripts/today.js | 算今天是第几天、本周主题、今天要描哪一句 |
scripts/check-prompts.js | 引导句质量闸门。改句库后必跑 |
以上 5 个文件(含 SKILL.md 自身)是 skill 的完整能力面,发放给别人的就是这些。
| 文件 | 作用 |
|---|---|
scripts/test-journal.js | 页面回归测试(数据不丢 / 键盘可达 / aria / 降级路径) |
它依赖 jsdom(开发期依赖),属于「改这个仓库的人用的」,不是「装这个 skill 的人用的」。
不要把它打进 ClawHub 发布包 —— 维护者工具混进发布包被判过
suspicious / DO_NOT_INSTALL(见 MAINTAINING.md 里记的那次教训)。
改句库:
node scripts/check-prompts.js
改页面逻辑或样式(仓库内,需要 jsdom):
node scripts/check-prompts.js
NODE_PATH=~/.workbuddy/binaries/node/workspace/node_modules node scripts/test-journal.js
两个都要退出码 0。
test-journal.js 覆盖三组:A 数据不丢(打字自动落盘 / 刷新还原 / 防抖窗口内切 tab)、
B 无障碍与键盘可达、C 拿不到 2D 上下文时的降级。
一个顺手的巧合:jsdom 不实现 canvas 2D,
getContext('2d')恒返回null, 所以 C 组那条降级分支在 jsdom 里是被真实执行的,不是 mock 出来的。
把这个文件复制到用户指定的位置就行,它没有任何依赖:
cp assets/index.html ~/Desktop/未来日记.html
file:// 协议下完整可用)future-journal-v1不要为它起本地服务器。 页面不依赖服务器就能完整使用(唯一的例外是可选同步), 起服务器只会带来额外故障点。
例外:想用「跨设备同步」就必须走线上网址 —— 见下面的「同步」一节。
node scripts/today.js 2026-09-17 # 以该日期为第 1 天,算到今天
node scripts/today.js 2026-09-17 --day 8 # 直接指定第几天
输出第几天、本周主题、今天要描的句子。用户想写在实体本子上时用这个。
49 句内嵌在 assets/index.html 的 <script id="prompt-data"> JSON 块里。
编辑后必须跑校验,退出码 0 才算通过:
node scripts/check-prompts.js
检查项:7 周 × 7 句的结构、重复句、将来时标志词、句末情绪词、单句长度 ≤ 30 字。
时间锚点 + 一件具体的好事 + 完成态 + 句末情绪词
今天的活一件件推进了,我很安心。我希望今天工作顺利。 ← 将来时,方法明确要求写过去时中文没有时态标记,肉眼判断「是不是过去时」极不可靠,所以校验脚本用 禁止将来时标志词这条硬规则兜底。不要跳过。
默认情况下,页面数据只存在用户浏览器的 localStorage 里,skill 读不到。因此:
跨设备同步是可选功能,且必须先发布到线上网址,见下一节。
页面内置了「账号登录 + 端到端加密」的跨设备同步,但有三条硬约束:
只在线上网址可用。 判断依据是 location.protocol:file: 开头时页面会直接提示
「联网同步要在发布后的网址上用」,且不加载 SDK。双击本地文件打开 = 纯本地模式,
这和以前完全一样,不要因此认为页面坏了。
需要先激活云服务并建表。 表是 journal_sync,一人一行,只存密文:
id BIGINT identity PK / owner_id TEXT DEFAULT auth.uid() UNIQUE
cipher TEXT NOT NULL / updated_at TIMESTAMPTZ
owner_id 由数据库默认值填充(TEXT,不是 uuid),客户端永远不要发这个字段。
RLS 要同时给 GRANT 和 POLICY 两道,缺一不可。
加密在浏览器里做,服务器只有密文。 PBKDF2 20 万次派生 AES-GCM-256 密钥,
密钥存本机 localStorage(fj-dk),不上传。所以同步密码丢了,云端那份就解不开,
本机记录不受影响 —— 这句话必须原样告诉用户,不能含糊。
其他约定:
schedulePush),不是每次按键mergeStates 合并:按天取 at 较新的一条,「3 个想要的」按文本取并集upsert —— 因为 owner_id 是数据库默认值,
客户端不知道值,onConflict 无从下手配置串(endpoint + publishableKey)存在本机 fj-cfg,用户换设备时粘贴一次即可。
看起来最顺手的「优化」是把 endpoint / publishableKey 直接内嵌进 assets/index.html,
这样用户就不用粘贴了。绝对不要这么做。
这个页面是要分发给别人的 skill 资产。一旦写死,任何装了这个 skill 的人打开页面都会连上 同一个后端——虽然 RLS 按用户隔离、彼此看不到内容,但陌生人会在号主的环境里注册账号、 消耗号主的配额。作者自己用着舒服的代价,是所有人的数据都涌向同一个人的账上。
配置串必须由使用者自己提供(fj-cfg 或设置页粘贴)。号主自己的那份也走同一条路——
把配置串放在 skill 目录外面的文件里,这样它永远不会随 skill 分发出去。
发布审核最容易被卡的点不是「有联网」,而是声称与实际不符。所以这里列全, 一个不漏 —— 如实罗列比写得含糊安全。
| 行为 | 何时发生 | 去向 | 传了什么 |
|---|---|---|---|
| 下载云同步 SDK | 仅当使用者自己粘贴了配置串、且页面从 http(s):// 打开 | cdn.jsdelivr.net 上的 @tencent-ai/workbuddy-cloud-sdk(版本号钉死 + SRI 完整性校验) | 只下载代码,不上传 |
| 发验证码 / 维持登录态 | 使用者主动点登录 | 使用者自己配置的后端 | 邮箱、会话令牌(会离开设备) |
| 上传日记 | 使用者设了同步密码之后写入内容 | 使用者自己配置的后端 | 只有密文(在本机加密完才发) |
这个表以外,没有别的:
endpoint / publishableKey 一律由使用者自备file:// 打开,一个网络请求都不发(SDK 根本不加载)scripts/today.js、scripts/check-prompts.js、references/DESIGN.md 全程纯本地assets/index.html 里的 SDK_URL / SDK_SRI 是一对必须同进同退的常量:
var SDK_URL = '…/@tencent-ai/workbuddy-cloud-sdk@<具体版本>/lib/index.global.js';
var SDK_SRI = 'sha384-<该版本文件的 sha384>';
为什么这条是硬约束:这段远端代码和页面同源执行,能读到 localStorage 里的日记正文、
fj-cfg 里的后端地址与 key、以及导出的加密密钥 fj-dk。所以「加载哪一份」不能由 CDN
当下决定。用 @dev 这类漂移标签,等于审核时的那份代码和用户实际执行的可以是两份。
hashlib.sha384 对新文件重算哈希并写回 SDK_SRIonerror 会给出提示,不会留半截界面)scripts/test-journal.js 的 D 组会卡住这个约定;@dev / @latest 一出现就失败<script> 上的三个属性缺一不可:integrity(不放行改动过的字节)、
crossorigin="anonymous"(SRI 需要 CORS 取文件)、referrerpolicy="no-referrer"setAttribute 写而不是 s.integrity = …:后者的 IDL 反射不是所有引擎都有那句话「加载远程脚本」确实是扫描器会多看两眼的模式——所以页面把它做成 必须先有人粘贴配置串才会发生,不是打开就跑。这是刻意的,改的时候别把它提前。
不是 WorkBuddy 账号,也不是微信 / Google / Apple 之类 —— 是使用者自己那个云服务环境里的 终端用户账号,用邮箱当唯一标识,登录靠邮箱收到的 6 位验证码(也可以另外设密码)。
要说准的四点:
traced: true,traceMode 存方式。
触控板描摹是手眼分离,实测无法控制 —— 打字模式不是可选项,是必需项。S.entries[day].text,而 renderToday() 又会用已存的值覆盖输入框 —— 于是「打了一半切个
tab」或「直接刷新」就把正在写的内容丢了。现在有 5 个落盘点:输入防抖 500ms、
切 tab、pagehide、beforeunload、页面隐藏。切 tab 前必须先 flushWrite() 再渲染。
描摹和心情词本来即时存,写作框过去是唯一的例外,别再制造这个例外。renderSyncCard() 一处渲染:未填配置串 / 已填未登录 /
已登录待设同步密码 / 已连接。改同步相关文案只改这一个函数,别散到各处。--trace,#ABA492,2.20:1)—— 它的身份是"盖着描的底稿"不是正文,真按 4.5:1 加深,
描上去的笔迹就和底稿分不清了。等价路径已备齐:打字模式用弱墨(4.55:1)、打印版加深到 6.71:1。
别在别处复用 --color-trace。disabled + aria-label 上;
心情词的选中态落到 aria-pressed;当前 tab 落到 aria-current。
读屏读不出"底色深浅",只写 CSS 等于没做。canvas.getContext('2d') 会返回 null
(浏览器禁用画布、或 iOS Safari 画布上下文超限)。原来 openTrace() 直接 .font = …
就抛 TypeError,表现为点「用笔描」毫无反应。现在先探、拿不到就原地退回打字模式
并给一句人话。"点了没反应"比报错还差。:focus-visible 用 2px 赤陶 + 2px offset;赤陶底上的按钮换成主墨描边。
不要写 outline: none。默认简体中文(zh-CN),英文双语说明随包提供。界面与文档以中文为第一语言,英文可用。
skill-card.md);用户书写内容不限语言,中英文皆可;
页面字体栈按中英双语定义(西文回退 Georgia / -apple-system),中英混排不会掉字体。Scope statement (English) — Default locale is Simplified Chinese (zh-CN), with
English documentation bundled (skill-card.md). User entries are not
language-restricted: journal content may be written in Chinese or English. Font
stacks are bilingual and fall back to Latin families for English text. Other
interface languages or prompt libraries are available on request.
1.0.3 — 语言声明统一为**「默认中文 + 中英双语」口径(1.0.2 里写成「只支持中文、
不提供语言切换」的方向是错的,反而压不下 SQP-3)。全文按同一口径重写:
SKILL.md(新增「中英双语」条目)、README.md、assets/index.html(<html lang> 处)、
references/DESIGN.md(引言 + 字体栈旁,如实说明西文回退 Georgia / -apple-system、
中英混排不掉字体**)、scripts/check-prompts.js、scripts/today.js。
同时消除文档自相矛盾的「声称与行为不符」风险。
1.0.2 — 针对 ClawHub 安全扫描报告逐条复核后的修复(skillspector 13 条):
① 把「语言」声明升级成有界范围声明(Language & Locale Scope),并逐文件补齐 ——
assets/index.html、references/DESIGN.md、scripts/*.js 此前只有 SKILL.md/README.md
有声明,是 SQP-3 被判 MEDIUM 的原因(已有声明的那两个文件只判 LOW)。6 条 SQP-3 全部落到同一口径。
② 清掉包内全部 default-ignorable 码点(U+FE0F 变体选择符 5 处)与 references/DESIGN.md
里混入的希腊大写字母(U+0394,原本写在亮度符号前面)—— 这是 AE4(Unicode / 混写异常)的直接触发特征。
③ 6 条 AE1 经查证不予处理:源码显示它只在「被引用文件未被扫描器完整检查」时生成,
属覆盖率信号而非文件缺陷(已排除体积 / NUL / 编码 / 混淆四类真实成因),
消除它只能靠删引用 —— 那是刻意规避。
1.0.1 — 修掉 ClawHub 安全扫描的 suspicious:云同步 SDK 从漂移的 @dev 标签改为
钉死具体版本 + SRI 完整性校验(扫描报告 SDI-2);补齐「开启同步后哪些数据会离开设备」的
前端告知与文档说明(SDI-1);声明中文优先是有意为之(SQP-3)。回归测试新增 D 组,44 条全过。
1.0.0 — 首次发布。