Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:18:13 +08:00
commit b8a1bfd4a1
12 changed files with 1582 additions and 0 deletions

View File

@@ -0,0 +1,346 @@
---
name: cli-demo-generator
description: This skill should be used when users want to create animated CLI demos, terminal recordings, or command-line demonstration GIFs. It supports both manual tape file creation and automated demo generation from command descriptions. Use when users mention creating demos, recording terminal sessions, or generating animated GIFs of CLI workflows.
---
# CLI Demo Generator
Generate professional animated CLI demos with ease. This skill supports both automated generation from command descriptions and manual control for custom demos.
## When to Use This Skill
Trigger this skill when users request:
- "Create a demo showing how to install my package"
- "Generate a CLI demo of these commands"
- "Make an animated GIF of my terminal workflow"
- "Record a terminal session and convert to GIF"
- "Batch generate demos from this config"
- "Create an interactive typing demo"
## Core Capabilities
### 1. Automated Demo Generation (Recommended)
Use the `auto_generate_demo.py` script for quick, automated demo creation. This is the easiest and most common approach.
**Basic Usage:**
```bash
scripts/auto_generate_demo.py \
-c "npm install my-package" \
-c "npm run build" \
-o demo.gif
```
**With Options:**
```bash
scripts/auto_generate_demo.py \
-c "command1" \
-c "command2" \
-o output.gif \
--title "Installation Demo" \
--theme "Dracula" \
--width 1400 \
--height 700
```
**Script Parameters:**
- `-c, --command`: Command to include (can be specified multiple times)
- `-o, --output`: Output GIF file path (required)
- `--title`: Demo title (optional, shown at start)
- `--theme`: VHS theme (default: Dracula)
- `--font-size`: Font size (default: 16)
- `--width`: Terminal width (default: 1400)
- `--height`: Terminal height (default: 700)
- `--no-execute`: Generate tape file only, don't execute VHS
**Smart Features:**
- Automatic timing based on command complexity
- Optimized sleep durations (1-3s depending on operation)
- Proper spacing between commands
- Professional defaults
### 2. Batch Demo Generation
Use `batch_generate.py` for creating multiple demos from a configuration file.
**Configuration File (YAML):**
```yaml
demos:
- name: "Install Demo"
output: "install.gif"
title: "Installation"
theme: "Dracula"
commands:
- "npm install my-package"
- "npm run build"
- name: "Usage Demo"
output: "usage.gif"
commands:
- "my-package --help"
- "my-package run"
```
**Usage:**
```bash
scripts/batch_generate.py config.yaml --output-dir ./demos
```
**When to Use Batch Generation:**
- Creating a suite of related demos
- Documenting multiple features
- Generating demos for tutorials or documentation
- Maintaining consistent demo series
### 3. Interactive Recording
Use `record_interactive.sh` for recording live terminal sessions.
**Usage:**
```bash
scripts/record_interactive.sh output.gif \
--theme "Dracula" \
--width 1400
```
**Recording Process:**
1. Script starts asciinema recording
2. Type commands naturally in your terminal
3. Press Ctrl+D when finished
4. Script auto-converts to GIF via VHS
**When to Use Interactive Recording:**
- Demonstrating complex workflows
- Showing real command output
- Capturing live interactions
- Recording debugging sessions
### 4. Manual Tape File Creation
For maximum control, create VHS tape files manually using templates.
**Available Templates:**
- `assets/templates/basic.tape` - Simple command demo
- `assets/templates/interactive.tape` - Typing simulation
**Example Workflow:**
1. Copy template: `cp assets/templates/basic.tape my-demo.tape`
2. Edit commands and timing
3. Generate GIF: `vhs < my-demo.tape`
Consult `references/vhs_syntax.md` for complete VHS syntax reference.
## Workflow Guidance
### For Simple Demos (1-3 commands)
Use automated generation for quick results:
```bash
scripts/auto_generate_demo.py \
-c "echo 'Hello World'" \
-c "ls -la" \
-o hello-demo.gif \
--title "Hello Demo"
```
### For Multiple Related Demos
Create a batch configuration file and use batch generation:
1. Create `demos-config.yaml` with all demo definitions
2. Run: `scripts/batch_generate.py demos-config.yaml --output-dir ./output`
3. All demos generate automatically with consistent settings
### For Interactive/Complex Workflows
Use interactive recording to capture real behavior:
```bash
scripts/record_interactive.sh my-workflow.gif
# Type commands naturally
# Ctrl+D when done
```
### For Custom Timing/Layout
Create manual tape file with precise control:
1. Start with template or generate base tape with `--no-execute`
2. Edit timing, add comments, customize layout
3. Generate: `vhs < custom-demo.tape`
## Best Practices
Refer to `references/best_practices.md` for comprehensive guidelines. Key recommendations:
**Timing:**
- Quick commands (ls, pwd): 1s sleep
- Standard commands (grep, cat): 2s sleep
- Heavy operations (install, build): 3s+ sleep
**Sizing:**
- Standard: 1400x700 (recommended)
- Compact: 1200x600
- Presentations: 1800x900
**Themes:**
- Documentation: Nord, GitHub Dark
- Code demos: Dracula, Monokai
- Presentations: High-contrast themes
**Duration:**
- Target: 15-30 seconds
- Maximum: 60 seconds
- Create series for complex topics
## Troubleshooting
### VHS Not Installed
```bash
# macOS
brew install vhs
# Linux (via Go)
go install github.com/charmbracelet/vhs@latest
```
### Asciinema Not Installed
```bash
# macOS
brew install asciinema
# Linux
sudo apt install asciinema
```
### Demo File Too Large
**Solutions:**
1. Reduce duration (shorter sleep times)
2. Use smaller dimensions (1200x600)
3. Consider MP4 format: `Output demo.mp4`
4. Split into multiple shorter demos
### Output Not Readable
**Solutions:**
1. Increase font size: `--font-size 18`
2. Use wider terminal: `--width 1600`
3. Choose high-contrast theme: `--theme "Dracula"`
4. Test on target display device
## Examples
### Example 1: Quick Install Demo
User request: "Create a demo showing npm install"
```bash
scripts/auto_generate_demo.py \
-c "npm install my-package" \
-o install-demo.gif \
--title "Package Installation"
```
### Example 2: Multi-Step Tutorial
User request: "Create a demo showing project setup with git clone, install, and run"
```bash
scripts/auto_generate_demo.py \
-c "git clone https://github.com/user/repo.git" \
-c "cd repo" \
-c "npm install" \
-c "npm start" \
-o setup-demo.gif \
--title "Project Setup" \
--theme "Nord"
```
### Example 3: Batch Generation
User request: "Generate demos for all my CLI tool features"
1. Create `features-demos.yaml`:
```yaml
demos:
- name: "Help Command"
output: "help.gif"
commands: ["my-tool --help"]
- name: "Init Command"
output: "init.gif"
commands: ["my-tool init", "ls -la"]
- name: "Run Command"
output: "run.gif"
commands: ["my-tool run --verbose"]
```
2. Generate all:
```bash
scripts/batch_generate.py features-demos.yaml --output-dir ./demos
```
### Example 4: Interactive Session
User request: "Record me using my CLI tool interactively"
```bash
scripts/record_interactive.sh my-session.gif --theme "Tokyo Night"
# User types commands naturally
# Ctrl+D to finish
```
## Bundled Resources
### scripts/
- **`auto_generate_demo.py`** - Automated demo generation from command lists
- **`batch_generate.py`** - Generate multiple demos from YAML/JSON config
- **`record_interactive.sh`** - Record and convert interactive terminal sessions
### references/
- **`vhs_syntax.md`** - Complete VHS tape file syntax reference
- **`best_practices.md`** - Demo creation guidelines and best practices
### assets/
- **`templates/basic.tape`** - Basic command demo template
- **`templates/interactive.tape`** - Interactive typing demo template
- **`examples/batch-config.yaml`** - Example batch configuration file
## Dependencies
**Required:**
- VHS (https://github.com/charmbracelet/vhs)
**Optional:**
- asciinema (for interactive recording)
- PyYAML (for batch YAML configs): `pip install pyyaml`
## Output Formats
VHS supports multiple output formats:
```tape
Output demo.gif # GIF (default, best for documentation)
Output demo.mp4 # MP4 (better compression for long demos)
Output demo.webm # WebM (smaller file size)
```
Choose based on use case:
- **GIF**: Documentation, README files, easy embedding
- **MP4**: Longer demos, better quality, smaller size
- **WebM**: Web-optimized, smallest file size
## Summary
This skill provides three main approaches:
1. **Automated** (`auto_generate_demo.py`) - Quick, easy, smart defaults
2. **Batch** (`batch_generate.py`) - Multiple demos, consistent settings
3. **Interactive** (`record_interactive.sh`) - Live recording, real output
Choose the approach that best fits the user's needs. For most cases, automated generation is the fastest and most convenient option.

View File

@@ -0,0 +1,31 @@
# Example batch configuration for generating multiple demos
# Usage: batch_generate.py batch-config.yaml --output-dir ./output
demos:
- name: "Installation Demo"
output: "install.gif"
title: "Package Installation"
theme: "Dracula"
width: 1400
height: 700
commands:
- "npm install my-package"
- "npm run build"
- name: "Usage Demo"
output: "usage.gif"
title: "Basic Usage"
theme: "Nord"
commands:
- "my-package --help"
- "my-package init"
- "my-package run"
- name: "Quick Start"
output: "quickstart.gif"
theme: "Tokyo Night"
commands:
- "git clone https://github.com/user/repo.git"
- "cd repo"
- "npm install"
- "npm start"

View File

@@ -0,0 +1,18 @@
Output demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Dracula"
Set Padding 20
Type "# Demo Title" Sleep 500ms Enter
Sleep 1s
Type "command1" Sleep 500ms
Enter
Sleep 2s
Type "command2" Sleep 500ms
Enter
Sleep 2s

View File

@@ -0,0 +1,21 @@
Output demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Dracula"
Set Padding 20
Set TypingSpeed 100ms
Type "# Interactive Demo" Sleep 500ms Enter
Sleep 1.5s
Type "# Type commands naturally..." Sleep 500ms Enter
Sleep 1s
Type "echo 'Hello World'" Sleep 500ms
Enter
Sleep 2s
Type "# Typing simulation makes it feel real" Sleep 500ms Enter
Sleep 2s

View File

@@ -0,0 +1,372 @@
# CLI Demo Best Practices
Guidelines for creating effective, professional CLI demos.
## General Principles
### 1. Keep It Short
- **Target**: 15-30 seconds per demo
- **Maximum**: 60 seconds (unless documenting complex workflows)
- **Reason**: Short demos maintain viewer attention and are easier to consume
### 2. Show, Don't Tell
- Focus on visual demonstration over textual explanation
- Let the commands and output speak for themselves
- Add brief comment-style titles when needed
### 3. One Concept Per Demo
- Each demo should illustrate a single feature or workflow
- For complex topics, create a series of short demos
- Better to have multiple focused demos than one lengthy tutorial
## Technical Guidelines
### Timing and Pacing
**Command Entry Timing:**
```
Type "command" Sleep 500ms # Fast enough to feel natural
Enter # Immediate
```
**Post-Command Sleep (based on operation):**
- **Quick commands** (ls, pwd, echo): 1s
- **Standard commands** (grep, cat, git status): 1.5-2s
- **Heavy operations** (install, build, test): 3s+
- **Final command**: 2-3s for viewers to see result
**Between Sections:**
- Add 1-1.5s between related commands
- Add 2s+ between different concepts
### Terminal Dimensions
**Standard Sizes:**
```tape
# Compact (for narrow contexts)
Set Width 1200
Set Height 600
# Standard (recommended default)
Set Width 1400
Set Height 700
# Wide (for complex output)
Set Width 1600
Set Height 800
# Presentation (for slides)
Set Width 1800
Set Height 900
```
**Choosing Dimensions:**
- Consider the output width (avoid wrapping)
- Test with longest expected line
- Standard 1400x700 works for most cases
### Font Sizing
**Recommended Sizes:**
```tape
# Documentation (small, information-dense)
Set FontSize 14
# Standard demos (readable)
Set FontSize 16
# Presentations (clear from distance)
Set FontSize 20-24
```
**Choosing Font Size:**
- Smaller fonts allow more output visibility
- Larger fonts improve readability on mobile
- Test on target display devices
### Theme Selection
**By Context:**
**Documentation/Tutorials:**
- Nord - Clean, professional
- GitHub Dark - Familiar to developers
- Catppuccin - Easy on eyes for long reading
**Code Demos:**
- Dracula - Popular, high contrast
- Monokai - Classic, widely recognized
- Tokyo Night - Modern, vibrant
**Presentations:**
- High-contrast themes for visibility
- Avoid very dark themes in bright rooms
- Test on actual projection equipment
**Brand Alignment:**
- Match company/project color schemes
- Custom themes can be defined
## Content Guidelines
### Command Structure
**Clear Sequencing:**
```tape
# Good - Shows logical flow
Type "# Step 1: Setup"
Sleep 500ms Enter
Type "mkdir project && cd project"
Sleep 500ms Enter
Sleep 2s
Type "# Step 2: Install"
Sleep 500ms Enter
Type "npm install"
Sleep 500ms Enter
Sleep 3s
```
**Avoid:**
```tape
# Bad - No context, rushed
Type "mkdir project"
Enter
Type "cd project"
Enter
Type "npm install"
Enter
```
### Adding Context
**Title Slides:**
```tape
Type "# Demo: Package Installation"
Sleep 500ms Enter
Sleep 1.5s
```
**Section Headers:**
```tape
Type "## Installing dependencies..."
Sleep 500ms Enter
Sleep 1s
```
**Comments:**
```tape
Type "npm install # This may take a moment"
Sleep 500ms Enter
```
### Output Visibility
**Ensure Key Output is Visible:**
- Let important output display fully before next command
- For long output, consider showing excerpts
- Use `Sleep` to give viewers time to read
**Managing Long Output:**
```tape
# Option 1: Show beginning only
Type "npm install"
Enter
Sleep 2s # Shows first part of output
Ctrl+C # Stop before it scrolls too much
# Option 2: Use commands that limit output
Type "git log --oneline -5" # Show last 5 commits only
Enter
```
## File Size Optimization
### Target Sizes
- **Small demos** (<500KB): Ideal for documentation
- **Medium demos** (500KB-1MB): Acceptable for most uses
- **Large demos** (>1MB): Consider compression or shorter duration
### Reducing File Size
**1. Shorter Duration:**
```tape
# Reduce unnecessary sleep time
Sleep 1s # Instead of Sleep 3s
```
**2. Smaller Dimensions:**
```tape
# Use compact size for simple demos
Set Width 1200
Set Height 600
```
**3. Appropriate Format:**
```tape
Output demo.mp4 # Better compression for longer demos
Output demo.webm # Smaller file size than GIF
Output demo.gif # Good for short demos
```
## Accessibility
### Consider All Viewers
**Color Choices:**
- High contrast improves readability
- Avoid color-only distinctions
- Test with color-blind simulators
**Font Size:**
- 16pt minimum for web documentation
- 20pt minimum for presentations
- Test on mobile devices
**Pacing:**
- Allow time to read output
- Avoid rapid command sequences
- Provide clear visual breaks
## Testing and Quality Assurance
### Before Publishing
**1. Watch the Entire Demo:**
- Verify all commands execute as expected
- Check for timing issues
- Ensure output is visible
**2. Test on Different Displays:**
- Desktop monitors
- Mobile devices
- Projection screens (if for presentations)
**3. Check File Size:**
- Optimize if necessary
- Consider alternative formats
**4. Verify Accessibility:**
- Readable fonts
- Clear contrast
- Appropriate pacing
**5. Get Feedback:**
- Show to someone unfamiliar with the content
- Ask if the flow is clear
- Adjust based on feedback
## Common Mistakes to Avoid
### ❌ Too Fast
```tape
Type "command1" Enter Sleep 0.5s
Type "command2" Enter Sleep 0.5s
Type "command3" Enter Sleep 0.5s
# Viewers can't process this
```
### ✅ Appropriate Pacing
```tape
Type "command1" Sleep 500ms Enter
Sleep 2s
Type "command2" Sleep 500ms Enter
Sleep 2s
```
### ❌ No Context
```tape
Type "npm install"
Enter
# What are we installing? Why?
```
### ✅ With Context
```tape
Type "# Installing dependencies"
Sleep 500ms Enter
Sleep 1s
Type "npm install"
Sleep 500ms Enter
```
### ❌ Output Scrolls Too Fast
```tape
Type "long-running-command"
Enter
Sleep 1s # Output still scrolling!
Type "next-command"
```
### ✅ Allow Output to Complete
```tape
Type "long-running-command"
Enter
Sleep 3s # Let it finish
Type "next-command"
```
## Examples of Good Demos
### Simple Feature Demo (15 seconds)
```tape
Output feature-demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Dracula"
Type "# Demo: Quick Start" Sleep 500ms Enter
Sleep 1.5s
Type "npm install my-tool" Sleep 500ms Enter
Sleep 2.5s
Type "my-tool --help" Sleep 500ms Enter
Sleep 2s
```
### Multi-Step Workflow (30 seconds)
```tape
Output workflow-demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Nord"
Type "# Demo: Complete Workflow" Sleep 500ms Enter
Sleep 1.5s
Type "# 1. Create project" Sleep 500ms Enter
Type "mkdir my-project && cd my-project" Sleep 500ms Enter
Sleep 2s
Type "# 2. Initialize" Sleep 500ms Enter
Type "npm init -y" Sleep 500ms Enter
Sleep 2s
Type "# 3. Install package" Sleep 500ms Enter
Type "npm install express" Sleep 500ms Enter
Sleep 3s
Type "# 4. Ready to code!" Sleep 500ms Enter
Sleep 2s
```
## Summary Checklist
Before publishing a demo, verify:
- [ ] Duration is appropriate (15-30s ideal)
- [ ] Timing allows reading output
- [ ] Commands are clear and purposeful
- [ ] Context is provided where needed
- [ ] Output is fully visible
- [ ] File size is reasonable
- [ ] Theme and fonts are readable
- [ ] Tested on target devices
- [ ] Accessible to all viewers
- [ ] Demonstrates one clear concept

View File

@@ -0,0 +1,241 @@
# VHS Tape File Syntax Reference
VHS (Video Home System) is a tool for creating terminal recordings as code. This reference covers the complete tape file syntax.
## Basic Structure
```tape
Output demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Dracula"
Type "echo Hello"
Enter
Sleep 1s
```
## Configuration Commands
### Output
Specify the output file path and format:
```tape
Output demo.gif # GIF format (default)
Output demo.mp4 # MP4 video
Output demo.webm # WebM video
```
### Set Commands
Configure the terminal appearance:
```tape
Set FontSize 16 # Font size (10-72)
Set Width 1400 # Terminal width in pixels
Set Height 700 # Terminal height in pixels
Set Theme "Dracula" # Color theme
Set Padding 20 # Padding around terminal (pixels)
Set TypingSpeed 50ms # Speed of typing animation
Set Shell bash # Shell to use (bash, zsh, fish)
Set FontFamily "MonoLisa" # Font family name
```
## Interaction Commands
### Type
Simulate typing text:
```tape
Type "ls -la" # Type the command
Type "Hello World" # Type any text
```
### Enter
Press the Enter key:
```tape
Enter
```
### Backspace
Delete characters:
```tape
Backspace # Delete one character
Backspace 5 # Delete 5 characters
```
### Sleep
Pause execution:
```tape
Sleep 1s # Sleep for 1 second
Sleep 500ms # Sleep for 500 milliseconds
Sleep 2.5s # Sleep for 2.5 seconds
```
### Ctrl+C
Send interrupt signal:
```tape
Ctrl+C
```
### Key combinations
```tape
Ctrl+D # End of transmission
Ctrl+L # Clear screen
Tab # Tab completion
```
## Advanced Features
### Play (asciinema integration)
Play back an asciinema recording:
```tape
Play recording.cast
```
### Hide/Show
Control terminal visibility:
```tape
Hide
Type "secret command"
Show
```
### Screenshot
Take a screenshot at specific point:
```tape
Screenshot demo-screenshot.png
```
## Available Themes
Popular built-in themes:
- **Dracula** - Dark purple theme
- **Monokai** - Classic dark theme
- **Nord** - Arctic-inspired cool theme
- **Catppuccin** - Soothing pastel theme
- **GitHub Dark** - GitHub's dark theme
- **Tokyo Night** - Vibrant dark theme
- **Gruvbox** - Retro groove colors
## Example Templates
### Basic Command Demo
```tape
Output demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Dracula"
Type "# Demo Title" Sleep 500ms Enter
Sleep 1s
Type "command1" Sleep 500ms Enter
Sleep 2s
Type "command2" Sleep 500ms Enter
Sleep 2s
```
### Interactive Typing Demo
```tape
Output demo.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Dracula"
Set TypingSpeed 100ms
Type "npm install my-package"
Enter
Sleep 3s
Type "npm start"
Enter
Sleep 2s
```
### Multi-Step Tutorial
```tape
Output tutorial.gif
Set FontSize 16
Set Width 1400
Set Height 700
Set Theme "Tokyo Night"
Type "# Step 1: Clone the repository" Enter
Sleep 1s
Type "git clone https://github.com/user/repo.git" Enter
Sleep 3s
Type "# Step 2: Install dependencies" Enter
Sleep 1s
Type "cd repo && npm install" Enter
Sleep 3s
Type "# Step 3: Run the app" Enter
Sleep 1s
Type "npm start" Enter
Sleep 2s
```
## Best Practices
1. **Timing**: Use appropriate sleep durations
- Quick commands: 1s
- Medium commands: 2s
- Long commands (install, build): 3s+
2. **Width/Height**: Standard sizes
- Compact: 1200x600
- Standard: 1400x700
- Wide: 1600x800
3. **Font Size**: Readability
- Small terminals: 14-16
- Standard: 16-18
- Presentations: 20-24
4. **Theme Selection**: Consider context
- Code demos: Dracula, Monokai
- Documentation: Nord, GitHub Dark
- Presentations: High-contrast themes
5. **Title Slides**: Add context
```tape
Type "# Demo: Project Setup" Enter
Sleep 1s
```
6. **Cleanup**: Show clear ending
```tape
Sleep 2s
Type "# Demo complete!" Enter
```

View File

@@ -0,0 +1,151 @@
#!/usr/bin/env python3
"""
Auto-generate CLI demos from command descriptions.
This script creates VHS tape files and generates GIF demos automatically.
"""
import argparse
import subprocess
import sys
from pathlib import Path
from typing import List, Optional
def create_tape_file(
commands: List[str],
output_gif: str,
title: Optional[str] = None,
theme: str = "Dracula",
font_size: int = 16,
width: int = 1400,
height: int = 700,
padding: int = 20,
) -> str:
"""Generate a VHS tape file from commands."""
tape_lines = [
f'Output {output_gif}',
'',
f'Set FontSize {font_size}',
f'Set Width {width}',
f'Set Height {height}',
f'Set Theme "{theme}"',
f'Set Padding {padding}',
'',
]
# Add title if provided
if title:
tape_lines.extend([
f'Type "# {title}" Sleep 500ms Enter',
'Sleep 1s',
'',
])
# Add commands with smart timing
for i, cmd in enumerate(commands, 1):
# Type the command
tape_lines.append(f'Type "{cmd}" Sleep 500ms')
tape_lines.append('Enter')
# Smart sleep based on command complexity
if any(keyword in cmd.lower() for keyword in ['install', 'build', 'test', 'deploy']):
sleep_time = '3s'
elif any(keyword in cmd.lower() for keyword in ['ls', 'pwd', 'echo', 'cat']):
sleep_time = '1s'
else:
sleep_time = '2s'
tape_lines.append(f'Sleep {sleep_time}')
# Add spacing between commands
if i < len(commands):
tape_lines.append('')
return '\n'.join(tape_lines)
def main():
parser = argparse.ArgumentParser(
description='Auto-generate CLI demos from commands',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''
Examples:
# Generate demo from single command
%(prog)s -c "npm install" -o demo.gif
# Generate demo with multiple commands
%(prog)s -c "git clone repo" -c "cd repo" -c "npm install" -o setup.gif
# Custom theme and size
%(prog)s -c "ls -la" -o demo.gif --theme Monokai --width 1200
# With title
%(prog)s -c "echo Hello" -o demo.gif --title "My Demo"
'''
)
parser.add_argument('-c', '--command', action='append', required=True,
help='Command to include in demo (can be specified multiple times)')
parser.add_argument('-o', '--output', required=True,
help='Output GIF file path')
parser.add_argument('--title', help='Demo title (optional)')
parser.add_argument('--theme', default='Dracula',
help='VHS theme (default: Dracula)')
parser.add_argument('--font-size', type=int, default=16,
help='Font size (default: 16)')
parser.add_argument('--width', type=int, default=1400,
help='Terminal width (default: 1400)')
parser.add_argument('--height', type=int, default=700,
help='Terminal height (default: 700)')
parser.add_argument('--no-execute', action='store_true',
help='Generate tape file only, do not execute VHS')
args = parser.parse_args()
# Generate tape file content
tape_content = create_tape_file(
commands=args.command,
output_gif=args.output,
title=args.title,
theme=args.theme,
font_size=args.font_size,
width=args.width,
height=args.height,
)
# Write tape file
output_path = Path(args.output)
tape_file = output_path.with_suffix('.tape')
with open(tape_file, 'w') as f:
f.write(tape_content)
print(f"✓ Generated tape file: {tape_file}")
if not args.no_execute:
# Check if VHS is installed
try:
subprocess.run(['vhs', '--version'], capture_output=True, check=True)
except (subprocess.CalledProcessError, FileNotFoundError):
print("✗ VHS is not installed!", file=sys.stderr)
print("Install it with: brew install vhs", file=sys.stderr)
print(f"✓ You can manually run: vhs < {tape_file}", file=sys.stderr)
return 1
# Execute VHS
print(f"Generating GIF: {args.output}")
try:
subprocess.run(['vhs', str(tape_file)], check=True)
print(f"✓ Demo generated: {args.output}")
print(f" Size: {output_path.stat().st_size / 1024:.1f} KB")
except subprocess.CalledProcessError as e:
print(f"✗ VHS execution failed: {e}", file=sys.stderr)
return 1
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
Batch generate multiple CLI demos from a configuration file.
Supports YAML and JSON formats for defining multiple demos.
"""
import argparse
import json
import subprocess
import sys
from pathlib import Path
from typing import Dict, List
try:
import yaml
YAML_AVAILABLE = True
except ImportError:
YAML_AVAILABLE = False
def load_config(config_file: Path) -> Dict:
"""Load demo configuration from YAML or JSON file."""
suffix = config_file.suffix.lower()
with open(config_file) as f:
if suffix in ['.yaml', '.yml']:
if not YAML_AVAILABLE:
print("Error: PyYAML not installed. Install with: pip install pyyaml", file=sys.stderr)
sys.exit(1)
return yaml.safe_load(f)
elif suffix == '.json':
return json.load(f)
else:
print(f"Error: Unsupported config format: {suffix}", file=sys.stderr)
print("Supported formats: .yaml, .yml, .json", file=sys.stderr)
sys.exit(1)
def generate_demo(demo_config: Dict, base_path: Path, script_path: Path) -> bool:
"""Generate a single demo from configuration."""
name = demo_config.get('name', 'unnamed')
output = demo_config.get('output')
commands = demo_config.get('commands', [])
if not output or not commands:
print(f"✗ Skipping '{name}': missing output or commands", file=sys.stderr)
return False
# Build command
cmd = [sys.executable, str(script_path)]
for command in commands:
cmd.extend(['-c', command])
cmd.extend(['-o', str(base_path / output)])
# Optional parameters
if 'title' in demo_config:
cmd.extend(['--title', demo_config['title']])
if 'theme' in demo_config:
cmd.extend(['--theme', demo_config['theme']])
if 'width' in demo_config:
cmd.extend(['--width', str(demo_config['width'])])
if 'height' in demo_config:
cmd.extend(['--height', str(demo_config['height'])])
print(f"\n{'='*60}")
print(f"Generating: {name}")
print(f"Output: {output}")
print(f"Commands: {len(commands)}")
print(f"{'='*60}")
try:
subprocess.run(cmd, check=True)
return True
except subprocess.CalledProcessError as e:
print(f"✗ Failed to generate '{name}': {e}", file=sys.stderr)
return False
def main():
parser = argparse.ArgumentParser(
description='Batch generate CLI demos from configuration file',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''
Configuration file format (YAML):
demos:
- name: "Install Demo"
output: "install.gif"
title: "Installation"
theme: "Dracula"
commands:
- "npm install my-package"
- "npm run build"
- name: "Usage Demo"
output: "usage.gif"
commands:
- "my-package --help"
- "my-package run"
Configuration file format (JSON):
{
"demos": [
{
"name": "Install Demo",
"output": "install.gif",
"commands": ["npm install"]
}
]
}
'''
)
parser.add_argument('config', type=Path,
help='Configuration file (.yaml, .yml, or .json)')
parser.add_argument('--output-dir', type=Path, default=Path.cwd(),
help='Output directory for generated demos')
args = parser.parse_args()
if not args.config.exists():
print(f"Error: Config file not found: {args.config}", file=sys.stderr)
return 1
# Load configuration
config = load_config(args.config)
demos = config.get('demos', [])
if not demos:
print("Error: No demos defined in configuration", file=sys.stderr)
return 1
# Create output directory
args.output_dir.mkdir(parents=True, exist_ok=True)
# Find auto_generate_demo.py script
script_path = Path(__file__).parent / 'auto_generate_demo.py'
if not script_path.exists():
print(f"Error: auto_generate_demo.py not found at {script_path}", file=sys.stderr)
return 1
# Generate demos
total = len(demos)
successful = 0
failed = 0
print(f"\n{'='*60}")
print(f"Starting batch generation: {total} demos")
print(f"Output directory: {args.output_dir}")
print(f"{'='*60}\n")
for i, demo in enumerate(demos, 1):
print(f"\n[{i}/{total}] Processing: {demo.get('name', 'unnamed')}")
if generate_demo(demo, args.output_dir, script_path):
successful += 1
else:
failed += 1
# Summary
print(f"\n{'='*60}")
print(f"Batch generation complete!")
print(f"{'='*60}")
print(f"✓ Successful: {successful}")
if failed > 0:
print(f"✗ Failed: {failed}")
print(f"Total: {total}")
print(f"{'='*60}\n")
return 0 if failed == 0 else 1
if __name__ == '__main__':
sys.exit(main())

View File

@@ -0,0 +1,136 @@
#!/bin/bash
#
# Record interactive CLI demos using asciinema and convert to GIF
#
# Usage:
# record_interactive.sh output.gif
# record_interactive.sh output.gif --theme Dracula --width 1200
#
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Default values
OUTPUT=""
THEME="Dracula"
WIDTH=1400
HEIGHT=700
FONT_SIZE=16
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--theme)
THEME="$2"
shift 2
;;
--width)
WIDTH="$2"
shift 2
;;
--height)
HEIGHT="$2"
shift 2
;;
--font-size)
FONT_SIZE="$2"
shift 2
;;
*)
OUTPUT="$1"
shift
;;
esac
done
if [ -z "$OUTPUT" ]; then
echo -e "${RED}Error: Output file required${NC}" >&2
echo "Usage: $0 output.gif [--theme Theme] [--width 1200] [--height 700]"
exit 1
fi
# Check dependencies
if ! command -v asciinema &> /dev/null; then
echo -e "${RED}Error: asciinema not installed${NC}" >&2
echo "Install it with:"
echo " macOS: brew install asciinema"
echo " Linux: sudo apt install asciinema"
exit 1
fi
if ! command -v vhs &> /dev/null; then
echo -e "${RED}Error: VHS not installed${NC}" >&2
echo "Install it with: brew install vhs"
exit 1
fi
# Generate temp files
CAST_FILE="${OUTPUT%.gif}.cast"
TAPE_FILE="${OUTPUT%.gif}.tape"
echo -e "${GREEN}===========================================================${NC}"
echo -e "${GREEN}Interactive Demo Recording${NC}"
echo -e "${GREEN}===========================================================${NC}"
echo ""
echo -e "${YELLOW}Instructions:${NC}"
echo "1. Type your commands naturally"
echo "2. Press ENTER after each command"
echo "3. Press Ctrl+D when finished"
echo ""
echo -e "${YELLOW}Output:${NC} $OUTPUT"
echo -e "${YELLOW}Theme:${NC} $THEME"
echo -e "${YELLOW}Size:${NC} ${WIDTH}x${HEIGHT}"
echo ""
echo -e "${GREEN}Starting recording in 3 seconds...${NC}"
sleep 3
echo ""
# Record with asciinema
asciinema rec "$CAST_FILE"
echo ""
echo -e "${GREEN}✓ Recording saved to: $CAST_FILE${NC}"
echo ""
echo -e "${YELLOW}Converting to GIF...${NC}"
# Convert asciinema cast to VHS tape format
cat > "$TAPE_FILE" << EOF
Output $OUTPUT
Set FontSize $FONT_SIZE
Set Width $WIDTH
Set Height $HEIGHT
Set Theme "$THEME"
Set Padding 20
Play $CAST_FILE
EOF
echo -e "${GREEN}✓ Generated tape file: $TAPE_FILE${NC}"
# Generate GIF with VHS
vhs < "$TAPE_FILE"
if [ -f "$OUTPUT" ]; then
FILE_SIZE=$(du -h "$OUTPUT" | cut -f1)
echo ""
echo -e "${GREEN}===========================================================${NC}"
echo -e "${GREEN}✓ Demo generated successfully!${NC}"
echo -e "${GREEN}===========================================================${NC}"
echo -e "${YELLOW}Output:${NC} $OUTPUT"
echo -e "${YELLOW}Size:${NC} $FILE_SIZE"
echo ""
echo "Generated files:"
echo " - $CAST_FILE (asciinema recording)"
echo " - $TAPE_FILE (VHS tape file)"
echo " - $OUTPUT (GIF demo)"
echo ""
else
echo -e "${RED}✗ Failed to generate GIF${NC}" >&2
exit 1
fi