Generates or updates tutorials from VHS tapes and Playwright specs with dual-tone markdown and GIF recording. Use when tutorial assets need refreshing.
Generates or updates tutorials from VHS tapes and Playwright specs with dual-tone markdown and GIF recording. Use when tutorial assets need refreshing.
/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.
Required TodoWrite Items
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:integration
Verification: Run the command with --help flag to verify availability.
Verification: Run the command with --help flag to verify availability.
Step 1.2: Parse Manifests
For each manifest file, extract:
Tutorial name and title
Component list (tape files, playwright specs)
Output paths for GIFs
Composition rules (layout, combine options)
See modules/manifest-parsing.md for manifest schema details.
Step 1.3: Handle Options
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.tape
Verification: Run the command with --help flag to verify availability.
CRITICAL: Validate tape commands BEFORE running VHS to avoid expensive regeneration cycles.
See modules/tape-validation.md for detailed validation logic.
Step 1.5.1: VHS Syntax Validation
Check each tape file for valid VHS syntax:
# 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" | whileread -r line; do
quote_count=$(echo"$line" | tr -cd'"' | wc -c)
if [ $((quote_count % 2)) -ne 0 ]; thenecho"ERROR: Unbalanced quotes: $line"fidone
Verification: Run the command with --help flag to verify availability.
Step 1.5.2: Extract and Validate CLI Commands
For each Type directive, extract the command and validate flags:
# Extract commands from Type directives
grep '^Type '"$tape_file" | sed 's/^Type "//' | sed 's/"$//' | whileread -r cmd; do# Skip comments, clear, and echo commands
[[ "$cmd" =~ ^# ]] && continue
[[ "$cmd" == "clear" ]] && continue# For skrills commands, validate flags existif [[ "$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; doif ! $base_cmd --help 2>&1 | grep -q -- "$flag"; thenecho"ERROR: Invalid flag '$flag' in command: $cmd"fidonefidone
Verification: Run the command with --help flag to verify availability.
Step 1.5.3: Verify Demo Data Exists
If the tape uses demo data, verify it exists and is populated:
# Check SKRILLS_SKILL_DIR if set
skill_dir=$(grep '^Env SKRILLS_SKILL_DIR'"$tape_file" | sed 's/.*"\(.*\)"/\1/')
if [ -n "$skill_dir" ]; thenif [ ! -d "$skill_dir" ]; thenecho"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 ]; thenecho"ERROR: No skills in demo directory: $skill_dir"elseecho"OK: Found $skill_count demo skills in $skill_dir"fififi
Verification: Run the command with --help flag to verify availability.
Step 1.5.4: Test Commands Locally
CRITICAL: Run each extracted command locally to verify it produces expected output:
# 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 commandsif ! timeout 5s bash -c "$cmd" &>/dev/null; thenecho"WARNING: Command may fail or hang: $cmd"fidone
Verification: Run the command with --help flag to verify availability.
Validation Flags
Flag
Behavior
--validate-only
Run validation without generating GIF
--skip-validation
Bypass validation for rapid regeneration
Validation Exit Criteria
VHS tape syntax is valid (Output directive, balanced quotes)
All CLI flags in commands are valid (verified against --help)
Demo data directories exist and are populated
Commands execute successfully with expected output
If validation fails: Stop immediately, report errors, and do NOT proceed to VHS recording.
CRITICAL: Ensure the binary being tested in tapes matches the latest source code. Stale binaries produce misleading demos.
Step 1.6.1: Detect Build System
Identify the project's build system:
# 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 Makefileelif [ -f "Makefile" ]; then
BUILD_SYSTEM="make"echo"Detected Make project"# Unknownelseecho"WARNING: Unknown build system, skipping binary check"
BUILD_SYSTEM="unknown"fi
Verification: Run make --dry-run to verify build configuration.
Step 1.6.2: Check Binary Freshness
Compare binary modification time against Git HEAD:
check_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" ]; thenecho"WARNING: Binary '$binary_name' not found in PATH"return 1
fi# Get binary modification time (Linux/macOS compatible)local binary_mtime
ifcommand -v stat >/dev/null 2>&1; then# Linux
binary_mtime=$(stat -c %Y "$binary_path" 2>/dev/null || \
# macOSstat -f %m "$binary_path" 2>/dev/null)
elseecho"WARNING: stat command not available, skipping freshness check"return 2
fi# Get Git HEAD commit timelocal git_head_time=$(git log -1 --format=%ct 2>/dev/null)
if [ -z "$git_head_time" ]; thenecho"WARNING: Not a git repository, skipping freshness check"return 2
fi# Compare timestampsif [ "$binary_mtime" -lt "$git_head_time" ]; thenecho"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
elseecho"OK: Binary is up-to-date"return 0
fi
}
Verification: Run git status to confirm working tree state.
Step 1.6.3: Rebuild Binary
Rebuild using the detected build system:
rebuild_binary() {
local build_system="$1"local binary_name="$2"case"$build_system"in
cargo)
echo"Rebuilding with Cargo..."# Use cargo install for CLI binariesif [ -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
;;
esacecho"Build complete: $binary_name"
}
Verification: Run make --dry-run to verify build configuration.
Step 1.6.4: Verify Binary Accessibility
Ensure the rebuilt binary is accessible:
verify_binary() {
local binary_name="$1"if ! command -v "$binary_name" >/dev/null 2>&1; thenecho"ERROR: Binary '$binary_name' not found after rebuild"echo" Check PATH includes: $HOME/.cargo/bin"return 1
fi# Test binary can executeif ! "$binary_name" --version >/dev/null 2>&1; thenecho"WARNING: Binary exists but --version failed"elseecho"OK: Binary is accessible and functional""$binary_name" --version
fi
}
Verification: Run pytest -v to verify tests pass.
Rebuild Flags
Flag
Behavior
--skip-rebuild
Skip binary freshness check and rebuild
--force-rebuild
Force rebuild even if binary is fresh
Rebuild Exit Criteria
Build system detected (Cargo, Make, or explicitly skipped)
Binary freshness checked against Git HEAD
Binary rebuilt if stale (or forced)
Rebuilt binary is accessible in PATH
Binary executes successfully (--version test)
If rebuild fails: Stop immediately, report build errors, and do NOT proceed to tape validation or VHS recording.
Phase 2: Recording (tutorial-updates:recording)
Step 2.1: Process Tape Components
For each tape file component:
Parse tape file for metadata annotations (@step, @docs-brief, @book-detail)
Validate Output directive exists
Invoke Skill(scry:vhs-recording) with tape file path
Verify GIF output was created
Step 2.2: Process Browser Components
For each playwright spec component:
Check requires field for prerequisite commands (e.g., start server)
Launch any required background processes
Invoke Skill(scry:browser-recording) with spec path
Stop background processes
Invoke Skill(scry:gif-generation) to convert WebM to GIF
Step 2.3: Handle Multi-Component Tutorials
For manifests with combine section:
Verify all component GIFs exist
Invoke Skill(scry:media-composition) with manifest
Verify combined output was created
Phase 3: Generation (tutorial-updates:generation)
Step 3.1: Parse Tape Annotations
Extract documentation content from tape files:
# @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)
Step 3.2: Generate Dual-Tone Markdown
Generate two versions of each tutorial:
Project docs (docs/tutorials/<name>.md)
Brief, action-oriented
Uses @docs-brief content
Focuses on commands and quick results
Technical book (book/src/tutorials/<name>.md)
Detailed, educational
Uses @book-detail content
Explains concepts and rationale
See modules/markdown-generation.md for formatting details.
Step 3.3: Generate README Demo Section
Create or update demo section in README.md:
## 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.
Create template tape file with metadata annotations
Create template manifest file
Create empty markdown files in docs/tutorials/ and book/src/tutorials/
Template tape file:
# @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.