Claude-night-market tutorial-updates
Generate tutorials from VHS tapes and Playwright specs with dual-tone markdown and GIF recording
git clone https://github.com/athola/claude-night-market
T=$(mktemp -d) && git clone --depth=1 https://github.com/athola/claude-night-market "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/sanctum/skills/tutorial-updates" ~/.claude/skills/athola-claude-night-market-tutorial-updates && rm -rf "$T"
plugins/sanctum/skills/tutorial-updates/SKILL.mdTable of Contents
- Overview
- Command Options
- Required TodoWrite Items
- Phase 1: Discovery (
)tutorial-updates:discovery - Step 1.1: Locate Tutorial Assets
- Step 1.2: Parse Manifests
- Step 1.3: Handle Options
- Phase 1.5: Validation (
)tutorial-updates:validation - Step 1.5.1: VHS Syntax Validation
- Step 1.5.2: Extract and Validate CLI Commands
- Step 1.5.3: Verify Demo Data Exists
- Step 1.5.4: Test Commands Locally
- Validation Flags
- Validation Exit Criteria
- Phase 1.6: Binary Rebuild (
)tutorial-updates:rebuild - Step 1.6.1: Detect Build System
- Step 1.6.2: Check Binary Freshness
- Step 1.6.3: Rebuild Binary
- Step 1.6.4: Verify Binary Accessibility
- Rebuild Flags
- Rebuild Exit Criteria
- Phase 2: Recording (
)tutorial-updates:recording - Step 2.1: Process Tape Components
- Step 2.2: Process Browser Components
- Step 2.3: Handle Multi-Component Tutorials
- Phase 3: Generation (
)tutorial-updates:generation - Step 3.1: Parse Tape Annotations
- Step 3.2: Generate Dual-Tone Markdown
- Step 3.3: Generate README Demo Section
- Demos
- Quickstart
- Phase 4: Integration (
)tutorial-updates:integration - Step 4.1: Verify All Outputs
- Step 4.2: Update SUMMARY.md (Book)
- Step 4.3: Report Results
- Exit Criteria
- Error Handling
- Scaffold Mode
Tutorial Updates Skill
Orchestrate tutorial generation with GIF recordings from VHS tape files and Playwright browser specs.
When To Use
- Generating or updating user-facing tutorials
- Creating VHS and Playwright tutorial recordings
When NOT To Use
- Internal documentation without user-facing tutorials
- API reference docs - use scribe:doc-generator instead
Overview
This skill coordinates the complete tutorial generation pipeline:
- Discover tape files and manifests in the project
- Validate tape commands and check binary freshness
- Rebuild binaries if stale so demos reflect latest code
- Record terminal sessions using VHS (scry:vhs-recording)
- Record browser sessions using Playwright (scry:browser-recording)
- Generate optimized GIFs (scry:gif-generation)
- Compose multi-component tutorials (scry:media-composition)
- Generate dual-tone markdown for docs/ and book/
Command Options
/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.
Phase 1: Discovery (tutorial-updates:discovery
)
tutorial-updates:discoveryStep 1.1: Locate Tutorial Assets
Find tape files and manifests in the project:
# 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.
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 |
|---|---|
| Display discovered tutorials and exit |
| Process all discovered manifests |
| Create directory structure and empty files without recording |
| 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.
Phase 1.5: Validation (tutorial-updates:validation
)
tutorial-updates:validationCRITICAL: 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" | 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.
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/"$//' | 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.
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" ]; 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.
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 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.
Validation Flags
| Flag | Behavior |
|---|---|
| Run validation without generating GIF |
| 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.
Phase 1.6: Binary Rebuild (tutorial-updates:rebuild
)
tutorial-updates:rebuildCRITICAL: 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 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.
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" ]; 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.
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 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.
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; 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.
Rebuild Flags
| Flag | Behavior |
|---|---|
| Skip binary freshness check and 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
)
tutorial-updates:recordingStep 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
with tape file pathSkill(scry:vhs-recording) - Verify GIF output was created
Step 2.2: Process Browser Components
For each playwright spec component:
- Check
field for prerequisite commands (e.g., start server)requires - Launch any required background processes
- Invoke
with spec pathSkill(scry:browser-recording) - Stop background processes
- Invoke
to convert WebM to GIFSkill(scry:gif-generation)
Step 2.3: Handle Multi-Component Tutorials
For manifests with
combine section:
- Verify all component GIFs exist
- Invoke
with manifestSkill(scry:media-composition) - Verify combined output was created
Phase 3: Generation (tutorial-updates:generation
)
tutorial-updates:generationStep 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 title/heading@step
- Concise text for project docs (docs/ directory)@docs-brief
- Extended text for technical book (book/ directory)@book-detail
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.
Phase 4: Integration (tutorial-updates:integration
)
tutorial-updates:integrationStep 4.1: Verify All Outputs
Confirm all expected files exist:
# 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.
Step 4.2: Update SUMMARY.md (Book)
If the project has an mdBook structure, update
book/src/SUMMARY.md:
- [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.
Step 4.3: Report Results
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 updated
Verification: Run the command with
--help flag to verify availability.
Exit Criteria
- All specified tutorials processed (or all if --all)
- GIF files created at manifest-specified paths
- Dual-tone markdown generated for each tutorial
- README demo section updated with GIF embeds
- Book SUMMARY.md updated (if applicable)
- All TodoWrite items completed
Error Handling
| Error | Resolution |
|---|---|
| VHS not installed | |
| Playwright not installed | |
| Tape file missing Output | Add directive |
| Browser spec requires server | Start server before running spec |
| GIF too large | Adjust fps/scale in gif-generation |
Scaffold Mode
When
--scaffold is specified, create structure without recording:
- Create
directoryassets/tapes/ - Create
directoryassets/gifs/ - Create
directory (if browser tutorials planned)assets/browser/ - 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.