一键导入
tutorial-factory
Autonomous tutorial generator — brainstorms a tutorial idea, implements it, self-reviews, and links it into the registry. Designed for /loop.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Autonomous tutorial generator — brainstorms a tutorial idea, implements it, self-reviews, and links it into the registry. Designed for /loop.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when someone asks to apply code style rules, check code style, clean up code style, or follow project code conventions.
Use when working on the klangscript module, implementing klangscript language features, working on the parser or interpreter, or needing klangscript architecture knowledge.
Use when working with Kraft UI framework, io.peekandpoke.kraft, Kraft components, VDom, Kraft routing, Kraft forms, Kraft modals, Kraft toasts, Kraft popups, or any io.peekandpoke.kraft.* package.
Use when working with ultra libs, io.peekandpoke.ultra, ultra.html events, ultra streams, ultra common utilities, or any io.peekandpoke.ultra.* package.
Use when working on the sprudel / sprudel-ksp module, implementing sprudel DSL functions, writing sprudel tests, or needing sprudel architecture knowledge.
Use when working on the klangblocks module, implementing block editor features, working on AST-to-blocks conversion, code generation, or round-trip testing for the visual block editor.
| name | tutorial-factory |
| description | Autonomous tutorial generator — brainstorms a tutorial idea, implements it, self-reviews, and links it into the registry. Designed for /loop. |
Generates one tutorial per invocation. Reads existing tutorials to avoid duplicates, brainstorms via Six Hats, implements the winning idea as a Kotlin data file, adds it to the registry, and self-reviews.
CRITICAL: This skill runs autonomously. Only use tools that do NOT require human acceptance: Read, Write, Edit, Glob, Grep, Agent. NO Bash commands. NO git commands.
Read the registry file to see what already exists:
/opt/dev/peekandpoke/klang/src/jsMain/kotlin/pages/docs/tutorials/TutorialRegistry.kt
Also read the generation log to track what has been created:
/opt/dev/peekandpoke/klang/src/jsMain/kotlin/pages/docs/tutorials/GENERATION_LOG.md
Note all existing tutorial slugs, topics, difficulty levels, and scopes. The goal is DIVERSITY — avoid duplicating topics and spread across difficulty levels and scopes.
Run /six-hats with this topic:
"What is the single best NEW tutorial to create next for the Klang live-coding music platform? It must teach something concrete using Sprudel pattern language. It must NOT overlap with existing tutorials: [list existing slugs/titles here]. Current difficulty spread: [list counts per difficulty]. Current topic spread: [list existing tags]. The tutorial should use ONLY these verified functions: note(), n(), sound(), s(), stack(), cat(), fastcat(), slowcat(), silence, fast(), slow(), gain(), pan(), lpf(), hpf(), bandf(), delay(), delaytime(), delayfeedback(), room(), rsize(), scale(), transpose(), chord(), adsr(), attack(), decay(), sustain(), release(), legato(), every(), superimpose(), jux(), scramble(), shuffle(), pick(), distort(), crush(), tremolo(), vibrato(), phaser(), sine, saw, tri, square, brown, pink, supersaw, pure(), range(), bpm(), cps, arrange(), orbit(), spread()."
From the Six Hats output, select the tutorial idea that:
Create a new file at:
src/jsMain/kotlin/pages/docs/tutorials/tut_<PascalCaseSlug>.kt
Use this template:
package io.peekandpoke.klang.pages.docs.tutorials
val <camelCaseSlug> Tutorial = Tutorial(
slug = "<kebab-case-slug>",
title = "<Human Readable Title>",
description = "<One sentence describing what the learner will achieve>",
difficulty = TutorialDifficulty.< level >,
scope = TutorialScope.< scope >,
tags = listOf(TutorialTag.< Tag1 >, TutorialTag.< Tag2 >),
// Available tags: Rhythm, Melody, Chords, Synthesis, Effects, Patterns,
// Mixing, Arrangement, LiveCoding, Generative, Genre, GettingStarted
sections = listOf(
TutorialSection(
heading = "Introduction",
text = "<Brief context — why this matters, what you'll learn>",
),
TutorialSection(
heading = "<Step heading>",
text = "<Explanation of the concept>",
code = "<working sprudel code>",
),
// 2-5 sections with progressive complexity
TutorialSection(
heading = "Putting It All Together",
text = "<Summary of what was learned>",
code = "<final combined example that sounds good>",
),
),
)
CRITICAL — every code example must be valid Sprudel that runs in the engine:
note("c3 d3 e3") not note(c3, d3, e3)sound("bd hh sd hh")note("<c3 e3 g3>")note("[c3 e3] g3")stack(pattern1, pattern2)note("c3").sound("sine").gain(0.5)n("0 2 4 6").scale("C4:major").sound("saw").adsr("0.01:0.2:0.8:0.1").lpf(800) not .lpf("800")chord() alone does NOT produce sound. Correct usage:
chord("<Am C F G>").voicing().sound("supersaw"). The chord() takes chord name strings, voicing() turns them into
notes..orbit(N). Layers sharing the same effects (or no effects) can share an orbit.
Dry drums should be on a different orbit than wet synths.n().scale().chord("minor") — that syntax is wrong. Use chord("<ChordName>").voicing()
instead.pan(0.0) = hard LEFT, pan(0.5) = CENTER, pan(1.0) = hard RIGHT. The range is 0.0 to 1.0, NOT -1
to +1.// Watch: this is where the shape emerges, // Chisel away: just a touch of reverb,
// Now carve out some stereo width, // Feel the grain: this gives great texturesound("saw"), sound("supersaw"), sound("square") must have .lpf() to
sound nice. Exception: when deliberately demonstrating the raw unfiltered sound.Edit TutorialRegistry.kt to add the new tutorial to allTutorials. Add the import and list entry.
Read back the created file and verify:
Fix any issues found.
Edit GENERATION_LOG.md to append:
| <slug> | <title> | <difficulty> | <scope> | <tags> |
After completion, briefly state: