Install
openclaw skills install study-notesGenerate polished HTML study notes AND full homework solutions for academic subjects, especially STEM (physics, math, chemistry, engineering, CS). Trigger on requests to create study notes, learning notes, a study guide, lecture notes, or self-study reference — e.g. "make me notes on X", "help me learn X", "summarize X for an exam". Also trigger when the user uploads a PDF textbook or course material and asks for review notes, 学习笔记, or 复习笔记. Also trigger when the user gives homework or exercise problems (作业题 / 习题) and wants either study notes for the chapter those problems test (re-learning the chapter through its exercises) or full step-by-step solutions as a standalone HTML page, with each problem and its figure shown (simple figures as inline SVG, complex or photo figures embedded from the original) and each solution collapsed. Output is one standalone HTML file with KaTeX math, color-coded sections, collapsible derivations and solutions, callouts, worked examples, and practice problems.
openclaw skills install study-notesGenerates detailed, exam-ready HTML study notes — and full homework solutions — that are visually polished, mathematically rigorous, and pedagogically structured, modeled after the best university-level reference materials.
Default audience assumption: treat the reader as someone encountering this subject for the first time. Write as if they attended lectures but are confused and need everything explained clearly — intuition first, then rigor, then worked examples. Never assume prior knowledge beyond what is stated as a prerequisite.
Path convention (read this first). The examples below use /mnt/user-data/uploads/ (inputs) and /mnt/user-data/outputs/ (outputs) as placeholders — these are the Claude.ai web paths. In Claude Code (or any other environment) substitute the real paths: read inputs from wherever the user's files actually are, and write the final HTML to the current working directory (or a directory the user names). Every helper script in scripts/ takes paths as arguments, so nothing is hard-coded — call them with the paths that exist in your environment.
This skill is a multi-branch workflow. Before generating anything, read the input, then route to exactly one mode.
On the relationship to Claude Code "dynamic workflows": a SKILL.md cannot be a dynamic workflow (those are JavaScript-orchestrated subagent runs). What this routing does is make the skill behave like one — a decision tree over input types. All three modes should additionally run their generation as a workflow — plan → fan-out → verify → assemble — rather than one giant pass. This is what fixes shallow notes and wrong answers. See
references/workflow-orchestration.md(mandatory for MODE A and MODE B) and the scale tip in MODE C.
| Input | User's intent | → Mode |
|---|---|---|
| 课本 / 讲义 PDF (text or scanned images) | "出学习笔记 / 复习笔记 / review notes" | MODE A — PDF → 学习笔记 |
| 几道作业 / 习题 | "用这些题帮我重新学这一章" | MODE B — 作业题 → 章节学习笔记 |
| 一份作业 / 习题 | "给我每道题的解答 / 答案" | MODE C — 作业题 → 全部题目解答 |
| 只有一个主题,无文件 | "帮我做 X 的笔记" | MODE A (scratch) — 从零生成 |
Routing rules
All modes share the same design system, math-rendering rules, post-generation checks, and file-generation strategy described later in this file. The modes only differ in what content to produce and how to structure it.
Do not generate a whole document in one linear pass. Run each mode in four phases — this is the
fix for "笔记空泛" and especially "题做错了". Full details in references/workflow-orchestration.md; the essentials:
scripts/build_and_check.py, and
verify every answer — every worked example (MODE A) and every homework solution (MODE B) —
with the per-problem verification checklist in references/workflow-orchestration.md.Why answers come out wrong — and the cure. A linear pass writes a solution once and never checks it, and does arithmetic in its head. The workflow cures both:
python3 and every non-trivial
symbolic step with sympy; paste only verified results into the HTML.This phase/verify discipline is required even when you run everything sequentially in one context — only the parallelism is optional; the plan → fan-out → verify → assemble structure and the verification are not.
Activate this mode when the user uploads a PDF textbook or course material and asks for 学习笔记 / 复习笔记 / review notes / organised notes from the book. (With no PDF and only a topic, use the same Content Structure from scratch — "MODE A scratch".)
Follow Steps 0–4 below for PDF handling, then generate content using the full Content Structure (same depth as scratch mode — derivations, intuition, examples, everything), run as the four-phase workflow in §0.5 / references/workflow-orchestration.md (plan the TOC + shared spec once, fan-out one unit per section, verify each section incl. every worked-example answer, assemble + coherence pass). The steps below only govern how to read the PDF and handle special formatting rules; they do NOT reduce the depth or completeness of the notes.
Exception — compact/formula-only mode: If the user explicitly asks for a condensed version (e.g., "只要公式", "精简版", "只整理公式和概念"), then limit content to core formulas and key concepts only for that request.
Use the helper script (preferred — it auto-detects scanned PDFs and renders page images):
python3 scripts/extract_pdf.py text <input.pdf> -o <outdir>/extracted.txt
# if extracted.txt is empty / near-empty → scanned PDF, render pages to images:
python3 scripts/extract_pdf.py images <input.pdf> -o <outdir>/pages --dpi 150
Or inline, if you prefer not to use the script:
pip install pymupdf --break-system-packages -q
python3 -c "
import fitz
doc = fitz.open('<input.pdf>')
for i, page in enumerate(doc):
txt = page.get_text()
if txt.strip():
print(f'--- PAGE {i+1} ---'); print(txt)
" > <outdir>/extracted.txt
wc -l <outdir>/extracted.txt
If text extraction yields 0 / very few lines (scanned/image-only PDF), render pages to PNG (scripts/extract_pdf.py images ...) and use the Read tool to view each page image. Read ALL pages — never skip content.
Then extract the table of contents: note every chapter title, section number, and sub-section heading. This becomes the TOC in the HTML notes.
From the book's title page or content, determine the subject (e.g., 力学, 热学, 电磁学, 线性代数, 有机化学).
<subject>学习笔记.html (e.g., 力学学习笔记.html).header: <subject>学习笔记 · 覆盖全书重点Sections or problems marked with *, ★, or labelled 选学/选读 are elective — the student has not studied them.
Rules:
.elective-badge span.Elective badge CSS (add to <style> block in Part 1):
.elective-badge {
display: inline-block;
font-size: 11px;
font-weight: 700;
color: var(--amber-dark);
background: var(--amber-light);
border: 1px solid var(--amber);
border-radius: 4px;
padding: 1px 6px;
margin-left: 6px;
vertical-align: middle;
letter-spacing: 0.04em;
}
Usage: <h3 id="sX-X">§X.X 节标题 <span class="elective-badge">★ 选学</span></h3>
In the TOC, append ★ (plain text) after the title of any elective section link.
Figures and diagrams: In MODE A, do NOT draw SVG diagrams or embed base64 images unless the user explicitly asks. Instead write an inline reference:
<p class="fig-ref">(见图 3-5:弹簧振子示意图)</p>
Add to <style> block:
.fig-ref { color: var(--text3); font-size: 13px; font-style: italic;
padding: 4px 0 4px 12px; border-left: 3px solid var(--border); margin: 8px 0; }
Reference format: (见图 X-X:图题) — use the book's exact figure number and caption.
(Note: MODE C is different — there figures are mandatory and either drawn as SVG or embedded from the original image. See MODE C.)
Tables: Reproduce simple tables directly in the HTML using a <table> element inside a .card. Use the design system's table CSS (alternating row backgrounds). A table is "simple" if it has ≤ 8 columns and its content (text or short formulas) fits comfortably in a cell. For complex multi-page tables, write a reference instead: (见表 X-X:表题).
All example problems (例题) and exercise answers/hints (答案、提示) MUST be placed inside collapsible <details> blocks. Do not show them inline.
Pattern:
<div class="card">
<h3>例题 & 练习</h3>
<details>
<summary>例 3-2 弹簧振子的周期</summary>
<div class="details-body">
<p><strong>题目:</strong>质量为 $m$ 的物体挂在劲度系数为 $k$ 的弹簧上,求振动周期。</p>
<p><strong>解:</strong>由 $F = -kx$ 和牛顿第二定律…</p>
<div class="fbox">$$T = 2\pi\sqrt{\frac{m}{k}}$$</div>
</div>
</details>
<details>
<summary>练习 3-4 答案与提示</summary>
<div class="details-body">
<p><strong>答案:</strong>$T = 0.63\,\text{s}$</p>
<p><strong>提示:</strong>代入 $m = 0.1\,\text{kg}$,$k = 10\,\text{N/m}$。</p>
</div>
</details>
</div>
Rules:
<summary> line always shows the problem number and title — always visible.<div class="details-body">.<details> per exercise, grouped in a single card at the end of that chapter.Goal: the student gives a handful of homework problems; you infer which chapter/topic they test, then produce full study notes for that chapter (same depth as MODE A), using the problems as the spine for re-learning. The point is not to answer the problems in isolation — it is to re-teach the chapter so the student can solve them and others like them.
references/workflow-orchestration.md)The intent is unchanged: reverse-infer the chapter from the problems and produce complete notes for the whole chapter, with each homework problem embedded as a collapsible worked example. The phases below add a correctness layer so those embedded solutions are actually right — this is the fix for "MODE B 有时候题都做不对".
B0 — Read the problems. Read text and/or images (see "Reading problem images" in references/problem-solutions.md). If a course PDF or chapter scan is also provided, use its section numbering and notation throughout.
B1 — Plan: map problems → concepts + shared spec (one pass). For each problem, identify the concept(s) it requires (e.g. 题3 → 动量守恒 + 完全非弹性碰撞;题5 → 转动惯量 + 平行轴定理) and its prerequisites. Tell the user this mapping in one short line, e.g. "这几题集中在:动量守恒、非弹性碰撞、转动惯量——我会按这条线把整章重点串起来。" Set scope = union of those concepts + prerequisites + surrounding chapter context, so the notes re-teach the whole chapter (not just the sub-points the problems poke at). Write the shared spec (notation table from the source, section color plan) used by all later units.
B2 — Solve + VERIFY every problem (do this BEFORE writing the notes; one unit per problem). This is the key step. For each problem:
python3 and every non-trivial symbolic step with sympy (don't do mental math).已核验 ✓; if they disagree → find the error, re-derive, and do not ship until two routes agree.B3 — Generate notes (fan-out, one unit per concept) using the full Content Structure (intuition → rigorous statement → derivation → special cases → worked examples → common mistakes → connections → exam tips). Order sections pedagogically (prerequisite → core → harder), not in the order the problems happened to be given. Each unit gets the shared spec.
B4 — Weave the VERIFIED homework solutions in as worked examples. For EACH homework problem, place a worked-example card in the section that teaches its concept:
<summary> names it, e.g. 作业 3 两物体完全非弹性碰撞求末速度 — always visible..answer-box) go inside a collapsible <details>; add a small 已核验 ✓ marker so the student knows it was double-checked.references/problem-solutions.md).B5 — Self-test card + assemble (coherence pass). End with a "本章习题自测" card that lists every homework problem with a one-line 考点 tag and links to its worked-example card. Then concatenate, run the coherence pass (consistent notation, no duplicate/clashing sections, TOC links resolve) and the post-generation checks.
Output: <subject>-<chapter>学习笔记.html (e.g. 力学-动量守恒学习笔记.html). Subtitle: <chapter> · 由作业题反推重点. Then run scripts/build_and_check.py and the post-generation checks.
Goal: a standalone HTML page containing every given problem with its full, step-by-step solution. The problem statement and its figure are always visible; the solution is hidden in a <details> block until the student clicks. This lets the student attempt each problem first, then check.
references/problem-solutions.md)One card per problem. Always-visible: 题号 + 完整题目文字 + 题目图. Collapsible <details>: 解答 (every step), with the final result in an .answer-box. Multi-part problems: label (1) (2) (3), each with its own answer.
Figure rule (IMPORTANT — never drop a figure the problem depends on):
references/design-system.md.<img>. Use scripts/extract_pdf.py crop ... to cut the figure region out of a PDF page, or scripts/embed_images.py datauri <png> to turn any image file into an inline data-URI. The HTML must stay a single standalone file, so all images are base64-inlined (never external src paths).references/problem-solutions.md.Answers must be correct — verify every one. Run the blind double-solve + verification checklist in references/workflow-orchestration.md for each problem: solve, then independently re-solve from the statement alone; do every non-trivial number with python3 / sympy (no mental math); dimensional/units check, limiting cases, substitute the answer back, order-of-magnitude plausibility; state assumptions when ambiguous. If the two solves disagree, reconcile before shipping. Don't hand-wave a step the student would get stuck on. Tag verified solutions 已核验 ✓. For ≥6 independent problems, run this as a dynamic workflow / parallel subagents (one per problem).
Layout reuses the design system: each problem = a .card containing an .example-block; the figure (SVG or <img>) sits above the <details> solution. Cycle section colors by problem group or leave a single accent.
Output: <subject>作业解答.html. Subtitle: <作业范围> · 习题详解. Run scripts/build_and_check.py before presenting.
If there are many problems (≈8+) or they are independent of each other, you may solve them with parallel subagents / a Claude Code dynamic workflow — one agent per problem or per cluster — then concatenate the resulting solution cards into the final HTML. Keep all rendering rules identical across agents (same design system, same figure rule, same <details> structure) so the concatenated page is consistent. For a handful of problems, just do them inline.
references/design-system.md before writing any code. For MODE A & MODE B also read references/workflow-orchestration.md (the plan→fan-out→verify→assemble workflow). For MODE C / any solutions also read references/problem-solutions.md.scripts/extract_pdf.py) and/or problem images.scripts/build_and_check.py build <part1> <part2> ... -o <output.html> to concatenate and run the static checks, then run the three post-generation checks below and the coherence pass. Fix and re-run until clean.<outdir>/<name>.html and call present_files.Ask: "If a student had to learn this topic from scratch using only these notes, would anything important be missing?" If yes, add more. There is no upper limit on sections. Cover everything in the given scope.
General arc:
Opening: Motivation & context (why this matters, where it appears)
Prerequisites: Any assumed knowledge that is used but not derived here
Core body: One section per distinct concept — as many as needed
└─ Sub-sections within a section are fine for closely related ideas
Synthesis: Connections between concepts, unified perspective
Applications: Real physical/mathematical/engineering uses
Summary table: Side-by-side comparison of key formulas/ideas
Practice problems: Graded difficulty, all major question types
本章自测 (optional): an interactive self-test quiz — active recall, not passive re-reading
Optional — interactive 本章自测 (MODE A & MODE B). After the practice problems, you may
add a .quiz card: 3–8 multiple-choice questions that grade on click (green/red), reveal an
explanation, track a running score, and remember answers in localStorage — all self-contained
in the single file. It turns the notes from something you read into something you can test
yourself on. Full CSS + HTML pattern + the one-copy JS are in references/design-system.md →
Self-test quiz widget. Write the questions from the chapter's own pitfalls and exam points;
set data-answer to the 0-based correct index and click through once to confirm the key.
Optional — Anki deck. The notes can also carry a hidden spaced-repetition deck (a
<div id="anki-deck" hidden> of .anki-card front/back blocks — plain HTML, no JSON
escaping of LaTeX). It stays invisible in the single file; python3 scripts/make_anki.py <notes>.html exports it (plus any quiz questions) to an Anki-importable TSV. Format in
references/design-system.md → Anki flashcard deck. Emit it only when the user wants
flashcards; one card per high-value fact/formula/pitfall.
.fbox with LaTeX. Every symbol explained.<details> block. Do not skip steps; a student should be able to follow line by line. If multiple derivation routes exist, show the most illuminating one in the collapsible, mention the alternative in text..mistake callout. Be specific: not just "be careful with signs" but "students forget the negative sign in the $\hat{\boldsymbol{j}}$ component of the curl because the cofactor expansion alternates $+,-,+$"..exam callout. What to memorize, what can be derived on the spot, typical question formats.The notes should be detailed enough that a student who has attended lectures but is confused can use these notes alone to fully understand the material. Concreteness beats brevity: one well-explained derivation with intermediate steps is worth more than three terse formula statements.
Use .toc-l1 / .toc-l2 classes from the design system:
<div class="toc">
<div class="toc-title">目录</div>
<div class="toc-l1">
<a href="#s8-1"><span class="sec-dot" style="background:var(--purple-mid)"></span>§8-1 液体的微观结构</a>
<div class="toc-l2">
<a href="#s8-1-1"><span class="sec-dot" style="background:var(--purple-mid)"></span>§8-1-1 近程有序性</a>
<a href="#s8-1-2"><span class="sec-dot" style="background:var(--purple-mid)"></span>§8-1-2 液晶 ★</a>
</div>
</div>
<div class="toc-l1">
<a href="#s8-2"><span class="sec-dot" style="background:var(--teal-mid)"></span>§8-2 热传导与扩散</a>
<div class="toc-l2">
<a href="#s8-2-1"><span class="sec-dot" style="background:var(--teal-mid)"></span>§8-2-1 傅里叶定律</a>
</div>
</div>
</div>
Rules:
.toc-l1 > a links to the .sec-COLOR wrapper (id="s8-1").toc-l2 a links to the first <h3> of that sub-section (id="s8-1-1")sec-dot color for all entries within a chapter.toc-l2 ★ after title text in the TOC link第1题, 第2题, …) instead of concepts — one .toc-l1 per problem (or per problem group).The nav panel JS tracks which <h3> inside a .card is on screen. Requirements:
<h3> starting a sub-section must have an id matching the TOC href (e.g. <h3 id="s8-1-1">§8-1-1 近程有序性</h3>).<h3> text (e.g. §8-1-1). The nav panel strips leading section numbers from the label automatically.When the user supplies a PDF:
(见图 X-X:图题) inline (Step 3); MODE B/C → follow the figure rule (SVG or embed original)Trigger when the user asks for 忠实模式 / 对照课本 / 标注出处 / "anchor everything to the
book", or whenever maximum verifiability is wanted. In this mode, every formula box and
key conclusion carries a .src-ref badge pointing to its exact place in the source —
见课本 p.123 式(5-7) — so the student can check each claim against the original book, the
way NotebookLM grounds answers in citations.
scripts/extract_pdf.py text already prints --- PAGE N --- markers; record the page each
formula/definition came from while reading, and attach it as <span class="src-ref">见课本 p.N 式(X-Y)</span> next to the .fbox label (CSS in references/design-system.md →
Source citation tag)..fidelity-banner under the header so the reader knows every item is sourced.Run scripts/build_and_check.py first (it automates Checks 2 & 3 plus div-balance and forbidden-command scans on the static file). Then run all three checks below. Only present the file when all pass.
class="katex-error" is only added when KaTeX runs in the browser, so it is not present in the static HTML. To catch these, open the finished file in a browser — the template already shows a red banner counting .katex-error spans. (The static scans in Check 2/3 catch the silent failures that never raise an error.)
Common fixes:
| Error | Cause | Fix |
|---|---|---|
^\circ without base | starts the formula | Use {}^\circ\text{C}, or the \degree / \celsius macro |
\degree, \celsius, \unit, \bm, \cdotp | — | Not errors — these are pre-registered template macros (see design-system.md → KaTeX Pre-defined Macros). Use them freely; build_and_check.py is macro-aware and won't flag them. |
\SI{}, \qty{}, \si{} | siunitx, not KaTeX and not a macro | Spell the unit: 9.8\,\text{m/s}^2 |
\boldsymbol in display | missing amsmath | Use \mathbf or \bm |
python3 scripts/build_and_check.py check <file>.html # runs this automatically
Or inline:
python3 -c "
import re
html = open('<file>.html').read()
for m in re.finditer(r'(\\\$\\\$[\s\S]*?\\\$\\\$|\\\$[^\\\$]+?\\\$)', html):
span = m.group()
if chr(0x00B7) in span or chr(0x00B0) in span or chr(0x2212) in span:
line = html[:m.start()].count('\n') + 1
print(f'Line {line}: dangerous Unicode in math: ...{span[:80]}...')
"
Fix: \text{J·mol} → \text{J}\cdot\text{mol}, ° → {}^\circ, − → -, × → \times, ≈ → \approx.
Auto-repair (recovery): to rewrite every naked-Unicode-in-math hit in place instead of by hand:
python3 scripts/fix_math.py <file>.html # writes a .bak, then re-run the check
It only touches inside $…$ / $$…$$ (prose and SVG are left alone) and handles the
\text{} case correctly (a · inside \text{J/(mol·K)} becomes \text{J/(mol}\cdot\text{K)},
not a literal \cdot stuck inside the text group). Prefer writing it right the first time;
this is for cleaning up a file that already slipped.
\boxed{} inside HTML containers (CRITICAL — silent visual failure)\boxed{} wrapped around tall formulas (containing \dfrac, \sqrt, matrices) inside .fbox / .big-formula / .callout / .answer-box renders as an empty grey rectangle that covers the formula text. KaTeX raises NO error — Check 1 misses it entirely. The HTML wrappers already provide visible boxes; nested \boxed{} is redundant emphasis that breaks rendering.
grep -n '\\boxed' <file>.html
If matches found inside a colored container, REMOVE the \boxed{...} wrapper — keep only the inner formula. For full rules and bulk-strip recovery snippet, see references/design-system.md → "CRITICAL: Never use \boxed{} inside .fbox / .big-formula / .callout".
Re-run all checks after fixing.
Include in <head>:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],throwOnError:false});"></script>
(The full template in references/design-system.md registers extra macros like \degree, \d, \e, \bm and a post-render error banner — copy that template verbatim.)
$...$ | Display: $$...$$\vec{F} (arrow notation), unit vectors: \hat{n}, differentials: \mathrm{d}x\boldsymbol{} alone for vectors — bold is nearly invisible in body text.NEVER use Unicode · inside \text{}. Use \cdot (LaTeX command) instead.
| WRONG — silent failure | CORRECT |
|---|---|
$\text{J·mol}^{-1}$ | $\text{J}\cdot\text{mol}^{-1}$ |
$\text{W·m}^{-1}$ | $\text{W}\!\cdot\!\text{m}^{-1}$ |
$\text{m}^2\text{·s}^{-1}$ | $\text{m}^2\!\cdot\!\text{s}^{-1}$ |
Inside $...$ or $$...$$: ONLY ASCII and LaTeX commands — never Unicode symbols.
See references/design-system.md → KaTeX Pre-defined Macros and KaTeX Forbidden Commands for the complete macro / unit / forbidden-command tables. These naked-Unicode-in-math slips are silent — the browser shows no error — so always run the static scan before presenting:
python3 scripts/build_and_check.py check <file>.html
It flags every ·, °, −, × that lands inside a math span (and is macro-aware: a command your file registers as a macro is not reported, while the same command used without a definition still is). Treat a FAIL as blocking — never ship a file until the scan is clean.