Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generates or updates tutorials from VHS tapes and Playwright specs with dual-tone markdown and GIF recording. Use when tutorial assets need refreshing.
.claude/skills/athola-tutorial-updates/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | 258% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 175% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 157% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 300% | 0% |
| case-20 | ✗→✓ | ▲ Improved | 431% | 0% |
tutorial-updates:discovery))tutorial-updates:validation))tutorial-updates:rebuild))tutorial-updates:recording))tutorial-updates:generation))tutorial-updates:integration))Orchestrate tutorial generation with GIF recordings from VHS tape files and Playwright browser specs.
This skill coordinates the complete tutorial generation pipeline:
bash/update-tutorial quickstart # Single tutorial by name /update-tutorial sync mcp # Multiple tutorials /update-tutorial --all # All tutorials with manifests /update-tutorial --list # Show available tutorials /update-tutorial --scaffold # Create structure without recording
Verification: Run the command with --help flag to verify availability.
Create todos with these prefixes for progress tracking:
**Verification:** Run the command with `--help` flag to verify availability.
- tutorial-updates:discovery
- tutorial-updates:validation
- tutorial-updates:rebuild
- tutorial-updates:recording
- tutorial-updates:generation
- tutorial-updates:integrationVerification: Run the command with --help flag to verify availability.
tutorial-updates:discovery)Find tape files and manifests in the project:
bash# Find manifest files find . -name "*.manifest.yaml" -type f \ -not -path "*/.venv/*" -not -path "*/__pycache__/*" \ -not -path "*/node_modules/*" -not -path "*/.git/*" \ 2>/dev/null | head -20 # Find tape files find . -name "*.tape" -type f \ -not -path "*/.venv/*" -not -path "*/__pycache__/*" \ -not -path "*/node_modules/*" -not -path "*/.git/*" \ 2>/dev/null | head -20 # Find browser specs find . -name "*.spec.ts" -path "*/browser/*" -type f \ -not -path "*/.venv/*" -not -path "*/__pycache__/*" \ -not -path "*/node_modules/*" -not -path "*/.git/*" \ 2>/dev/null | head -20
Verification: Run the command with --help flag to verify availability.
For each manifest file, extract:
See modules/manifest-parsing.md for manifest schema details.
| Option | Behavior | |--------|----------| | --list | Display discovered tutorials and exit | | --all | Process all discovered manifests | | --scaffold | Create directory structure and empty files without recording | | <names> | Process only specified tutorials |
When --list is specified:
**Verification:** Run the command with `--help` flag to verify availability.
Available tutorials:
quickstart assets/tapes/quickstart.tape
sync assets/tapes/sync.tape (manifest)
mcp assets/tapes/mcp.manifest.yaml (terminal + browser)
skill-debug assets/tapes/skill-debug.tapeVerification: Run the command with --help flag to verify availability.
tutorial-updates:validation)CRITICAL: Validate tape commands BEFORE running VHS to avoid expensive regeneration cycles.
See modules/tape-validation.md for detailed validation logic.
Check each tape file for valid VHS syntax:
bash# Required: Output directive exists grep -q '^Output ' "$tape_file" || echo "ERROR: Missing Output directive" # Check for balanced quotes in Type directives grep '^Type ' "$tape_file" | while read -r line; do quote_count=$(echo "$line" | tr -cd '"' | wc -c) if [ $((quote_count % 2)) -ne 0 ]; then echo "ERROR: Unbalanced quotes: $line" fi done
Verification: Run the command with --help flag to verify availability.
For each Type directive, extract the command and validate flags:
bash# Extract commands from Type directives grep '^Type ' "$tape_file" | sed 's/^Type "//' | sed 's/"$//' | while read -r cmd; do # Skip comments, clear, and echo commands [[ "$cmd" =~ ^# ]] && continue [[ "$cmd" == "clear" ]] && continue # For skrills commands, validate flags exist if [[ "$cmd" =~ ^skrills ]]; then base_cmd=$(echo "$cmd" | awk '{print $1, $2}') flags=$(echo "$cmd" | grep -oE '\-\-[a-zA-Z0-9-]+' || true) for flag in $flags; do if ! $base_cmd --help 2>&1 | grep -q -- "$flag"; then echo "ERROR: Invalid flag '$flag' in command: $cmd" fi done fi done
Verification: Run the command with --help flag to verify availability.
If the tape uses demo data, verify it exists and is populated:
bash# Check SKRILLS_SKILL_DIR if set skill_dir=$(grep '^Env SKRILLS_SKILL_DIR' "$tape_file" | sed 's/.*"\(.*\)"/\1/') if [ -n "$skill_dir" ]; then if [ ! -d "$skill_dir" ]; then echo "ERROR: Demo skill directory missing: $skill_dir" else skill_count=$(find "$skill_dir" -name "SKILL.md" 2>/dev/null | wc -l) if [ "$skill_count" -eq 0 ]; then echo "ERROR: No skills in demo directory: $skill_dir" else echo "OK: Found $skill_count demo skills in $skill_dir" fi fi fi
Verification: Run the command with --help flag to verify availability.
CRITICAL: Run each extracted command locally to verify it produces expected output:
bash# For each command in the tape, do a quick sanity check # This catches issues like: # - Commands that exit with non-zero status # - Commands that produce no output (won't show anything in GIF) # - Commands that require user input (will hang VHS) for cmd in $(extract_commands "$tape_file"); do # Run with timeout to catch hanging commands if ! timeout 5s bash -c "$cmd" &>/dev/null; then echo "WARNING: Command may fail or hang: $cmd" fi done
Verification: Run the command with --help flag to verify availability.
| Flag | Behavior | |------|----------| | --validate-only | Run validation without generating GIF | | --skip-validation | Bypass validation for rapid regeneration |
If validation fails: Stop immediately, report errors, and do NOT proceed to VHS recording.
tutorial-updates:rebuild)CRITICAL: Ensure the binary being tested in tapes matches the latest source code. Stale binaries produce misleading demos.
Identify the project's build system:
bash# Check for Cargo (Rust) if [ -f "Cargo.toml" ]; then BUILD_SYSTEM="cargo" BINARY_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') echo "Detected Cargo project: $BINARY_NAME" # Check for Makefile elif [ -f "Makefile" ]; then BUILD_SYSTEM="make" echo "Detected Make project" # Unknown else echo "WARNING: Unknown build system, skipping binary check" BUILD_SYSTEM="unknown" fi
Verification: Run make --dry-run to verify build configuration.
Compare binary modification time against Git HEAD:
bashcheck_binary_freshness() { local binary_name="$1" # Locate binary (check cargo install location first, then PATH) local binary_path=$(which "$binary_name" 2>/dev/null) if [ -z "$binary_path" ]; then echo "WARNING: Binary '$binary_name' not found in PATH" return 1 fi # Get binary modification time (Linux/macOS compatible) local binary_mtime if command -v stat >/dev/null 2>&1; then # Linux binary_mtime=$(stat -c %Y "$binary_path" 2>/dev/null || \ # macOS stat -f %m "$binary_path" 2>/dev/null) else echo "WARNING: stat command not available, skipping freshness check" return 2 fi # Get Git HEAD commit time local git_head_time=$(git log -1 --format=%ct 2>/dev/null) if [ -z "$git_head_time" ]; then echo "WARNING: Not a git repository, skipping freshness check" return 2 fi # Compare timestamps if [ "$binary_mtime" -lt "$git_head_time" ]; then echo "STALE: Binary is older than Git HEAD" echo " Binary: $(date -d @$binary_mtime 2>/dev/null || date -r $binary_mtime)" echo " HEAD: $(date -d @$git_head_time 2>/dev/null || date -r $git_head_time)" return 1 else echo "OK: Binary is up-to-date" return 0 fi }
Verification: Run git status to confirm working tree state.
Rebuild using the detected build system:
bashrebuild_binary() { local build_system="$1" local binary_name="$2" case "$build_system" in cargo) echo "Rebuilding with Cargo..." # Use cargo install for CLI binaries if [ -d "crates/cli" ]; then cargo install --path crates/cli --locked --quiet else cargo install --path . --locked --quiet fi ;; make) echo "Rebuilding with Make..." make build --quiet ;; *) echo "ERROR: Cannot rebuild, unknown build system" return 1 ;; esac echo "Build complete: $binary_name" }
Verification: Run make --dry-run to verify build configuration.
Ensure the rebuilt binary is accessible:
bashverify_binary() { local binary_name="$1" if ! command -v "$binary_name" >/dev/null 2>&1; then echo "ERROR: Binary '$binary_name' not found after rebuild" echo " Check PATH includes: $HOME/.cargo/bin" return 1 fi # Test binary can execute if ! "$binary_name" --version >/dev/null 2>&1; then echo "WARNING: Binary exists but --version failed" else echo "OK: Binary is accessible and functional" "$binary_name" --version fi }
Verification: Run pytest -v to verify tests pass.
| Flag | Behavior | |------|----------| | --skip-rebuild | Skip binary freshness check and rebuild | | --force-rebuild | Force rebuild even if binary is fresh |
If rebuild fails: Stop immediately, report build errors, and do NOT proceed to tape validation or VHS recording.
tutorial-updates:recording)For each tape file component:
Skill(scry:vhs-recording) with tape file pathFor each playwright spec component:
requires field for prerequisite commands (e.g., start server)Skill(scry:browser-recording) with spec pathSkill(scry:gif-generation) to convert WebM to GIFFor manifests with combine section:
Skill(scry:media-composition) with manifesttutorial-updates:generation)Extract documentation content from tape files:
tape# @step Install skrills # @docs-brief Install via cargo # @book-detail The recommended installation method uses cargo... Type "cargo install skrills"
Verification: Run the command with --help flag to verify availability.
Annotations:
@step - Step title/heading@docs-brief - Concise text for project docs (docs/ directory)@book-detail - Extended text for technical book (book/ directory)Generate two versions of each tutorial:
docs/tutorials/<name>.md)book/src/tutorials/<name>.md)See modules/markdown-generation.md for formatting details.
Create or update demo section in README.md:
markdown## Demos ### Quickstart  *Install, validate, analyze, and serve in under a minute. [Full tutorial](docs/tutorials/quickstart.md)*
Verification: Run the command with --help flag to verify availability.
tutorial-updates:integration)Confirm all expected files exist:
bash# Check GIF files for gif in assets/gifs/*.gif; do if [[ -f "$gif" ]]; then echo "OK: $gif ($(du -h "$gif" | cut -f1))" else echo "MISSING: $gif" fi done # Check markdown files ls -la docs/tutorials/*.md 2>/dev/null ls -la book/src/tutorials/*.md 2>/dev/null
Verification: Run the command with --help flag to verify availability.
If the project has an mdBook structure, update book/src/SUMMARY.md:
markdown- [Tutorials](./tutorials/README.md) - [Quickstart](./tutorials/quickstart.md) - [Sync Workflow](./tutorials/sync.md) - [MCP Integration](./tutorials/mcp.md) - [Skill Debugging](./tutorials/skill-debug.md)
Verification: Run the command with --help flag to verify availability.
Summarize the update:
**Verification:** Run the command with `--help` flag to verify availability.
Tutorial Update Complete
========================
Tutorials processed: 4
GIFs generated: 5
- quickstart.gif (1.2MB)
- sync.gif (980KB)
- mcp-terminal.gif (1.5MB)
- mcp-browser.gif (2.1MB)
- skill-debug.gif (890KB)
Markdown generated:
- docs/tutorials/ (4 files)
- book/src/tutorials/ (4 files)
README demo section updatedVerification: Run the command with --help flag to verify availability.
| Error | Resolution | |-------|------------| | VHS not installed | go install github.com/charmbracelet/vhs@latest | | Playwright not installed | npm install -D @playwright/test && npx playwright install chromium | | Tape file missing Output | Add Output assets/gifs/<name>.gif directive | | Browser spec requires server | Start server before running spec | | GIF too large | Adjust fps/scale in gif-generation |
When --scaffold is specified, create structure without recording:
assets/tapes/ directoryassets/gifs/ directoryassets/browser/ directory (if browser tutorials planned)Template tape file:
tape# @title: Tutorial Name # @description: Brief description of the tutorial Output assets/gifs/tutorial-name.gif Set FontSize 14 Set Width 1200 Set Height 600 Set Theme "Catppuccin Mocha" # @step Step 1 Title # @docs-brief Brief docs text # @book-detail Extended book text with more context and explanation Type "command here" Enter Sleep 2s
Verification: Run the command with --help flag to verify availability.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 5,840 | 7,279 | +25% | 1 | 1 | 0% | 310 | 5,770 | +1761% | 0 | 0 | — |
case-01 | fail→fail | 27,688 | 8,096 | -71% | 1 | 1 | 0% | 2,878 | 5,775 | +101% | 0 | 0 | — |
case-02 | fail→fail | 12,767 | 13,707 | +7% | 1 | 1 | 0% | 2,185 | 5,799 | +165% | 0 | 0 | — |
case-04 | fail→fail | 7,858 | 5,365 | -32% | 1 | 1 | 0% | 1,032 | 6,118 | +493% | 0 | 0 | — |
case-05 | fail→fail | 10,003 | 6,293 | -37% | 1 | 1 | 0% | 1,748 | 5,771 | +230% | 0 | 0 | — |
case-06 | fail→fail | 4,525 | 9,035 | +100% | 1 | 1 | 0% | 639 | 5,820 | +811% | 0 | 0 | — |
case-07 | fail→fail | 8,727 | 11,407 | +31% | 1 | 1 | 0% | 1,380 | 6,673 | +384% | 0 | 0 | — |
case-08 | fail→fail | 5,850 | 6,834 | +17% | 1 | 1 | 0% | 907 | 5,750 | +534% | 0 | 0 | — |
case-09 | pass→pass | 9,225 | 6,856 | -26% | 1 | 1 | 0% | 1,719 | 6,823 | +297% | 0 | 0 | — |
case-10 | pass→pass | 6,184 | 3,287 | -47% | 1 | 1 | 0% | 1,062 | 5,971 | +462% | 0 | 0 | — |
case-11 | pass→pass | 5,501 | 3,103 | -44% | 1 | 1 | 0% | 807 | 5,820 | +621% | 0 | 0 | — |
case-12 | fail→pass | 10,163 | 2,467 | -76% | 1 | 1 | 0% | 1,638 | 5,861 | +258% | 0 | 0 | — |
case-13 | fail→pass | 14,034 | 2,079 | -85% | 1 | 1 | 0% | 2,093 | 5,762 | +175% | 0 | 0 | — |
case-14 | fail→pass | 13,460 | 8,858 | -34% | 1 | 1 | 0% | 2,736 | 7,036 | +157% | 0 | 0 | — |
case-15 | pass→pass | 15,535 | 6,178 | -60% | 1 | 1 | 0% | 2,730 | 6,562 | +140% | 0 | 0 | — |
case-16 | fail→pass | 8,874 | 4,797 | -46% | 1 | 1 | 0% | 1,532 | 6,134 | +300% | 0 | 0 | — |
case-17 | fail→fail | 2,055 | 8,651 | +321% | 1 | 1 | 0% | 185 | 5,972 | +3128% | 0 | 0 | — |
case-18 | pass→pass | 14,232 | 4,867 | -66% | 1 | 1 | 0% | 2,314 | 6,337 | +174% | 0 | 0 | — |
case-19 | fail→fail | 11,188 | 3,481 | -69% | 1 | 1 | 0% | 1,144 | 5,935 | +419% | 0 | 0 | — |
case-20 | fail→pass | 6,588 | 2,495 | -62% | 1 | 1 | 0% | 1,086 | 5,765 | +431% | 0 | 0 | — |
case-21 | pass→fail | 12,493 | 7,095 | -43% | 1 | 1 | 0% | 1,885 | 5,792 | +207% | 0 | 0 | — |
case-22 | pass→pass | 18,722 | 16,523 | -12% | 1 | 1 | 0% | 3,873 | 8,647 | +123% | 0 | 0 | — |
case-23 | pass→pass | 12,284 | 32,104 | +161% | 1 | 1 | 0% | 2,144 | 8,742 | +308% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 17 counted toward the lift figure. The other 6 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +17 percentage points is the difference between those two pass rates over the 17 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.