关于 tutorkit
tutorkit 是面向多次学习的持久化技能,适合学习软件工程等主题。它根据已有知识调整课程,并通过定期提示和不同的教学、练习及测评模式跟踪回忆情况。
主要功能
- 01五种教学与进度模式
- 02按主题组织的学习仓库
- 03可打印的 HTML 课程
- 04五阶段检索复习计划
- 05跨主题回忆练习
- 06进度路由与状态查看
适用场景
- 01持续学习软件工程主题
- 02复习多个主题的到期提示
- 03查看进度并选择下一种学习模式
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mimukit/ skills --skill tutorkit安装后在 Claude Code 中输入/tutorkit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/lesson.cssmodes/drill.mdexam.mdexplain.mdlesson.mdstatus.md详细介绍
tutorkit
通过多次会话教授一个主题,并记住哪些内容已经掌握。tutorkit 将所有学习内容保存在一个仓库中,每个主题各有一个文件夹;它会将每节课的难度设定在用户已有知识的边缘,将课程写成可打印的 HTML 成品,并安排日后到期的检索提示。导师会记得你并做出调整;这种持续性就是整个设计的核心。
四种姿态,而不是四种呈现方式:explain 回答问题,不写入任何内容;lesson 教授内容,也是唯一会开启学习轨道的模式;drill 跨主题测试记忆;exam 评估水平,并拒绝教学。
status 是第五种模式,而不是第五种姿态。它不教任何内容、不提任何问题,也不评分。它会读取两个路由文件,显示每条学习轨道的进展,并选出下一步行动。运行它,以决定要使用四种姿态中的哪一种。
tutorkit 不是什么
- 不是代码编写器。 它绝不会在用户的项目中实现功能。它会读取用户的代码来构建示例,仅此而已。
- 不是决策报告。 “我们该使用哪个队列库”属于研究问题,即使两者都会查阅一手资料也是如此。
- 不是项目文档。 它不会记录用户仓库中的任何内容。
- 不是间隔重复引擎。 固定的五步间隔阶梯,不提供 SM-2 或 FSRS 调优、不支持 Anki 导出,也不建模记忆保持情况。设置日程是为了确保进行复习,而非追求最优。
- 它并非专为通用场景设计。 它适用于任何主题,并针对软件工程进行了调优;在这一领域,基于仓库的内容、可运行的练习和源代码引用都能发挥更大作用。
- 它绝不会自行提交学习仓库。
模式选择
这是此技能的首个决策,触发条件有意设置为重叠。 “解释 X 的工作原理”对应 explain,“教我 X”对应 lesson,但措辞只是较弱的信号。应根据意图而非表达方式来判断:想要答案的问题使用 explain;希望最终掌握某项内容的请求使用 lesson。“有哪些内容到期了”“给我出个小测验”“测试我”使用 drill。“我准备好了吗”“我到底掌握了多少”“考考我”使用 exam。“我目前进展如何”“我正在学什么”“学习状态”“显示我的进度”使用 status。
没有提及主题的请求几乎总是使用 status。 这是区分所有模式最明确的标准:其他四种模式都需要一个 slug,而 status 不接受 slug。“我准备好了吗”提到了主题并要求评估,因此使用 exam;“我目前进展如何”没有提及主题,而是报告所有学习轨道的情况,因此使用 status。
如果请求确实模棱两可,选择成本较低的分支:运行 explain,并在最后提出开启学习轨道的建议。误选 lesson 会让用户经历一场他们并不想要的任务访谈;误选 explain 则只会多用一句话。
学习仓库
所有状态都存放在用户工作仓库之外的一个仓库中,默认路径为 ~/learning,除非 $TUTORKIT_HOME 指定了其他位置。将它放在工作仓库之外,技能就能读取工作仓库中的示例,而不会把笔记写进去。
~/learning/ ← one git repo; $TUTORKIT_HOME overrides
INDEX.md ← the router
REVIEW.md ← cross-topic due queue, one row per topic
NOTES.md ← how the user likes to be taught, global
assets/lesson.css ← copied from the skill on first run, never overwritten
topics/<slug>/
MISSION.md ← append-only; why they are learning it, plus the grounding consent
PROGRESS.md ← placement result, what stuck, what is shaky, where they are
CUES.md ← retrieval cues, key points, due dates, interval step, last seen
SOURCES.md ← vetted primary sources, so the agent stops re-searching
lessons/0001-<dash-case>.html
reference/<name>.html ← printable cheat sheets and the glossary
exercises/ ← runnable practice, code topics only
首次使用时创建该仓库,并在其中运行 git init。进度历史确实很有用,而且仓库属于用户本人。绝不自动提交。 在会话结束时询问用户是否提交,并接受用户的拒绝。
路由规则是关键防护措施。 在会话开始时读取 INDEX.md 和 NOTES.md,准确确定一个 slug,然后只读取 topics/<slug>/。绝不对 topics/ 进行全局匹配。没有这条规则,随着用户学得越多,技能表现就越差,这恰恰与目标背道而驰:路由 30 个主题大约只需查看 60 行,而打开它们则要处理数万个 token。
有两种模式属于例外,但两者的范围都有限。drill 根据 REVIEW.md 而不是用户的提问来确定 slug,然后只打开这些主题的 CUES.md。它绝不读取课程内容,也绝不进行全局匹配。交错练习需要同时查看多个主题,但每个主题并不需要查看多个文件。
status 是限制更严格的例外:它会报告所有主题,但完全不打开任何主题文件夹。这是可行的,因为 INDEX.md 和 REVIEW.md 已经包含仪表板要显示的所有字段,或可用于推导这些字段的日期。打开主题文件夹来查看跨主题信息是设计缺陷,而非权衡取舍,因为这两个路由文件的存在,正是为了让读取操作随着用户的主题数量增长而保持精简。
当 cwd 是学习仓库本身时,应将其视为学习仓库,而不是作为知识依据的来源。 这两种角色绝不会重叠,因此,从学习仓库内部运行 lesson 时,应跳过知识依据确认,而不是提出要教用户了解他们自己的笔记。
路由器
INDEX.md 保存别名,让模糊的请求无需打开任何内容就能路由:
| Topic | Slug | Also called | Status | Last touched |
|-------|------|-------------|--------|--------------|
| Postgres MVCC | `postgres-mvcc` | transaction isolation, snapshot, vacuum, row locking | active | 2026-08-11 |
状态为 active 或 learned。有三种路由结果,成本都很低:
- 请求匹配某个 slug 或别名 → 打开对应文件夹。
- 请求没有匹配项,且用户想深入学习 → 创建文件夹并开启一个学习轨道。
- 请求没有匹配项,且用户想要答案 → 运行
explain,不写入任何内容。
REVIEW.md 每个主题占一行,而不是每个提示占一行:postgres-mvcc · due: 2026-08-18, 2026-08-18, 2026-08-21, 2026-09-08 · min step: 3d。due 单元格列出该主题中每个提示的到期日期,按日期排序,不包含任何其他提示信息。读取时计算到期数量:统计不晚于今天的日期。切勿保存数量,因为保存的数量只在写入当天准确;明天到期的提示永远不会被计入其中。drill 会读取该行,查看哪些主题已到期,并且只打开这些主题的 CUES.md 文件。若在此处保存提示文本,就会重复保存答案,并导致它们与所属课程内容不一致。
min step 是该主题任一提示达到的最低间隔步长;保留它,是因为它能让路由器单独回答一个问题:这条学习轨道完成了吗?最低提示间隔达到 60d 的主题已通过 learned 门槛中的间隔计划部分,因此 status 无需读取任何 CUES.md,就能将 exam 作为下一步。应保存最小值而非平均值,因为门槛要求每个提示都达到 60d,其中一个提示只有 1d 就无法通过。
这两个文件都是缓存,而缓存需要修复机制。 修复只会在某个模式已经打开主题文件夹时进行,因此不会违反单文件夹限制:
- 每个打开主题文件夹的模式都会根据该文件夹自身的
CUES.md和MISSION.md,重写两个文件中该主题对应的行,无论原来的行看起来是否有误。 - 磁盘上存在文件夹但
INDEX.md中没有对应行的 slug,路由时会按该行已存在处理。对该 slug 运行lesson、drill或exam时会打开文件夹并写入该行。 status不会打开任何主题文件夹,因此不会修复任何内容。 它会列出路由文件中缺少的每个文件夹,以及字段缺失或格式过时的每一行,并提示对相应 slug 运行lesson。
缺少 min step,或用已保存的数量代替到期日期的 REVIEW.md 行,是按旧格式写入的。下一个打开该主题的模式会按当前格式写入该行。如果没有自我修复机制,一次手动编辑就会让路由永远悄无声息地出错。
样式表
assets/lesson.css 与此文件一同提供。首次运行时,解析此技能自身的安装目录,并将样式表复制到 <repo>/assets/lesson.css,因为工作目录是用户的项目,而不是技能目录,所以相对路径无法找到它。只复制一次,之后绝不覆盖。 后续技能更新会为新仓库提供新的默认样式,同时让现有课程保持原有的渲染效果。如果改为链接安装目录中的路径,技能一旦移动,所有课程都会立即失效。
各模式
每个模式的正文都单独存放在 modes/ 下的一个文件中。根据模式选择进行路由,读取对应的那个文件并遵循其中的说明。此行以上的所有内容以及以下的共享章节适用于所有模式,不会在模式文件中重复说明。
- 模式
status→ 读取 modes/status.md,然后遵循其中的说明。 - 模式
explain→ 读取 modes/explain.md,然后遵循其中的说明。 - 模式
lesson→ 读取 modes/lesson.md,然后遵循其中的说明。 - 模式
drill→ 读取 modes/drill.md,然后遵循其中的说明。 - 模式
exam→ 读取 modes/exam.md,然后遵循其中的说明。
间隔安排
间隔:1d → 3d → 7d → 21d → 60d。提示按主题记录在 CUES.md 中:
| id | cue | key points | due | step | misses | last seen |
|----|-----|------------|-----|------|--------|-----------|
| 3 | Why does a long-running read never block a write in MVCC? | readers see a snapshot; writers make a new row version; visibility is decided per transaction | 2026-08-21 | 3d | 1 | 2026-08-18 |
got it将间隔推进一级。partial保持在当前间隔,重复复习。missed将间隔重置为1d,并在文中重新讲解该提示。
迟到不会导致衰减。 由于上限而暂缓的提示,是技能的欠账,不是用户的;上限可能让提示逾期三十天。采用一条日程规则比两条更容易理解,而 partial 评分已经涵盖了衰减规则本来要处理的大多数情况。
为自由文本答案评分
根据提示中保存的 2–3 个关键点,分为三个等级:
got it。 答案以任何措辞涵盖了关键点。partial。 答案涵盖了部分关键点,或整体方向正确但有一处细节错误。missed。 答案没有提到关键点,或与关键点相矛盾。
二元评分会迫使你对半对的答案做出错误判断,而多数答案都属于这种情况。第三个等级能涵盖这种模糊性,而不是往任一方向错误地消除它。
每次评分都要提供修改选项,而不只是答错时才提供。 整个间隔阶梯都依赖这项判断,因此用户必须能够修正评分;尤其是在用户用关键点未预料到的措辞给出了正确答案时。
课程内容文件
一个自包含的 HTML 文件,位于 topics/<slug>/lessons/NNNN-<dash-case>.html,并链接到 ../../../assets/lesson.css。遵循 Tufte 风格约束:单栏、充足的页边距、使用旁注而非脚注,且篇幅上限约为 700 个单词。工作记忆容量有限,篇幅过长的课程就无法学完。
每节课依次包含:
- 一句与使命的关联说明,注明撰写时所依据的
MISSION.md条目及其日期。 - 用户做出的预测,以及预测错在哪里。
- 运作机制。
- 一个完整示例。
- 练习及其反馈循环。
- 已安排复习的提示。
- 下一步要阅读的主要来源。
- 指向相关课程和参考资料的链接。
- 一句结语,提醒用户仍有不清楚之处时可以向 Agent 提问。
注明使命条目,才能在使命变更时保留旧课程:针对已被取代的使命撰写的课程,看起来会像是过时,而不是错误。
先复用,再撰写。 先阅读 assets/,并基于其中现有组件来构建。样式表能让一堆一次性文件看起来像同一门课程;用户自己的主题所积累的组件也会与它并列。不要在第二节课中内嵌已经在第一节课中出现过的内容。
参考资料是会被反复查阅的内容,因此应呈现压缩后的精华,而非叙述:可以是表格、决策规则或图示,而不是复述。将其写入 reference/<name>.html。术语表一旦写好,就适用于之后的每一节课。
测验选项的单词数和字符数应相同,这样格式就不会泄露答案。
打开课程应尽力而为,绝不能阻塞流程。 尝试使用平台的打开命令(macOS 上用 open,Linux 上用 xdg-open,Windows 上用 start);如果都未能打开,就打印文件路径并继续。课程成功写入后,不能因为浏览器未能启动而报告失败。
引用规范
每项不显然的主张都要附上主要来源:规范、RFC、源代码、官方文档或变更日志。优先阅读源代码,而非博客文章。 如果找不到来源,就说“我认为 X 是这样,但找不到来源”,不要将其当作事实断言。
将读过的内容记录在 SOURCES.md 中,注明标题、URL、阅读日期,以及一句说明该来源能确认什么,以便后续会话不必重复搜索同一内容。搜索前先检查 SOURCES.md。
交接
本节采用流程化语体:每句话给出一条指令,使用主动语态和现在时,不使用比喻。
变更内容。 说明编写了哪篇课程、安排了哪些提示、记录了哪些等级,以及标记了哪些不牢固的内容。也说明哪些内容没有变化:拒绝了哪条学习路线、无法找到来源的提示,以及拒绝写入的状态。
保存位置。 给出主题文件夹路径和课程路径。如果本次运行创建了仓库,也给出仓库路径。
下一步。 根据状态指定一项行动:
- 现在有提示需要复习 → 运行
drill。 - 学习路线正在进行,且目前没有待复习的提示 → 运行下一篇
lesson。 - 每条提示都处于
60d阶段,且学习路线看起来已完成 → 运行exam。 - 学习路线刚以
learned状态结束 → 说明没有下一步。tutorkit 基本上到此为止。不要凭空编造后续行动。
然后提议提交学习仓库。未经用户同意,绝不执行提交。
status 运行以不同方式结束,因为它的全部输出就是一份交接。 仪表板已经指定了要优先执行的行动,因此不要重复打印该行动。说明没有任何内容发生变化,并指出每一项需要修复的条目。不要提议提交。
explain 运行以简短内容结束,因为它没有写入任何内容。 说明没有任何内容发生变化。用户接受学习路线提议时,指定该主题的 lesson 为优先行动。用户拒绝时,说明没有下一步。不要提议提交。
还有两条相邻路线,但适用范围都很窄。仅在已安装相邻技能时才点名该技能,否则直接描述行动。如果问题最终是工具选择,而非知识缺口,则转向研究技能。如果唯一诚实的答案是亲自构建并验证,则转向原型技能。
注意事项
- 上下文防护规则优先于此处其他所有规则。 为了教授一个主题而打开三十个主题文件夹,会使技能随着用户学得越多而变得越慢。只解析一个 slug,只打开一个文件夹。
status会报告全部三十个主题,却一个也不打开;这正是防护规则在起作用,并非例外。 status只报告,不评分。 打印待复习数量是读取事实。判断用户是否掌握某个主题属于exam,而在它能够给出任何结论前,必须先得到用户的回答。根据min step列推断掌握程度的仪表板,会捏造它声称要报告的信号。- 每次都先预测,再解释。 面对简单主题时,人们容易想跳过这一步。预测就是诊断;不先预测就教学,无异于盲目教学。
- 绝不将没有来源支持的说法断言为事实。 自信却错误的解释比没有课程更糟,因为用户会基于它继续构建。
- 没有可写文件系统(例如基于浏览器的 Agent)?请直说,并用代码块打印课程,供用户保存;同时注明没有状态就无法保存间隔。不要假装安排了你无法写入的提示。
status和explain仍可运行,因为它们都不会写入内容。