finalize について
finalizeは、未処理のasciinema録画を処理するスキルです。録画や実行中のプロセスを検出して停止し、ファイルを検証・zstd圧縮したうえで、orphanブランチへプッシュできます。
主な機能
- 01実行中プロセスと未処理録画の検出
- 02録画プロセスの通常停止または強制停止
- 03録画ファイルの整合性確認
- 04zstdによる.castファイルの圧縮
- 05任意でプッシュしローカル原本を削除
活用シーン
- 01中断後に残った録画の処理
- 02選択した録画の圧縮と保管
- 03完了した録画のorphanブランチへのプッシュ
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill finalizeインストール後、Claude Code で/finalizeを入力して読み込まれたか確認します。
同梱ファイルreferences/evolution-log.md
詳細
/asciinema-tools:finalize
孤立した asciinema 録画を確定します。実行中のプロセスを正常に停止し、圧縮して、孤立ブランチにプッシュします。
自己進化するスキル:このスキルは使用を通じて改善されます。指示が誤っていた場合、パラメーターにずれがあった場合、または回避策が必要だった場合は、先延ばしにせず、このファイルをすぐに修正してください。実際に再現できる問題だけを更新してください。
引数
| Argument | Description |
|---|---|
file | 確定する特定の .cast ファイル |
--all | 未処理の .cast ファイルをすべて確定します |
--force | 正常な停止に失敗した場合は SIGKILL を使用します |
--no-push | 孤立ブランチへのプッシュをスキップします(ローカルのみ) |
--keep-local | 圧縮後もローカルの .cast を保持します |
ワークフロー
- 検出:実行中の asciinema プロセスと未処理の .cast ファイルを探します
- 選択:処理するファイルを AskUserQuestion で確認します
- 停止:実行中のプロセスを正常に停止します(SIGTERM → SIGINT → SIGKILL)
- 検証:停止後にファイルの整合性を確認します
- 圧縮:.cast ファイルを zstd で圧縮します
- プッシュ:孤立ブランチにプッシュします(設定されている場合)
- クリーンアップ:ローカルの .cast を削除します(任意)
実行
フェーズ 1:検出
/usr/bin/env bash << 'DISCOVER_EOF'
echo "=== Running asciinema processes ==="
PROCS=$(ps aux | grep -E "asciinema rec" | grep -v grep)
if [[ -n "$PROCS" ]]; then
echo "$PROCS" | while read -r line; do
PID=$(echo "$line" | awk '{print $2}')
CAST_FILE=$(echo "$line" | grep -oE '[^ ]+\.cast' | head -1)
if [[ -n "$CAST_FILE" ]]; then
SIZE=$(ls -lh "$CAST_FILE" 2>/dev/null | awk '{print $5}' || echo "?")
echo "PID $PID: $CAST_FILE ($SIZE)"
else
echo "PID $PID: (no file detected)"
fi
done
else
echo "No running asciinema processes"
fi
echo ""
echo "=== Unhandled .cast files ==="
find ~/eon -name "*.cast" -size +1M -mtime -30 2>/dev/null | while read -r f; do
SIZE=$(ls -lh "$f" | awk '{print $5}')
echo "$f ($SIZE)"
done
DISCOVER_EOF
フェーズ 2:選択
AskUserQuestion:
question: "Which recordings should be finalized?"
header: "Select"
multiSelect: true
options:
- label: "All running processes"
description: "Stop all asciinema rec processes and finalize their files"
- label: "All unhandled files"
description: "Finalize all .cast files found in ~/eon"
- label: "Specific file"
description: "Enter path to specific .cast file"
フェーズ 3:実行中のプロセスを停止
PID のリストをこのブロックに渡します。ユーザーが
/asciinema-tools:finalize を --force 付きで実行した場合は、--force も渡してください。このブロックは自身の引数から --force を解析します。個別の bash ヒアドキュメントは別々のプロセスとして実行されるため、$FORCE は、それを使用する同じブロック内で解決する必要があります(独立した解析フェーズでは、ブロック間で値を引き継げません)。
/usr/bin/env bash << 'STOP_EOF'
# Arguments: PID list, plus optional --force (documented in argument-hint).
# Split flags from PIDs so the documented --force flag actually takes effect.
FORCE=false
PIDS=""
for arg in "$@"; do
case "$arg" in
--force) FORCE=true ;;
*) PIDS="$PIDS $arg" ;;
esac
done
for PID in $PIDS; do
echo "Stopping PID $PID..."
# Try SIGTERM first (graceful)
kill -TERM "$PID" 2>/dev/null
sleep 2
if kill -0 "$PID" 2>/dev/null; then
echo " SIGTERM ignored, trying SIGINT..."
kill -INT "$PID" 2>/dev/null
sleep 2
fi
if kill -0 "$PID" 2>/dev/null; then
echo " Process still running. Use --force for SIGKILL"
# Only SIGKILL with --force flag
if [[ "$FORCE" == "true" ]]; then
echo " Sending SIGKILL (file may be truncated)..."
kill -9 "$PID" 2>/dev/null
sleep 1
fi
fi
if ! kill -0 "$PID" 2>/dev/null; then
echo " ✓ Process stopped"
else
echo " ✗ Process still running"
fi
done
STOP_EOF
フェーズ 4:ファイルの整合性チェック
/usr/bin/env bash << 'CHECK_EOF'
CAST_FILE="$1"
echo "Checking file integrity: $CAST_FILE"
# Check if file exists
if [[ ! -f "$CAST_FILE" ]]; then
echo " ✗ File not found"
exit 1
fi
# Check file size
SIZE=$(stat -f%z "$CAST_FILE" 2>/dev/null || stat -c%s "$CAST_FILE")
echo " Size: $(numfmt --to=iec-i "$SIZE" 2>/dev/null || echo "$SIZE bytes")"
# Check last line (NDJSON should have complete JSON arrays)
LAST_LINE=$(tail -c 500 "$CAST_FILE" | tail -1)
if [[ "$LAST_LINE" == *"]"* ]]; then
echo " ✓ File appears complete (ends with JSON array)"
else
echo " ⚠ File may be truncated (incomplete JSON)"
echo " Note: asciinema 2.0+ streams to disk, so most data is preserved"
fi
# Test with asciinema cat (quick validation)
if timeout 5 asciinema cat "$CAST_FILE" > /dev/null 2>&1; then
echo " ✓ File is playable"
else
echo " ⚠ File may have issues (but often still usable)"
fi
CHECK_EOF
フェーズ 5:圧縮
/usr/bin/env bash << 'COMPRESS_EOF'
CAST_FILE="$1"
ZSTD_LEVEL="${2:-6}"
echo "Compressing: $CAST_FILE"
OUTPUT="${CAST_FILE}.zst"
if zstd -"$ZSTD_LEVEL" -f "$CAST_FILE" -o "$OUTPUT"; then
ORIG_SIZE=$(stat -f%z "$CAST_FILE" 2>/dev/null || stat -c%s "$CAST_FILE")
COMP_SIZE=$(stat -f%z "$OUTPUT" 2>/dev/null || stat -c%s "$OUTPUT")
RATIO=$(echo "scale=1; $ORIG_SIZE / $COMP_SIZE" | bc 2>/dev/null || echo "?")
echo " ✓ Compressed: $(basename "$OUTPUT")"
echo " Compression ratio: ${RATIO}:1"
else
echo " ✗ Compression failed"
exit 1
fi
COMPRESS_EOF
フェーズ 6:孤立ブランチにプッシュ
/usr/bin/env bash << 'PUSH_EOF'
COMPRESSED_FILE="$1"
RECORDINGS_DIR="$HOME/asciinema_recordings"
# Find the local recordings clone
REPO_DIR=$(find "$RECORDINGS_DIR" -maxdepth 1 -type d -name "*" | head -1)
if [[ -z "$REPO_DIR" ]] || [[ ! -d "$REPO_DIR/.git" ]]; then
echo " ⚠ No orphan branch clone found at $RECORDINGS_DIR"
echo " Run /asciinema-tools:bootstrap to set up orphan branch"
exit 1
fi
echo "Pushing to orphan branch..."
# Copy compressed file
BASENAME=$(basename "$COMPRESSED_FILE")
DEST="$REPO_DIR/recordings/$BASENAME"
mkdir -p "$(dirname "$DEST")"
cp "$COMPRESSED_FILE" "$DEST"
# Commit and push
cd "$REPO_DIR"
git add -A
git commit -m "finalize: $BASENAME" 2>/dev/null || true
# Push with token (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
REMOTE_URL=$(git remote get-url origin)
# Convert to token-authenticated URL
TOKEN_URL=$(echo "$REMOTE_URL" | sed "s|https://github.com|https://[email protected]|")
if git push "$TOKEN_URL" HEAD 2>/dev/null; then
echo " ✓ Pushed to orphan branch"
else
echo " ✗ Push failed (check credentials)"
fi
else
echo " ⚠ No GitHub token, skipping push"
fi
PUSH_EOF
フェーズ 7:クリーンアップの確認
AskUserQuestion:
question: "Delete local .cast file after successful compression/push?"
header: "Cleanup"
options:
- label: "Yes, delete local .cast"
description: "Remove original .cast file (compressed version preserved)"
- label: "No, keep local"
description: "Keep both .cast and .cast.zst files"
使用例
# Interactive mode - discover and select
/asciinema-tools:finalize
# Finalize specific file
/asciinema-tools:finalize ~/eon/project/tmp/session.cast
# Finalize all with force stop
/asciinema-tools:finalize --all --force
# Local only (no push)
/asciinema-tools:finalize session.cast --no-push
トラブルシューティング
| Issue | Cause | Solution |
|---|---|---|
| プロセスが停止しない | asciinema プロセスがハングしている | SIGKILL を使用するには --force フラグを指定します |
| ファイルが切り詰められている可能性がある | 強制停止によってファイル処理が中断された | ほとんどのデータは保持されています。再生してみてください |
| zstd が見つからない | zstd がインストールされていない | brew install zstd |
| プッシュに失敗した | GitHub トークンがない | GH_TOKEN を設定するか、gh auth login を実行します |
| 孤立ブランチがない | クローンが設定されていない | まず /asciinema-tools:bootstrap を実行します |
| ファイルが見つからない | パスが間違っているか、すでに移動されている | /daemon-status で確認します |
関連コマンド
/asciinema-tools:daemon-status- ステータスを表示し、未処理のファイルを探します/asciinema-tools:convert- .cast を解析用の .txt に変換します/asciinema-tools:summarize- 録画を AI で分析します
実行後の振り返り
このスキルの実行が完了したら、タスクを終了する前に振り返ってください。
- 現在の場所を確認する。 — 編集前に、この SKILL.md の正式なパスを確認します。
- 何が失敗したか? — 原因となった指示を修正します。
- 予想以上にうまくいったことは? — 推奨される方法として取り入れます。
- 何がずれていたか? — 現状と一致しなくなったスクリプト、参照先、依存関係を修正します。
- 記録する。 — きっかけ、修正内容、根拠を進化ログに記録します。
先延ばしにしないでください。次回の実行には、ここに残した状態が引き継がれます。
コメント
Markdown 対応