会自己整理的便签。 你只管说和读,AI 负责想和理。
jot 是一个为 AI 时代而生的 todo CLI:主要由 AI 写入、由人阅读。你对着 Claude Code 之类的 AI 随口说一句「帮我记一下 X」「网站改版有几个 bug 要修」,AI 就自然而然把它组织好存进 jot;你只需要敲一下 jt,一屏看懂自己手头的状态。
命令叫
jt(不是jot)——macOS/BSD 自带一个/usr/bin/jot数字序列工具,为避开撞名,本工具的可执行文件取名jt。项目本身仍叫 jot。
$ jt
▌ site-redesign 3 在办
◐ 96gs 推进网站改版方案
○ m1vq 修复登录超时
复现:并发下偶发,疑似锁竞争
○ 010w 优化首页加载
✓ 2zw0 接通新版导航
▌ misc 1 在办
○ 62b5 回复设计评审
▌ 未分组 1 在办
○ v060 写周报按分组分层:组是父、todo 缩进其下,一眼看出「哪个项目下有哪些事」。
◐ 在做(高亮)· ○ 待办 · ✓ 今天完成;备注以淡色行挂在条目下。
普通 todo app 为「人手动输入」优化;jot 反过来——输入端为 AI 优化,展示端为人优化。
- 工具笨到可以被信任。 jot 不嵌 LLM、不做语义判断、完全确定性。所有理解 / 归类 / 拆分的智能,都在调用它的 AI 那一侧(它本来就是大脑)。jot 只做两件事:给 AI 的结构化存取,给人的漂亮渲染。同样的命令永远是同样的结果——可预测、可测试、可回滚。
- AI 写,人读,同一份视图。 人在终端敲
jt是彩色的分组层级视图;AI 管道调用拿到的是同一份视图的无色纯文本——LLM 母语级直接读,比 JSON 省 token、更不易出错。要机器解析才显式--json。 - 存储是人类可读的 JSONL。 每行一条 todo。行级独立意味着 AI 追加、人手改、
git diff三者都安全——一行坏了不连累整文件,而且你随时能cat一眼看完。 - 克制。 数据模型只有
id / title / status / group? / note? / 时间戳。没有优先级、没有标签、没有子任务、没有依赖、没有提醒、没有协作。需要那些的,那就不是一张便签。
cargo install --path . # 安装为 ~/.cargo/bin/jt
# 或
cargo build --release # 产物在 target/release/jt配套的 Claude Code skill 就在本仓库里:skills/jot/SKILL.md(跟 jt 同版本维护)。它在你想记事、报告进展/完成、查看手头任务时自动触发,指导 AI 按使用契约调用 jt:何时主动记、写前先 jt ctx、复用已有组 slug、把一句话拆成多条原子项、状态怎么标、用自然语言向你复述。无需往全局 CLAUDE.md 里塞东西。
让它全局生效:把仓库里的 skill 软链进你的 skills 目录——
ln -s "$PWD/skills/jot" ~/.claude/skills/jot(将来想分发给别人,给本仓库加个 .claude-plugin/plugin.json 即可升级成可 /plugin install 的 Claude Code 插件。)
| 命令 | 作用 |
|---|---|
jt |
按分组分层的层级视图(组→todo,含 doing 高亮、note 淡色行) |
jt show <id> |
看单条完整信息:title / note / 状态 / 分组 / 时间 |
jt ctx |
给 AI 的状态快照(同上视图的纯文本 + 分组/维护脚注),写前必读 |
jt add "<text>" [-g <slug>] [-s doing] [-n <note>] |
加一条 todo |
jt done <id>... |
按 id 前缀标完成,幂等,可一次多个 |
jt update <id> [-t] [-s] [-g] [-n] |
改一条 todo |
jt list [-g <slug>] [-s <status>] |
列出(可过滤) |
jt reorder <id>... |
把这些项提到「接下来」最前(重排,显示序=文件行序) |
jt groups |
所有组 + 计数 |
jt merge <from> <into> |
把一个组并入另一个(你决策,jt 执行) |
- 状态:
todo/doing/done/dropped(dropped 默认隐藏)。 - 输出格式:默认是人类视图——终端里彩色、管道里无色纯文本(AI 直接读);
--json才给机器解析用的 JSON;NO_COLOR去色。 - 存储:
~/.jot/todos.jsonl,用JOT_FILE或--file覆盖。 - id:git 风格短前缀唯一匹配(
jt done k3f)。退出码:0 成功 / 1 内部错误 / 2 歧义 / 3 未找到 / 4 输入非法(1 与 4 区分开,便于 AI 判断该不该重试)。
同一个主题被 AI 用不同措辞写成多个组(网站 改版 / 网站-改版 / 网站改版)是真问题。jot 用三道全程零猜测的确定性防线对付它:
- ctx-first:AI 写前先读
jt ctx,复用已有 slug 而非发明新名——从源头掐断发散。 - 确定性 slugify:组名归一化是输入的纯函数(NFKC + 小写 + 空格/分隔符折叠,CJK 原样),免费消灭大小写/空格/分隔符这类排版抖动。它只管「同一个字符串的不同写法」,绝不碰「不同字符串是否同义」。
jt merge:库脏了,由 AI 决策该并哪两个组、jt 忠实执行——透明、可审计、可回滚。
聚合不是「记的那一下」的一次性动作,而是每次 AI 碰 jot 都顺手 tend 一遍整个结构。jt ctx 在视图末尾给一段确定性的 维护: 脚注:
分组: site-redesign 2在办/1完成 · site-redesgn 1在办/0完成
维护: 疑似重复 site-redesgn|site-redesign · 0py6 卡了9天 · 3条未归组
AI 据此做有界的整理:合并重复组、归位、标记完成、jt reorder 重排。信号是确定性的(slug 编辑距离聚类、doing 在办时长、未归组计数,纯函数、可测试、非 LLM),但「该不该合/动」的判断留给 AI——工具只亮灯、不开车。结构性整理安静做(但会告知用户),改写原话/删条目则必须先问。(--json 下这些信号以结构化 health 块给出,供脚本用。)
注意区分:工具不做基于相似度的自动合并——它只把形近的组亮出来,合不合由 AI 定。「两个串像」是确定性的,「它们是不是一回事」是判断,判断归 AI。这条线保住了工具的「可信赖」。
单 binary crate,模块化,store 隔离所有 IO:
src/
model.rs Todo 类型 + JSONL 序列化(未知字段原样保留)
slug.rs 确定性 slugify(纯函数)
id.rs 短 id + 前缀唯一匹配
store.rs 唯一碰文件系统的地方:fs4 跨进程锁 + 原子写(temp + rename)
render.rs 分组层级视图(人/AI 读)+ 维护脚注 + show + --json
cli.rs clap 命令定义
main.rs 解析 + 分发 + 输出格式选择
测试:cargo test(单元 + 集成;含 16 进程并发测试,验证跨进程文件锁有效)。
v0.1 MVP。Phase 2 候选:MCP server、相似度去重提示、due 软日期、项目级 .jot.jsonl。
许可证:MIT OR Apache-2.0。