bootstrap について
Claude Code の外で asciinema の録画セッションを開始するブートストラップスクリプトを生成するスキルです。環境と GitHub リポジトリを確認し、チャンク処理は launchd デーモンに任せます。
主な機能
- 01asciinema、zstd、git の確認
- 02Git リポジトリとブランチ状態の検出
- 03録画用リポジトリと orphan ブランチの選択・作成
- 04ブートストラップスクリプトの生成
- 05起動手順とトラブルシューティングの提示
活用シーン
- 01Claude Code セッションの端末録画設定
- 02指定した GitHub リポジトリへの録画保存
- 03録画に必要なデーモンとツールの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill bootstrapインストール後、Claude Code で/bootstrapを入力して読み込まれたか確認します。
同梱ファイルreferences/evolution-log.md
詳細
/asciinema-tools:bootstrap
Claude Code の外部で実行し、録画セッションを開始するブートストラップスクリプトを生成します。
重要:チャンク分割は launchd デーモンが処理します。まだ設定していない場合は、先に /asciinema-tools:daemon-setup を実行してください。
自己進化型スキル:このスキルは使用するたびに改善されます。指示に誤りがある場合、パラメーターにずれがある場合、または回避策が必要だった場合は、先送りせず、すぐにこのファイルを修正してください。実際に再現できる問題がある場合にのみ更新してください。
アーキテクチャ
┌─────────────────────────────────────────────────────────────────────────────┐
│ DAEMON-BASED RECORDING WORKFLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. ONE-TIME SETUP (if not done): │
│ /asciinema-tools:daemon-setup │
│ → Configures launchd daemon with Keychain credentials │
│ │
│ 2. GENERATE BOOTSTRAP (in Claude Code): │
│ /asciinema-tools:bootstrap │
│ → Generates tmp/bootstrap-claude-session.sh │
│ │
│ 3. EXIT CLAUDE and RUN BOOTSTRAP: │
│ $ ./tmp/bootstrap-claude-session.sh ← NOT source! │
│ → Writes config for daemon │
│ → Starts asciinema recording │
│ │
│ 4. WORK IN RECORDING: │
│ $ claude │
│ → Daemon automatically pushes chunks to GitHub │
│ │
│ 5. EXIT (two times): │
│ Ctrl+D (exit Claude) → exit (end recording) │
│ → Daemon pushes final chunk │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
引数
| 引数 | 説明 |
|---|---|
-r, --repo | GitHub リポジトリ(例:owner/repo) |
-b, --branch | 孤立ブランチ名(デフォルト:asciinema-recordings) |
--setup-orphan | 孤立ブランチを強制的に作成 |
-y, --yes | 確認プロンプトをスキップ |
実行
フェーズ 0:事前チェック
/usr/bin/env bash << 'PREFLIGHT_EOF'
MISSING=()
for tool in asciinema zstd git; do
command -v "$tool" &>/dev/null || MISSING+=("$tool")
done
if [[ ${#MISSING[@]} -gt 0 ]]; then
echo "MISSING: ${MISSING[*]}"
exit 1
fi
echo "PREFLIGHT: OK"
asciinema --version | head -1
# Check daemon status
if launchctl list 2>/dev/null | grep -q "asciinema-chunker"; then
echo "DAEMON: RUNNING"
else
echo "DAEMON: NOT_RUNNING"
fi
PREFLIGHT_EOF
DAEMON: NOT_RUNNING の場合は、AskUserQuestion を使用してください:
Question: "The chunker daemon is not running. Chunks won't be pushed to GitHub without it."
Header: "Daemon"
Options:
- label: "Run daemon setup (Recommended)"
description: "Switch to /asciinema-tools:daemon-setup to configure the daemon"
- label: "Continue anyway"
description: "Generate bootstrap script without daemon (local recording only)"
フェーズ 1:リポジトリのコンテキストを検出
必須:オプションを自動入力するため、AskUserQuestion の前に実行してください。
/usr/bin/env bash << 'DETECT_CONTEXT_EOF'
IN_GIT_REPO="false"
CURRENT_REPO_URL=""
CURRENT_REPO_OWNER=""
CURRENT_REPO_NAME=""
ORPHAN_BRANCH_EXISTS="false"
LOCAL_CLONE_EXISTS="false"
ORPHAN_BRANCH="asciinema-recordings"
if git rev-parse --git-dir &>/dev/null 2>&1; then
IN_GIT_REPO="true"
if git remote get-url origin &>/dev/null 2>&1; then
CURRENT_REPO_URL=$(git remote get-url origin)
elif [[ -n "$(git remote)" ]]; then
REMOTE=$(git remote | head -1)
CURRENT_REPO_URL=$(git remote get-url "$REMOTE")
fi
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
if git ls-remote --heads "$CURRENT_REPO_URL" "$ORPHAN_BRANCH" 2>/dev/null | grep -q "$ORPHAN_BRANCH"; then
ORPHAN_BRANCH_EXISTS="true"
fi
LOCAL_CLONE_PATH="$HOME/asciinema_recordings/$CURRENT_REPO_NAME"
if [[ -d "$LOCAL_CLONE_PATH/.git" ]]; then
LOCAL_CLONE_EXISTS="true"
fi
fi
fi
echo "IN_GIT_REPO=$IN_GIT_REPO"
echo "CURRENT_REPO_URL=$CURRENT_REPO_URL"
echo "CURRENT_REPO_OWNER=$CURRENT_REPO_OWNER"
echo "CURRENT_REPO_NAME=$CURRENT_REPO_NAME"
echo "ORPHAN_BRANCH_EXISTS=$ORPHAN_BRANCH_EXISTS"
echo "LOCAL_CLONE_EXISTS=$LOCAL_CLONE_EXISTS"
DETECT_CONTEXT_EOF
フェーズ 2:リポジトリの選択(AskUserQuestion を必ず使用)
検出結果に基づきます:
IN_GIT_REPO=true、ORPHAN_BRANCH_EXISTS=true の場合:
Question: "Orphan branch found in {repo}. Use it?"
Header: "Destination"
Options:
- label: "Use existing (Recommended)"
description: "Branch 'asciinema-recordings' already configured in {repo}"
- label: "Use different repository"
description: "Store recordings in a different repo"
IN_GIT_REPO=true、ORPHAN_BRANCH_EXISTS=false の場合:
Question: "No orphan branch in {repo}. Create one?"
Header: "Setup"
Options:
- label: "Create orphan branch (Recommended)"
description: "Initialize with GitHub Actions workflow for brotli"
- label: "Use different repository"
description: "Store recordings elsewhere"
IN_GIT_REPO=false の場合:
Question: "Not in a git repo. Where to store recordings?"
Header: "Destination"
Options:
- label: "Dedicated recordings repo"
description: "Use {owner}/asciinema-recordings"
- label: "Enter repository"
description: "Specify owner/repo manually"
フェーズ 3:孤立ブランチの作成(必要な場合)
最初に SSH キャッシュをクリアしてから、孤立ブランチを作成します:
/usr/bin/env bash << 'CREATE_ORPHAN_EOF'
REPO_URL="${1:?}"
BRANCH="${2:-asciinema-recordings}"
LOCAL_PATH="$HOME/asciinema_recordings/$(basename "$REPO_URL" .git)"
# Clear SSH caches first
rm -f ~/.ssh/control-* 2>/dev/null || true
ssh -O exit [email protected] 2>/dev/null || true
# Get GitHub token for HTTPS clone (prefer env var to avoid process spawning)
GH_TOKEN="${GH_TOKEN:-${GITHUB_TOKEN:-$(gh auth token 2>/dev/null || echo "")}}"
if [[ -n "$GH_TOKEN" ]]; then
# Parse owner/repo
if [[ "$REPO_URL" =~ github\.com[:/]([^/]+)/([^/.]+) ]]; then
OWNER_REPO="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}"
AUTH_URL="https://${GH_TOKEN}@github.com/${OWNER_REPO}.git"
CLEAN_URL="https://github.com/${OWNER_REPO}.git"
else
AUTH_URL="$REPO_URL"
CLEAN_URL="$REPO_URL"
fi
else
AUTH_URL="$REPO_URL"
CLEAN_URL="$REPO_URL"
fi
# Clone and create orphan
TEMP_DIR=$(mktemp -d)
git clone "$AUTH_URL" "$TEMP_DIR/repo"
cd "$TEMP_DIR/repo"
# Create orphan branch
git checkout --orphan "$BRANCH"
git reset --hard
git commit --allow-empty -m "Initialize asciinema recordings"
git push origin "$BRANCH"
# Cleanup temp
rm -rf "$TEMP_DIR"
# Clone orphan branch locally
mkdir -p "$(dirname "$LOCAL_PATH")"
git clone --single-branch --branch "$BRANCH" --depth 1 "$AUTH_URL" "$LOCAL_PATH"
# Strip token from remote
git -C "$LOCAL_PATH" remote set-url origin "$CLEAN_URL"
mkdir -p "$LOCAL_PATH/chunks"
echo "ORPHAN_CREATED: $LOCAL_PATH"
CREATE_ORPHAN_EOF
フェーズ 4:ブートストラップスクリプトの生成
簡略化したブートストラップスクリプトを生成します(チャンク分割はデーモンが処理します):
/usr/bin/env bash << 'GENERATE_SCRIPT_EOF'
REPO_URL="${1:?}"
BRANCH="${2:-asciinema-recordings}"
LOCAL_REPO="${3:-$HOME/asciinema_recordings/$(basename "$REPO_URL" .git)}"
OUTPUT_FILE="${4:-$PWD/tmp/bootstrap-claude-session.sh}"
mkdir -p "$(dirname "$OUTPUT_FILE")"
cat > "$OUTPUT_FILE" << 'SCRIPT_EOF'
#!/usr/bin/env bash
# bootstrap-claude-session.sh - Start asciinema recording session
# Generated by /asciinema-tools:bootstrap
# Chunking handled by launchd daemon
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
echo "ERROR: Do not source this script. Run directly: ./${BASH_SOURCE[0]##*/}"
return 1
fi
set -uo pipefail
SCRIPT_EOF
# Append configuration
cat >> "$OUTPUT_FILE" << SCRIPT_CONFIG
REPO_URL="$REPO_URL"
BRANCH="$BRANCH"
LOCAL_REPO="$LOCAL_REPO"
SCRIPT_CONFIG
cat >> "$OUTPUT_FILE" << 'SCRIPT_BODY'
WORKSPACE="$(basename "$PWD")"
DATETIME="$(date +%Y-%m-%d_%H-%M)"
ASCIINEMA_DIR="$HOME/.asciinema"
ACTIVE_DIR="$ASCIINEMA_DIR/active"
CAST_FILE="$ACTIVE_DIR/${WORKSPACE}_${DATETIME}.cast"
CONFIG_FILE="${CAST_FILE%.cast}.json"
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ asciinema Recording Session ║"
echo "╠════════════════════════════════════════════════════════════════╣"
# Check daemon
if ! launchctl list 2>/dev/null | grep -q "asciinema-chunker"; then
echo "║ WARNING: Daemon not running! Run /asciinema-tools:daemon-start║"
echo "╠════════════════════════════════════════════════════════════════╣"
fi
# Clear SSH caches
rm -f ~/.ssh/control-* 2>/dev/null || true
ssh -O exit [email protected] 2>/dev/null || true
# Setup
mkdir -p "$ACTIVE_DIR" "$LOCAL_REPO/chunks"
# Write config for daemon
cat > "$CONFIG_FILE" <<EOF
{
"repo_url": "$REPO_URL",
"branch": "$BRANCH",
"local_repo": "$LOCAL_REPO",
"workspace": "$WORKSPACE",
"started": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
cleanup() {
echo ""
echo "Recording ended. Daemon will push final chunk."
echo "Check status: /asciinema-tools:daemon-status"
}
trap cleanup EXIT
echo "║ Recording to: $CAST_FILE"
echo "║ Run 'claude' inside this session. Exit twice to end. ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
asciinema rec --stdin "$CAST_FILE"
SCRIPT_BODY
chmod +x "$OUTPUT_FILE"
echo "SCRIPT_GENERATED: $OUTPUT_FILE"
GENERATE_SCRIPT_EOF
フェーズ 5:手順の表示
## Bootstrap Complete
Script generated at: `tmp/bootstrap-claude-session.sh`
### Quick Start
1. Exit Claude Code: `exit` or Ctrl+D
2. Run bootstrap: `./tmp/bootstrap-claude-session.sh` ← NOT source!
3. Inside recording, run: `claude`
4. Work normally - daemon pushes chunks to GitHub
5. Exit twice: Ctrl+D (Claude) → `exit` (recording)
### What Happens
- asciinema records to `~/.asciinema/active/{workspace}_{datetime}.cast`
- Daemon monitors for idle periods
- On idle, chunk is compressed and pushed via Keychain PAT
- Daemon sends Pushover notification on failures
- Recording is decoupled from Claude Code session
### Daemon Commands
| Command | Description |
| -------------------------------- | ------------------- |
| `/asciinema-tools:daemon-status` | Check daemon health |
| `/asciinema-tools:daemon-logs` | View logs |
| `/asciinema-tools:daemon-start` | Start daemon |
| `/asciinema-tools:daemon-stop` | Stop daemon |
スキップ条件
-rと-bが指定されている場合 -> リポジトリの選択をスキップ-yが指定されている場合 -> すべての確認をスキップ--setup-orphanが指定されている場合 -> 孤立ブランチを強制的に作成
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| asciinema が見つからない | asciinema がインストールされていない | brew install asciinema |
| zstd が見つからない | zstd がインストールされていない | brew install zstd |
| デーモンが起動していない | デーモンが起動していない | /asciinema-tools:daemon-start を実行 |
| Git のクローンに失敗する | 認証の問題または URL の誤り | gh auth login を実行 |
| 孤立ブランチのエラー | ブランチがすでに存在する | --setup-orphan フラグを削除 |
| スクリプトが実行可能でない | 権限の問題 | chmod +x tmp/bootstrap-*.sh を実行 |
| ソースエラー | スクリプトが source された | 直接実行してください:./script.sh |
実行後の振り返り
このスキルの実行後、タスクを終了する前に振り返ってください:
- 自分の場所を確認します。 — 編集する前に、このスキル名で Glob を実行して SKILL.md の正規パスを見つけてください。修正対象は必ずこのファイルとその兄弟ファイルである
references/に限定し、他のドキュメントは変更しないでください。 - 何が失敗しましたか? — 原因となった指示を修正してください。再発する可能性がある場合は、アンチパターンとして追加してください。
- 予想以上にうまくいったことは何ですか? — 推奨プラクティスとして取り入れてください。その理由も記録してください。
- 何にずれがありましたか? — 現状と一致しなくなったスクリプト、参照資料、外部依存関係は、今すぐ修正してください。
- 記録してください。 — 変更のたびに、きっかけ、修正内容、根拠を含む進化ログのエントリーを追加してください。
先送りしないでください。次回の実行では、ここに残した状態が引き継がれます。