1实现原理 · 为什么它能做到
整条链路的输入是 agent 自己的历史:找出用户的常态,把一次典型会话按发生顺序做成 40-70 秒的片子;素材是用户的原话,画面里的房间与桌面从 agent 对用户的了解里长出来。
The agent reads its own history with its user, finds their routine, and turns one typical session into a 40 to 70 s film, in the order it happened:
只有一份创作输入:story.json。编排(滑入、折叠、投掷、挥锤、蝶翼)由引擎 scenes/*.js 负责,agent 不该动;上屏的每一句都是引用,且渲染前每句都要用户批准。
Write `story.json` and the engine does the choreography. Nothing on screen is invented: every line is a quote, and the user approves every line before a frame is rendered.
取材是本地行为,且以用户明确同意为前置:harvest.py 读当前项目的 Claude Code(~/.claude/projects/<slug>/*.jsonl)与 Codex(~/.codex/sessions)记录,按「最典型」排序而不是「最戏剧」;每条消息带本地时间、类型猜测与敏感标记。
It prints the routine first: messages and minutes in a median session, the usual start time, the mix of kinds, and the words that come up most.
schedule.mjs 用「片子自己跑的同一份代码」编译 story.json:在 vm 里执行 scenes/compile.js,产出 story.js、score/timeline.json、index.html 时长与 kit/config.js;同时充当校验器——拒收示例故事冒充、校验房间道具名与槽位、缺 source 的引用告警、>80 秒告警、开篇即回复或超长引用直接 exit 1。
// schedule.mjs: compile a project's story.json with the same code the film runs (scenes/compile.js) … refusing: this is the example story ( … vm.runInContext(fs.readFileSync(P('scenes/compile.js'), 'utf8'), ctx, { filename: 'compile.js' });
隐私门是硬门:设计 pass 之前要给用户一张表(hook、铭牌、每条引用、每条回复、每件道具及其理由)并注明来源,拿到显式 yes 才写 approved: true;未批准前每帧盖 DRAFT 章。除用户外的人名、客户、公司、NDA 产品、路径、URL、邮箱、可识别数字与密钥都要剪掉。
7. **Privacy gate:** show the user one table of every on-screen line (hook, nameplate, each quote, each reply, each prop and why), each with its source. Take their edits, get an explicit yes, then set `"approved": true`. Until then every frame carries a DRAFT stamp.
配乐是自作曲但有数值门禁:写 score/score.py(自定主题/调/音色),build.sh 走 compose→render→master→check;macOS 用 swift 走系统 General MIDI,其他平台要 fluidsynth + SOUNDFONT,ffmpeg loudnorm 到 -16 LUFS,最后 qc.py 逐 beat 检响度与死气。
# build.sh: compose → render → master → check. Run from anywhere: sh score/build.sh … python3 qc.py ../assets/audio/score.wav timeline.json
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | HyperFrames CLI(钉版 npx --yes [email protected];check/preview/render/snapshot) |
| cli | ffmpeg(配乐母带 loudnorm/afade + 渲染后抽帧核对) |
| package | p5 2.3.3(LGPL-2.1)/ p5.brush 2.2.3(MIT)/ @fontsource/permanent-marker 5.3.0(Apache-2.0),经 npm ci 按锁文件安装 |
| cli | 配乐渲染器:macOS 的 swift(系统 General MIDI 音色库)或其他平台的 fluidsynth + 用户自备 SOUNDFONT |
| network | 构建期声明无网络;唯一潜在外发是 snapshot 把帧送 Gemini(仅在 GEMINI_API_KEY 存在时),skill 要求一律带 --describe false 规避 |
| network | 本地隐私数据读取(非凭证):当前项目的 Claude Code / Codex 会话记录,以及用于填房间的 memory 与指令文件 |
4风险提醒 风险提醒:蓝色 · 知晓即可
- 读的是用户的私密历史 — harvest 读 ~/.claude/projects 与 ~/.codex/sessions 的会话原文,还读 memory 与 CLAUDE.md/AGENTS.md 来填房间;虽然全程本地且有『先问用户』的要求,但同意是提示级约束。
- 用户原话会落盘 — story.json 与 session-story-candidates.json 都含用户原话;文档明说 never commit or share them,但项目一旦被提交/同步即外泄。
- 脱敏靠正则 + 人眼 — FLAGS 会漏(小写人名、非英语姓名、间接可识别信息),最终责任在那张人工隐私表上——用之前得真的逐行看。
- 平台依赖会阻断成片 — 非 macOS 且没有 fluidsynth + General MIDI 音色库时,配乐渲染直接失败;macOS 也需要 swift/Xcode CLT。
- snapshot 的默认行为在 CLI 一侧 — 帧上传 Gemini 的开关由 HyperFrames CLI 决定,skill 只能以文档要求 --describe false 规避;agent 漏参数即等于把用户的话送出去。
- 身份与形象表达 — 片子按 agent 自己的形象演出(非 Claude 需按 cast.md 自绘),涉及品牌/身份表达,属创作判断而非技术风险。
5第二遍独立确认
- [ok] 『No credentials』与『Network at build time: none』是否成立 — 目录内 process.env 命中只有 SOUNDFONT(build.sh 交给 fluidsynth 的音色库路径)与 GEMINI_API_KEY 的**提示文本**;无键值读取、无 fetch。engine/index.html 引用 assets/vendor/p5.min.js(本地),渲染链路不需联网。
- [discrepancy] harvest 的敏感 flag 能否替代人工审核 — 不能,文档自己说明了:FLAGS 是正则模式匹配(secret/email/path/url/number/name?/person?),sources.md 明写 'The flags miss what they can't see: a name typed in lowercase ("like peter said") has no flag.'。故能力清单不写成『自动脱敏』,隐私门本质是人读。
- [ok] 示例故事冒充是否真会被拦 — schedule.mjs 读取随包 assets/example/story.json,用 quotes() 归一化小写比对引用;命中 ≥2 条且未加 --example 时 exit 1 并提示写自己用户的故事。防糊弄逻辑真实存在。
- [ok] 配乐链是否真有三平台分支与母带门禁 — build.sh 依序判断:Darwin + 系统 gs_instruments.dls + swift → swift 渲染;否则 fluidsynth + SOUNDFONT → 渲染;都不满足则报错退出(并明说两者都不下载东西)。母带为 ffmpeg loudnorm=I=-16:TP=-1.5:LRA=14 + 首尾淡入淡出,最后 python3 qc.py 检响度与死气。
- [ok] 引擎代码来源是否交代 — assets/engine/NOTICE.md 写明 kit/core.js、kit/clawd.js、kit/timeline.js 改编自 ClaudeAnimationBase(commit b1d7e89,MIT),并随包分发 LICENSE-ClaudeAnimationBase;非自有代码有交代。
- [unlocatable] 『40 到 70 s 抓得住注意力』的时长论断 — 该区间是设计声明(schedule.mjs 仅对 >80s 打 warning),源码内无实测依据;本次只读侦查未运行 harvest 与渲染,故不作为已核事实使用。
6结论
0e83cbb985854ae8…ba7a0bb6d3