Claude-skill-registry agent-ops-selective-copy
Create clean git branches from feature work, excluding agent-ops files. Use for PR preparation.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/agent-ops-selective-copy" ~/.claude/skills/majiayu000-claude-skill-registry-agent-ops-selective-copy && rm -rf "$T"
skills/data/agent-ops-selective-copy/SKILL.mdSelective Copy — Clean Branch Creation
Create a clean git branch from feature work, excluding specific paths. Platform agnostic.
Works with or without
CLI. Uses standard git commands.aoc
Purpose
Create a new branch containing feature work while excluding agent/workflow files for clean PRs.
CRITICAL: No Assumptions
NEVER assume. NEVER guess. ALWAYS ask.
Before creating ANY clean branch, confirm with user:
| If unclear about... | ASK |
|---|---|
| Source branch | "Which branch contains your feature work?" |
| Clean branch name | "I'll create . Does this look right?" |
| Base branch | "Which branch should excluded paths be restored from? (e.g., develop, main)" |
| What to exclude | "What paths should I exclude? (Default: .agent/, .github/)" |
If ANY of these are ambiguous:
- Stop
- Ask ONE question at a time
- Wait for explicit confirmation
- Only proceed when ALL inputs are confirmed
NEVER:
- Guess the base branch
- Assume exclusions without asking
- Create a branch without showing the user the exact name first
- Proceed if source branch is unclear
Prerequisites
MANDATORY: File Audit Trail
The file-created.log MUST exist before proceeding. This ensures we know which files to exclude.
If
.agent/log/created-files.log does not exist:
- Generate it from git history (see Generation Procedure below)
- Present to user for validation
- Only proceed after user confirms the list
This prevents accidental inclusion of agent-ops files in the clean branch.
Invocation
User says something like:
- "Create a clean branch for PR"
- "Make a branch without .agent and .github changes"
- "Prepare my feature for code review"
Arguments
| Argument | Description | Default |
|---|---|---|
| Feature branch with work | Current branch |
| Name for clean branch | |
| Branch to restore excluded paths from | Auto-detect |
| Paths/patterns to exclude | Prompt user |
Workflow
1. Gather Requirements
If not provided, ask:
- Source branch (default: current)
- New branch name (default:
){current}-clean - Base branch — try auto-detect first:
# PowerShell: Find merge-base with main or develop $mainBase = git merge-base HEAD main 2>$null $devBase = git merge-base HEAD develop 2>$null if ($mainBase) { $baseBranch = "main" } elseif ($devBase) { $baseBranch = "develop" } else { # Ask user Write-Host "Could not auto-detect base branch. Which branch was this feature branched from?" }
# Bash: Find merge-base main_base=$(git merge-base HEAD main 2>/dev/null) dev_base=$(git merge-base HEAD develop 2>/dev/null) if [ -n "$main_base" ]; then base_branch="main" elif [ -n "$dev_base" ]; then base_branch="develop" else echo "Could not auto-detect base branch. Which branch was this feature branched from?" fi
- Exclusions — if not specified, prompt:
Would you like to exclude agent-ops files? This includes: - `.agent/` directory - `.github/skills/`, `.github/prompts/`, `.github/agents/` Additionally, agent-ops created these files outside .agent/: {list from .agent/log/created-files.log} [1] Exclude all agent-ops files (recommended) [2] Exclude only .agent/ and .github/ [3] Let me specify custom paths [4] Don't exclude anything
2. Check and Generate Audit Trail (MANDATORY)
Before proceeding, verify
exists..agent/log/created-files.log
# PowerShell $logPath = ".agent/log/created-files.log" if (-not (Test-Path $logPath)) { Write-Host "⚠️ File audit trail not found: $logPath" -ForegroundColor Yellow Write-Host "Generating from git history..." -ForegroundColor Cyan # Proceed to generation } else { Write-Host "✓ Audit trail found: $logPath" -ForegroundColor Green # Skip to step 3 }
# Bash log_path=".agent/log/created-files.log" if [ ! -f "$log_path" ]; then echo "⚠️ File audit trail not found: $log_path" echo "Generating from git history..." # Proceed to generation else echo "✓ Audit trail found: $log_path" # Skip to step 3 fi
If log is missing, generate it:
Generation Procedure
- Find the branch point (where feature diverged from base):
# PowerShell $baseBranch = "develop" # or auto-detected $branchPoint = git merge-base HEAD $baseBranch Write-Host "Branch point: $branchPoint"
# Bash base_branch="develop" branch_point=$(git merge-base HEAD "$base_branch") echo "Branch point: $branch_point"
- List files added since branch point (excluding .agent/ and .github/):
# PowerShell $addedFiles = git diff --name-status --diff-filter=A $branchPoint HEAD | ForEach-Object { ($_ -split "\t")[1] } | Where-Object { $_ -notmatch "^\.agent/" -and $_ -notmatch "^\.github/skills/" -and $_ -notmatch "^\.github/prompts/" -and $_ -notmatch "^\.github/agents/" } Write-Host "`nFiles added since branch point:" -ForegroundColor Cyan $addedFiles | ForEach-Object { Write-Host " CREATE $_" } Write-Host "`nTotal: $($addedFiles.Count) files"
# Bash added_files=$(git diff --name-status --diff-filter=A "$branch_point" HEAD | cut -f2 | grep -v "^\.agent/" | grep -v "^\.github/skills/" | grep -v "^\.github/prompts/" | grep -v "^\.github/agents/") echo "" echo "Files added since branch point:" echo "$added_files" | while read -r file; do [ -n "$file" ] && echo " CREATE $file" done echo "" echo "Total: $(echo "$added_files" | grep -c .)"
- Present to user for validation (MANDATORY):
📋 Generated file list from git history: CREATE src/utils/helper.py CREATE tests/test_helper.py CREATE docs/PLANNING.md Total: 3 files ⚠️ Please review this list carefully. These files will be EXCLUDED from the clean branch. Missing files may leak into PR. Extra files may be wrongly excluded. Options: [1] Approve and continue [2] Edit list (will open in editor) [3] Abort
- Save after user approval:
# PowerShell (only after user confirms) $logDir = ".agent/log" if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } $timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ" # Write header @" # Agent-Ops File Creation Audit Trail # Generated from git history on $timestamp # Branch point: $branchPoint (from $baseBranch) # User validated: YES # --- Log entries below this line --- "@ | Out-File -FilePath $logPath -Encoding utf8 # Write entries foreach ($file in $addedFiles) { Add-Content -Path $logPath -Value "$timestamp CREATE $file" } Write-Host "✓ Audit trail saved: $logPath" -ForegroundColor Green
# Bash (only after user confirms) log_dir=".agent/log" mkdir -p "$log_dir" timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ) # Write header cat > "$log_path" << EOF # Agent-Ops File Creation Audit Trail # Generated from git history on $timestamp # Branch point: $branch_point (from $base_branch) # User validated: YES # --- Log entries below this line --- EOF # Write entries echo "$added_files" | while read -r file; do [ -n "$file" ] && echo "$timestamp CREATE $file" >> "$log_path" done echo "✓ Audit trail saved: $log_path"
3. Read Audit Trail
Check
.agent/log/created-files.log for files created outside .agent/:
# PowerShell $logPath = ".agent/log/created-files.log" $createdFiles = Get-Content $logPath | Where-Object { $_ -match "^\d{4}-\d{2}-\d{2}" } | ForEach-Object { $parts = $_ -split " ", 3 [PSCustomObject]@{ Timestamp = $parts[0] Action = $parts[1] Path = $parts[2] } } | Where-Object { $_.Action -eq "CREATE" } | Select-Object -ExpandProperty Path Write-Host "Files created by agent-ops:" $createdFiles | ForEach-Object { Write-Host " - $_" }
# Bash echo "Files created by agent-ops:" grep "^[0-9]" .agent/log/created-files.log | awk '$2 == "CREATE" { print " - " $3 }'
4. Execute (Git-Based)
Step 1: Create worktree with new branch
# PowerShell $sourceBranch = git branch --show-current $newBranch = "$sourceBranch-clean" $worktreePath = "../$newBranch" git worktree add -b $newBranch $worktreePath HEAD Set-Location $worktreePath
# Bash source_branch=$(git branch --show-current) new_branch="${source_branch}-clean" worktree_path="../${new_branch}" git worktree add -b "$new_branch" "$worktree_path" HEAD cd "$worktree_path"
Step 2: Restore excluded directories from base branch
# PowerShell $baseBranch = "develop" # or detected/user-provided $excludeDirs = @(".github", ".agent") foreach ($dir in $excludeDirs) { git checkout $baseBranch -- $dir 2>$null if ($LASTEXITCODE -eq 0) { Write-Host "Restored $dir from $baseBranch" } else { Write-Host "$dir doesn't exist in $baseBranch (new directory)" } }
# Bash base_branch="develop" exclude_dirs=(".github" ".agent") for dir in "${exclude_dirs[@]}"; do if git checkout "$base_branch" -- "$dir" 2>/dev/null; then echo "Restored $dir from $base_branch" else echo "$dir doesn't exist in $base_branch (new directory)" fi done
Step 3: Remove NEW files that don't exist in base
For files logged in audit trail that are new (not in base branch):
# PowerShell foreach ($file in $createdFiles) { # Check if file exists in base branch $existsInBase = git ls-tree -r $baseBranch --name-only | Where-Object { $_ -eq $file } if (-not $existsInBase) { # File is new, remove from git tracking git rm --cached $file 2>$null Write-Host "Removed new file from tracking: $file" } else { # File exists in base, restore it git checkout $baseBranch -- $file 2>$null Write-Host "Restored $file from $baseBranch" } }
# Bash for file in "${created_files[@]}"; do if git ls-tree -r "$base_branch" --name-only | grep -q "^${file}$"; then # File exists in base, restore it git checkout "$base_branch" -- "$file" 2>/dev/null echo "Restored $file from $base_branch" else # File is new, remove from git tracking git rm --cached "$file" 2>/dev/null echo "Removed new file from tracking: $file" fi done
Step 4: Commit the exclusions
# PowerShell git add -A git commit -m "chore: prepare clean branch for PR (exclude agent-ops files)"
# Bash git add -A git commit -m "chore: prepare clean branch for PR (exclude agent-ops files)"
Step 5: Create Exclusion Log
Create a log file for selective-merge to use later:
# PowerShell $timestamp = Get-Date -Format "yyyy-MM-dd-HHmmss" $logFile = ".agent/log/selective-copy-$newBranch-$timestamp.log" $cleanBranchHash = git rev-parse HEAD $sourceBranchHash = git rev-parse $sourceBranch # Create log directory if needed New-Item -ItemType Directory -Path ".agent/log" -Force | Out-Null # Write log header @" # Selective Copy Exclusion Log # Generated: $(Get-Date -Format "yyyy-MM-ddTHH:mm:ssK") # Source Branch: $sourceBranch ($sourceBranchHash) # Clean Branch: $newBranch ($cleanBranchHash) # Base Branch: $baseBranch # Excluded Paths: $($excludeDirs -join ", ") # Format: {ACTION} {path} # RESTORE = restored from base branch # REMOVE = removed from tracking (new file not in base) "@ | Out-File -FilePath $logFile -Encoding utf8 # Log each excluded directory foreach ($dir in $excludeDirs) { Add-Content -Path $logFile -Value "RESTORE $dir" } # Log removed files from audit trail foreach ($file in $createdFiles) { $existsInBase = git ls-tree -r $baseBranch --name-only | Where-Object { $_ -eq $file } if (-not $existsInBase) { Add-Content -Path $logFile -Value "REMOVE $file" } else { Add-Content -Path $logFile -Value "RESTORE $file" } } Write-Host "Exclusion log created: $logFile"
# Bash timestamp=$(date +"%Y-%m-%d-%H%M%S") log_file=".agent/log/selective-copy-${new_branch}-${timestamp}.log" clean_branch_hash=$(git rev-parse HEAD) source_branch_hash=$(git rev-parse "$source_branch") # Create log directory if needed mkdir -p ".agent/log" # Write log header cat > "$log_file" << EOF # Selective Copy Exclusion Log # Generated: $(date -Iseconds) # Source Branch: $source_branch ($source_branch_hash) # Clean Branch: $new_branch ($clean_branch_hash) # Base Branch: $base_branch # Excluded Paths: ${exclude_dirs[*]} # Format: {ACTION} {path} # RESTORE = restored from base branch # REMOVE = removed from tracking (new file not in base) EOF # Log each excluded directory for dir in "${exclude_dirs[@]}"; do echo "RESTORE $dir" >> "$log_file" done # Log removed files from audit trail for file in "${created_files[@]}"; do if git ls-tree -r "$base_branch" --name-only | grep -q "^${file}$"; then echo "RESTORE $file" >> "$log_file" else echo "REMOVE $file" >> "$log_file" fi done echo "Exclusion log created: $log_file"
5. Verify
# PowerShell Write-Host "`n=== Verification ===" -ForegroundColor Cyan # Check status git status # Compare with base branch Write-Host "`nChanges compared to ${baseBranch}:" git diff $baseBranch --stat # Verify excluded paths match base Write-Host "`nVerifying exclusions:" foreach ($dir in $excludeDirs) { $diff = git diff $baseBranch -- $dir if ([string]::IsNullOrEmpty($diff)) { Write-Host " $dir matches $baseBranch ✓" -ForegroundColor Green } else { Write-Host " $dir has differences from $baseBranch" -ForegroundColor Yellow } }
# Bash echo "" echo "=== Verification ===" # Check status git status # Compare with base branch echo "" echo "Changes compared to ${base_branch}:" git diff "$base_branch" --stat # Verify excluded paths match base echo "" echo "Verifying exclusions:" for dir in "${exclude_dirs[@]}"; do if [ -z "$(git diff "$base_branch" -- "$dir")" ]; then echo " $dir matches $base_branch ✓" else echo " $dir has differences from $base_branch" fi done
6. Validate Results (MANDATORY)
After creating the clean branch, validate using
created-files.log as source of truth:
# PowerShell - Validation Script Write-Host "`n=== Validation ===" -ForegroundColor Cyan $validationPassed = $true $issues = @() # 1. Check created files exist in clean branch (they should be the feature work) $createdFilesLog = ".agent/log/created-files.log" if (Test-Path $createdFilesLog) { Write-Host "`nChecking feature files are present in clean branch..." $createdFiles = Get-Content $createdFilesLog | Where-Object { $_ -match "^\d{4}-\d{2}-\d{2}" -and $_ -match "CREATE" } | ForEach-Object { ($_ -split " ", 3)[2] } | Where-Object { $_ -notmatch "^\.agent/" -and $_ -notmatch "^\.github/skills/" -and $_ -notmatch "^\.github/prompts/" -and $_ -notmatch "^\.github/agents/" } foreach ($file in $createdFiles) { $existsInClean = git ls-tree -r HEAD --name-only | Where-Object { $_ -eq $file } if ($existsInClean) { Write-Host " ✓ $file" -ForegroundColor Green } else { Write-Host " ✗ MISSING: $file" -ForegroundColor Red $issues += "MISSING: $file (should be in clean branch)" $validationPassed = $false } } } # 2. Check NO agent-ops files leaked into clean branch Write-Host "`nChecking for leaked agent-ops files..." $leakedFiles = git ls-tree -r HEAD --name-only | Where-Object { $_ -match "^\.agent/" -or $_ -match "^\.github/skills/agent-ops-" -or $_ -match "^\.github/prompts/agent-ops-" -or $_ -match "^\.github/agents/agent-ops-" } if ($leakedFiles) { foreach ($leaked in $leakedFiles) { Write-Host " ✗ LEAKED: $leaked" -ForegroundColor Red $issues += "LEAKED: $leaked (should NOT be in clean branch)" } $validationPassed = $false } else { Write-Host " ✓ No agent-ops files found" -ForegroundColor Green } # 3. Report Write-Host "`n=== Validation Result ===" -ForegroundColor Cyan if ($validationPassed) { Write-Host "✅ PASSED" -ForegroundColor Green Write-Host " - All feature files present in clean branch" Write-Host " - No agent-ops files leaked" Write-Host " - Clean branch ready for PR" } else { Write-Host "❌ FAILED" -ForegroundColor Red foreach ($issue in $issues) { Write-Host " - $issue" -ForegroundColor Yellow } Write-Host "`nPlease review and fix before pushing." }
# Bash - Validation Script echo "" echo "=== Validation ===" validation_passed=true issues=() # 1. Check created files exist in clean branch created_files_log=".agent/log/created-files.log" if [ -f "$created_files_log" ]; then echo "" echo "Checking feature files are present in clean branch..." while IFS= read -r line; do if [[ "$line" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}.*CREATE ]]; then file=$(echo "$line" | awk '{print $3}') # Skip agent-ops files if [[ ! "$file" =~ ^\.agent/ && ! "$file" =~ ^\.github/skills/ && ! "$file" =~ ^\.github/prompts/ && ! "$file" =~ ^\.github/agents/ ]]; then if git ls-tree -r HEAD --name-only | grep -q "^${file}$"; then echo " ✓ $file" else echo " ✗ MISSING: $file" issues+=("MISSING: $file (should be in clean branch)") validation_passed=false fi fi fi done < "$created_files_log" fi # 2. Check NO agent-ops files leaked echo "" echo "Checking for leaked agent-ops files..." leaked_files=$(git ls-tree -r HEAD --name-only | grep -E "^\.agent/|^\.github/skills/agent-ops-|^\.github/prompts/agent-ops-|^\.github/agents/agent-ops-") if [ -n "$leaked_files" ]; then while IFS= read -r leaked; do echo " ✗ LEAKED: $leaked" issues+=("LEAKED: $leaked (should NOT be in clean branch)") done <<< "$leaked_files" validation_passed=false else echo " ✓ No agent-ops files found" fi # 3. Report echo "" echo "=== Validation Result ===" if [ "$validation_passed" = true ]; then echo "✅ PASSED" echo " - All feature files present in clean branch" echo " - No agent-ops files leaked" echo " - Clean branch ready for PR" else echo "❌ FAILED" for issue in "${issues[@]}"; do echo " - $issue" done echo "" echo "Please review and fix before pushing." fi
7. Report to User
✅ Clean branch created: {new_branch} Location: {worktree_path} Excluded: - .github/ (restored from {base_branch}) - .agent/ (restored from {base_branch}) - {N} files from audit trail Changes from {base_branch}: {git diff --stat output} Validation: PASSED ✓ Next steps: 1. Review changes: cd {worktree_path} && git log --oneline {base_branch}..HEAD 2. Push for PR: git push -u origin {new_branch} 3. Cleanup when done: git worktree remove {worktree_path}
Cleanup
When done with the clean branch:
# PowerShell # Return to original repo Set-Location ../{original-repo} # Remove worktree (keeps branch) git worktree remove ../{new_branch} # Delete branch if no longer needed git branch -D {new_branch}
# Bash # Return to original repo cd ../{original-repo} # Remove worktree (keeps branch) git worktree remove "../${new_branch}" # Delete branch if no longer needed git branch -D "${new_branch}"
Common Exclusion Presets
Clean PR (Recommended)
Directories: .github, .agent Files: All from audit trail
Feature Only
Directories: .github, .agent, .vscode, docs Files: *.md at root, audit trail files
Minimal (Agent Core Only)
Directories: .agent Files: None
Error Handling
| Error | Solution |
|---|---|
| "fatal: not a git repository" | Must run from git repo |
| "error: branch already exists" | Use different name or delete existing |
| "fatal: worktree already exists" | Remove existing worktree first |
| "error: pathspec did not match" | Path doesn't exist in base branch (ok to skip) |
Related Skills
— General git operationsagent-ops-git
— Creates files that get loggedagent-ops-implementation
— Run before creating clean branchagent-ops-validation