A tiny interactive terminal app that lets the user drive a state model by hand. Use this when the question is about business logic, state transitions, or data shape — the kind of thing that looks reasonable on paper but only feels wrong once you push it through real cases.
一个小型交互式终端应用,让用户亲手驱动状态模型。当问题涉及业务逻辑、状态转换或数据结构时使用——那些在纸上看起来合理,只有通过真实案例推动才会觉得不对劲的事情。
If the question is "what should this look like" — wrong branch. Use UI.md.
如果问题是"这应该长什么样"——选错分支了。使用 UI.md。
Before writing code, write down what state model and what question you're prototyping. One paragraph, in the prototype's README or a comment at the top of the file. A logic prototype that answers the wrong question is pure waste — make the question explicit so it can be checked later, whether the user is watching now or returning to it AFK.
在写代码之前,写下你要原型化的状态模型和问题。一段话,放在原型的 README 或文件顶部的注释中。回答错误问题的逻辑原型纯粹是浪费——把问题明确写出来,这样以后可以检查,无论用户现在在看,还是离开后回来查看。
Use whatever the host project uses. If the project has no obvious runtime (e.g. a docs repo), ask.
使用宿主项目所用的语言。如果项目没有明显的运行时(如文档仓库),询问。
Match the project's existing conventions for tooling — don't add a new package manager or runtime just for the prototype.
匹配项目已有的工具链约定——不要仅为原型引入新的包管理器或运行时。
Put the actual logic — the bit that's answering the question — behind a small, pure interface that could be lifted out and dropped into the real codebase later. The TUI around it is throwaway; the logic module shouldn't be.
将实际逻辑——回答问题的部分——放在一个小的纯接口后面,以后可以提取出来放到真实的代码库中。周围的 TUI 是可抛弃的;逻辑模块不应该是。
The right shape depends on the question:
正确的形态取决于问题:
(state, action) => state. Good when actions are discrete events and state is a single value.(state, action) => state。适用于操作是离散事件且状态是单一值的情况。Pick whichever shape best fits the question being asked, not whichever is easiest to wire to a TUI. Keep it pure: no I/O, no terminal code, no console.log for control flow. The TUI imports it and calls into it; nothing flows the other direction.
选择最适合问题的形态,而不是最容易连接到 TUI 的。保持纯粹:无 I/O,无终端代码,不用 console.log 做控制流。TUI 导入它并调用它;没有反向流动。
This is what makes the prototype useful past its own lifetime: when the question's been answered, the validated reducer / machine / function set can be lifted into the real module on its own.
这正是让原型在其自身生命周期之外仍然有用的原因:当问题得到回答后,经过验证的 reducer / 状态机 / 函数集可以独立提升到真实模块中。
Build it as a lightweight TUI — on every tick, clear the screen (console.clear() / print("\033[2J\033[H") / equivalent) and re-render the whole frame. The user should always see one stable view, not an ever-growing scrollback.
以轻量级 TUI 的方式构建——每次 tick 时清屏(console.clear() / print("\033[2J\033[H") / 等效方式)并重新渲染整个画面。用户应该始终看到一个稳定的视图,而不是不断增长的滚动回退。
Each frame has two parts, in this order:
每帧按顺序包含两部分:
\x1b[1m bold, \x1b[2m dim, \x1b[0m reset. No need to pull in a styling library unless one is already in the project.[a] add user [d] delete user [t] tick clock [q] quit. Bold the key, dim the description, or vice-versa — whatever reads cleanly.\x1b[1m 粗体、\x1b[2m 暗淡、\x1b[0m 重置。除非项目中已有,否则无需引入样式库。[a] add user [d] delete user [t] tick clock [q] quit。键用粗体、描述用暗淡,或反之——只要清晰可读。Behaviour:
行为:
The whole frame should fit on one screen.
整个画面应适合一个屏幕。
Add a script to the project's existing task runner (package.json scripts, Makefile, justfile, pyproject.toml). The user should run pnpm run <prototype-name> or equivalent — never need to remember a path.
在项目已有的任务运行器中添加脚本(package.json scripts、Makefile、justfile、pyproject.toml)。用户应该运行 pnpm run <prototype-name> 或等效命令——永远不需要记住路径。
If the host project has no task runner, just put the command at the top of the prototype's README.
如果宿主项目没有任务运行器,只需把命令放在原型 README 顶部。
Give the user the run command. They'll drive it themselves; the interesting moments are when they say "wait, that shouldn't be possible" or "huh, I assumed X would be different" — those are the bugs in the idea, which is the whole point. If they want new actions added, add them. Prototypes evolve.
把运行命令交给用户。他们会自己操作;有趣的是当他们说"等等,那不应该可能"或"呃,我原以为 X 会不一样"的时候——那些是想法中的 bug,而这正是全部意义所在。如果他们想要添加新的操作,就添加。原型会进化。
Once the prototype has answered its question, capture the answer, then capture the prototype the way the [SKILL](SKILL.html) describes. The logic-specific mapping: the validated reducer / machine / function set lifts into the real module (the decision, absorbed); the TUI shell rides along to the throwaway branch that keeps the prototype as a primary source.
一旦原型回答了它的问题,先捕获答案,然后按 [SKILL](SKILL.html) 所述方式捕获原型。逻辑特有的映射是:经过验证的 reducer / 状态机 / 函数集提升到真实模块中(决策被吸收);TUI 外壳随行进入保留原型作为一手来源的一次性分支。
console.log, prompts, or terminal escape codes, it's no longer portable. Keep the TUI as a thin shell over a pure module.console.log、提示或终端转义码,它就不再可移植了。保持 TUI 作为纯模块上的薄壳。