mcpField
T
tutorkit

tutorkit

github.com/mimukit生产力2218 次安装今天更新
代码仓库

关于 tutorkit

tutorkit 是面向多次学习的持久化技能,适合学习软件工程等主题。它根据已有知识调整课程,并通过定期提示和不同的教学、练习及测评模式跟踪回忆情况。

主要功能

  1. 01五种教学与进度模式
  2. 02按主题组织的学习仓库
  3. 03可打印的 HTML 课程
  4. 04五阶段检索复习计划
  5. 05跨主题回忆练习
  6. 06进度路由与状态查看

适用场景

  1. 01持续学习软件工程主题
  2. 02复习多个主题的到期提示
  3. 03查看进度并选择下一种学习模式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mimukit/skills --skill tutorkit

安装后在 Claude Code 中输入/tutorkit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
lesson.css
modes/
drill.md
exam.md
explain.md
lesson.md
status.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 个单词。工作记忆容量有限,篇幅过长的课程就无法学完。

每节课依次包含:

  1. 一句与使命的关联说明,注明撰写时所依据的 MISSION.md 条目及其日期。
  2. 用户做出的预测,以及预测错在哪里。
  3. 运作机制。
  4. 一个完整示例。
  5. 练习及其反馈循环。
  6. 已安排复习的提示。
  7. 下一步要阅读的主要来源。
  8. 指向相关课程和参考资料的链接。
  9. 一句结语,提醒用户仍有不清楚之处时可以向 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 仍可运行,因为它们都不会写入内容。

评论

支持 Markdown