Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Complete system for streaming asciinema recordings to GitHub with automatic brotli archival. Uses idle-detection for intelligent chunking, zstd for concatenatable streaming compression, and GitHub Actions for final brotli recompression.
When to Use This Skill
Use this skill when:
Setting up real-time backup of asciinema recordings to GitHub
Configuring idle-detection chunking for recordings
Creating orphan branch infrastructure for recording storage
Integrating GitHub Actions for brotli recompression
Purpose: Verify all tools installed, offer self-correction if missing.
/usr/bin/env bash << 'PREFLIGHT_EOF'
# preflight-check.sh - Validates all requirements
MISSING=()
# Check each tool
for tool in asciinema zstd brotli git gh; do
if ! command -v "$tool" &>/dev/null; then
MISSING+=("$tool")
fi
done
if [[ ${#MISSING[@]} -gt 0 ]]; then
echo "Missing tools: ${MISSING[*]}"
echo ""
echo "Install with:"
echo " brew install ${MISSING[*]}"
exit 1
fi
# Check asciinema version (need 3.0+ for Rust version)
ASCIINEMA_VERSION=$(asciinema --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1)
if [[ "${ASCIINEMA_VERSION%%.*}" -lt 3 ]]; then
echo "Warning: asciinema $ASCIINEMA_VERSION detected. Version 3.0+ recommended."
echo "Upgrade: brew upgrade asciinema"
fi
echo "All requirements satisfied"
PREFLIGHT_EOF
AskUserQuestion (if tools missing):
AskUserQuestion:
question: "Required tools are missing. How would you like to proceed?"
header: "Preflight Check"
options:
- label: "Install all missing tools (Recommended)"
description: "Run: brew install ${MISSING[*]}"
- label: "Show manual installation commands"
description: "Display commands without executing"
- label: "Continue anyway (may fail later)"
description: "Skip installation and proceed"
Self-Correction: If tools are missing, generate installation command and offer to run it.
Phase 1: GitHub Account Detection
Purpose: Detect available GitHub accounts and let user choose which to use for recording storage.
Detection Sources
Probe these 5 sources to detect GitHub accounts:
Source
Command
What it finds
SSH config
grep -A5 "Host github" ~/.ssh/config
Match directives with IdentityFile
SSH keys
ls ~/.ssh/id_ed25519_*
Account-named keys (e.g., id_ed25519_terrylica)
gh CLI
gh auth status
Authenticated accounts
mise env
grep GH_ACCOUNT .mise.toml
GH_ACCOUNT variable
git config
git config user.name
Global git username
Detection Script
/usr/bin/env bash << 'DETECT_ACCOUNTS_EOF'
# detect-github-accounts.sh - Probe all sources for GitHub accounts
# Uses portable parallel arrays (works in bash 3.2+ and when wrapped for zsh)
ACCOUNT_NAMES=()
ACCOUNT_SOURCES=()
log() { echo "[detect] $*"; }
# Helper: add account with source (updates existing or appends new)
add_account() {
local account="$1" source="$2"
local idx
for idx in "${!ACCOUNT_NAMES[@]}"; do
if [[ "${ACCOUNT_NAMES[$idx]}" == "$account" ]]; then
ACCOUNT_SOURCES[$idx]+="$source "
return
fi
done
ACCOUNT_NAMES+=("$account")
ACCOUNT_SOURCES+=("$source ")
}
# 1. SSH config Match directives
if [[ -f ~/.ssh/config ]]; then
while IFS= read -r line; do
if [[ "$line" =~ IdentityFile.*id_ed25519_([a-zA-Z0-9_-]+) ]]; then
add_account "${BASH_REMATCH[1]}" "ssh-config"
fi
done < ~/.ssh/config
fi
# 2. SSH key filenames
for keyfile in ~/.ssh/id_ed25519_*; do
if [[ -f "$keyfile" && "$keyfile" != *.pub ]]; then
account=$(basename "$keyfile" | sed 's/id_ed25519_//')
add_account "$account" "ssh-key"
fi
done
# 3. gh CLI authenticated accounts
if command -v gh &>/dev/null; then
while IFS= read -r account; do
[[ -n "$account" ]] && add_account "$account" "gh-cli"
done < <(gh auth status 2>&1 | grep -oE 'Logged in to github.com account [a-zA-Z0-9_-]+' | awk '{print $NF}')
fi
# 4. mise env GH_ACCOUNT
if [[ -f .mise.toml ]]; then
account=$(grep -E 'GH_ACCOUNT\s*=' .mise.toml 2>/dev/null | sed 's/.*=\s*"\([^"]*\)".*/\1/')
[[ -n "$account" ]] && add_account "$account" "mise-env"
fi
# 5. git config user.name
git_user=$(git config user.name 2>/dev/null)
[[ -n "$git_user" ]] && add_account "$git_user" "git-config"
# Score and display
log "=== Detected GitHub Accounts ==="
RECOMMENDED=""
MAX_SOURCES=0
for idx in "${!ACCOUNT_NAMES[@]}"; do
account="${ACCOUNT_NAMES[$idx]}"
sources="${ACCOUNT_SOURCES[$idx]}"
count=$(echo "$sources" | wc -w | tr -d ' ')
log "$account: $count sources ($sources)"
if (( count > MAX_SOURCES )); then
MAX_SOURCES=$count
RECOMMENDED="$account"
RECOMMENDED_SOURCES="$sources"
fi
done
echo ""
echo "RECOMMENDED=$RECOMMENDED"
echo "SOURCES=$RECOMMENDED_SOURCES"
DETECT_ACCOUNTS_EOF
AskUserQuestion
AskUserQuestion:
question: "Which GitHub account should be used for recording storage?"
header: "GitHub Account Selection"
options:
- label: "${RECOMMENDED} (Recommended)"
description: "Detected via: ${SOURCES}"
# Additional detected accounts appear here dynamically
- label: "Enter manually"
description: "Type a GitHub username not listed above"
Post-Selection: If user selects an account, ensure gh CLI is using that account:
/usr/bin/env bash << 'POST_SELECT_EOF'
# Ensure gh CLI is authenticated as selected account
SELECTED_ACCOUNT="${1:?Usage: provide selected account}"
if ! gh auth status 2>&1 | grep -q "Logged in to github.com account $SELECTED_ACCOUNT"; then
echo "Switching gh CLI to account: $SELECTED_ACCOUNT"
gh auth switch --user "$SELECTED_ACCOUNT" 2>/dev/null || \
echo "Warning: Could not switch accounts. Manual auth may be needed."
fi
POST_SELECT_EOF
Phase 1.5: Current Repository Detection
Purpose: Detect current git repository context to provide intelligent defaults for Phase 2 questions.
Detection Script
/usr/bin/env bash << 'DETECT_REPO_EOF'
# Detect current repository context for intelligent defaults
CURRENT_REPO_URL=""
CURRENT_REPO_OWNER=""
CURRENT_REPO_NAME=""
DETECTED_FROM=""
# Check if we're in a git repository
if git rev-parse --git-dir &>/dev/null; then
# Try origin remote first
if git remote get-url origin &>/dev/null; then
CURRENT_REPO_URL=$(git remote get-url origin)
DETECTED_FROM="origin remote"
# Fallback to first available remote
elif [[ -n "$(git remote)" ]]; then
REMOTE=$(git remote | head -1)
CURRENT_REPO_URL=$(git remote get-url "$REMOTE")
DETECTED_FROM="$REMOTE remote"
fi
# Parse owner and name from URL (SSH or HTTPS)
if [[ -n "$CURRENT_REPO_URL" ]]; then
if [[ "$CURRENT_REPO_URL" =~ github\.com[:/]([^/]+)/([^/.]+) ]]; then
CURRENT_REPO_OWNER="${BASH_REMATCH[1]}"
CURRENT_REPO_NAME="${BASH_REMATCH[2]%.git}"
fi
fi
fi
# Output for Claude to parse
echo "CURRENT_REPO_URL=$CURRENT_REPO_URL"
echo "CURRENT_REPO_OWNER=$CURRENT_REPO_OWNER"
echo "CURRENT_REPO_NAME=$CURRENT_REPO_NAME"
echo "DETECTED_FROM=$DETECTED_FROM"
DETECT_REPO_EOF
Claude Action: Store detected values (CURRENT_REPO_OWNER, CURRENT_REPO_NAME, DETECTED_FROM) for use in subsequent AskUserQuestion calls. If no repo detected, proceed without defaults.
Phase 2: Core Configuration
Purpose: Gather essential configuration from user.
2.1 Repository URL
If current repo detected (from Phase 1.5):
AskUserQuestion:
question: "Which repository should store the recordings?"
header: "Repository"
options:
- label: "${CURRENT_REPO_OWNER}/${CURRENT_REPO_NAME} (Recommended)"
description: "Current repo detected from ${DETECTED_FROM}"
- label: "Create dedicated repo: ${GITHUB_ACCOUNT}/asciinema-recordings"
description: "Separate repository for all recordings"
- label: "Enter different repository"
description: "Specify another repository (user/repo format)"
If no current repo detected:
AskUserQuestion:
question: "Enter the GitHub repository URL for storing recordings:"
header: "Repository URL"
options:
- label: "Create dedicated repo: ${GITHUB_ACCOUNT}/asciinema-recordings"
description: "Separate repository for all recordings (Recommended)"
- label: "Enter repository manually"
description: "SSH (git@github.com:user/repo.git), HTTPS, or shorthand (user/repo)"
URL Normalization (handles multiple formats):
/usr/bin/env bash << 'NORMALIZE_URL_EOF'
# Normalize to SSH format for consistent handling
normalize_repo_url() {
local url="$1"
# Shorthand: user/repo -> git@github.com:user/repo.git
if [[ "$url" =~ ^[a-zA-Z0-9_-]+/[a-zA-Z0-9_.-]+$ ]]; then
echo "git@github.com:${url}.git"
# HTTPS: https://github.com/user/repo -> git@github.com:user/repo.git
elif [[ "$url" =~ ^https://github\.com/([^/]+)/([^/]+)/?$ ]]; then
echo "git@github.com:${BASH_REMATCH[1]}/${BASH_REMATCH[2]%.git}.git"
# Already SSH format
else
echo "$url"
fi
}
URL="${1:?Usage: provide URL to normalize}"
normalize_repo_url "$URL"
NORMALIZE_URL_EOF
Confirmation for free-form input (if user selected "Enter different/manually"):
AskUserQuestion:
question: "You entered '${USER_INPUT}'. Normalized to: ${NORMALIZED_URL}. Is this correct?"
header: "Confirm Repository"
options:
- label: "Yes, use ${NORMALIZED_URL}"
description: "Proceed with this repository"
- label: "No, let me re-enter"
description: "Go back to repository selection"
2.2 Recording Directory
AskUserQuestion:
question: "Where should recordings be stored locally?"
header: "Recording Directory"
options:
- label: "~/asciinema_recordings/${RESOLVED_REPO_NAME} (Recommended)"
description: "Example: ~/asciinema_recordings/alpha-forge"
- label: "Custom path"
description: "Enter a different directory path"
Note: ${RESOLVED_REPO_NAME} is the actual repo name from Phase 1.5 or Phase 2.1, not a variable placeholder. Display the concrete path to user.
2.3 Branch Name
AskUserQuestion:
question: "What should the orphan branch be named?"
header: "Branch Name"
options:
- label: "asciinema-recordings (Recommended)"
description: "Matches ~/asciinema_recordings/ parent directory pattern"
- label: "gh-recordings"
description: "GitHub-prefixed alternative (gh = GitHub storage)"
- label: "recordings"
description: "Minimal name"
- label: "Custom"
description: "Enter a custom branch name"
Naming Convention: The default asciinema-recordings matches the parent directory ~/asciinema_recordings/ for consistency.
Phase 3: Advanced Configuration
Purpose: Allow customization of compression and behavior parameters.
Configuration Parameters
Parameter
Default
Options
Idle threshold
30s
15s, 30s (Recommended), 60s, Custom (5-300)
zstd level
3
1 (fast), 3 (Recommended), 6, Custom (1-22)
Brotli level
9
6, 9 (Recommended), 11, Custom (1-11)
Auto-push
Yes
Yes (Recommended), No
Poll interval
5s
2s, 5s (Recommended), 10s
AskUserQuestion Sequence
3.1 Idle Threshold:
AskUserQuestion:
question: "How long should the chunker wait before creating a chunk?"
header: "Idle Threshold"
options:
- label: "15 seconds"
description: "More frequent chunks, smaller files"
- label: "30 seconds (Recommended)"
description: "Balanced chunk size and frequency"
- label: "60 seconds"
description: "Larger chunks, less frequent uploads"
- label: "Custom (5-300 seconds)"
description: "Enter a custom threshold"
AskUserQuestion:
question: "Ready to test recording? This requires you to start asciinema in another terminal."
header: "Recording Test"
options:
- label: "Guide me through it (Recommended)"
description: "Step-by-step instructions"
- label: "Skip this test"
description: "I'll verify manually later"
- label: "I've already verified recording works"
description: "Mark as passed"
If "Guide me through it" selected, display:
╔════════════════════════════════════════════════════════════════╗
║ USER ACTION REQUIRED: Recording Test ║
╠════════════════════════════════════════════════════════════════╣
║ ║
║ In a NEW terminal, run: ║
║ ┌────────────────────────────────────────────────────────┐ ║
║ │ asciinema rec ~/asciinema_recordings/test_session.cast │ ║
║ └────────────────────────────────────────────────────────┘ ║
║ ║
║ Then type a few commands and exit with Ctrl+D ║
║ ║
║ Come back here when done. ║
╚════════════════════════════════════════════════════════════════╝
Then Claude autonomously validates the created file:
# Claude runs after user confirms:
[RUN] Checking test_session.cast exists... ✓
[RUN] Validating JSON header... ✓ {"version": 2, ...}
[RUN] Checking line count... ✓ 23 events recorded
Test 10: Chunker Live Test
AskUserQuestion:
question: "Ready to test live chunking? This requires running recording + chunker simultaneously."
header: "Chunker Test"
options:
- label: "Guide me (Recommended)"
description: "Two-terminal workflow instructions"
- label: "Skip - I trust the setup"
description: "Skip live test"
Cause: zstd chunks not concatenating properly (overlapping data).
Fix: Ensure idle-chunker uses last_chunk_pos to avoid overlap:
/usr/bin/env bash << 'PREFLIGHT_EOF_2'
# Check for overlaps - each chunk should be sequential
for f in chunks/*.zst; do
zstd -d "$f" -c | head -1
done
PREFLIGHT_EOF_2
Key Design Decisions
Decision
Rationale
zstd for streaming
Supports frame concatenation (brotli doesn't)
brotli for archival
Best compression ratio (~300x for .cast files)
Orphan branch
Complete isolation, can't pollute main history
Idle-based chunking
Semantic breakpoints, not mid-output splits
Shallow clone
Minimal disk usage, can't accidentally access main
30s idle threshold
Balances chunk frequency vs semantic completeness
Post-Change Checklist
After modifying this skill:
Orphan branch creation scripts use heredoc wrapper
All bash blocks compatible with zsh (no declare -A, no grep -P)