Claude Code Bulk Actions

Run Claude Code interactively in tmux popups for batch processing tasks - generating content, updating files, or researching items one by one.

cli

When you need Claude to perform the same task across many items - generating descriptions, updating files, researching topics - running Claude interactively in a tmux popup for each item gives you visibility into what’s happening and the ability to intervene if needed.

Why Tmux Popups?

  • Interactive mode shows Claude’s thinking and tool usage in real-time
  • Isolated context - each item gets a fresh Claude session
  • Easy to cancel - close the popup to skip an item, Ctrl+C to stop the whole batch
  • Non-blocking - your main terminal remains usable between items

The Pattern

The key technique is writing a temporary shell script for each item, then executing it in a tmux popup:

#!/bin/bash

items=("item1" "item2" "item3")

for item in "${items[@]}"; do
  echo "Processing: $item"

  # Create temp script
  script_file=$(mktemp).sh

  # Write the script with variables expanded
  cat > "$script_file" << SCRIPT
#!/bin/bash
export PATH="$PATH"
cd /path/to/working/directory
claude "Your prompt for $item"
SCRIPT

  chmod +x "$script_file"

  # Run in tmux popup
  if [ -n "$TMUX" ]; then
    tmux display-popup -E -w 80% -h 80% "bash $script_file"
  else
    bash "$script_file"
  fi

  rm -f "$script_file"
done

Key Details

Temp Script Approach

Writing a temp script avoids shell escaping issues with complex prompts. The heredoc expands variables at write time, so the script contains the actual values.

script_file=$(mktemp).sh

cat > "$script_file" << SCRIPT
#!/bin/bash
claude "Process $item_name in $file_path"
SCRIPT

PATH Inheritance

Tmux popups don’t inherit your shell’s PATH by default. Export it in the temp script:

cat > "$script_file" << SCRIPT
#!/bin/bash
export PATH="$PATH"
claude "..."
SCRIPT

Working Directory

If Claude needs to edit files, set the working directory in the temp script so file paths resolve correctly:

cat > "$script_file" << SCRIPT
#!/bin/bash
export PATH="$PATH"
cd ~/repos/my-project
claude "Edit the file $relative_path"
SCRIPT

Interactive vs Print Mode

Use Claude without -p for interactive mode (recommended for bulk actions):

# Interactive - shows progress, can be interrupted
claude "Your prompt here"

# Print mode - silent, outputs result only
claude -p "Your prompt here"

Fallback for Non-Tmux

Always include a fallback for running outside tmux:

if [ -n "$TMUX" ]; then
  tmux display-popup -E -w 80% -h 80% "bash $script_file"
else
  bash "$script_file"
fi

Complete Template

#!/bin/bash
# Bulk action template for Claude Code

WORKING_DIR="$HOME/repos/my-project"
ITEMS_DIR="path/to/items"

# Find items to process
find_items() {
  find "$ITEMS_DIR" -name "*.md" -type f
}

# Extract metadata from an item
get_item_name() {
  local file="$1"
  grep "^name:" "$file" | sed 's/^name: *//'
}

# Count items
total=$(find_items | wc -l | tr -d ' ')
current=0

echo "Found $total items to process"
echo ""

# Process each item
find_items | while IFS= read -r item_file; do
  current=$((current + 1))
  item_name=$(get_item_name "$item_file")

  echo "[$current/$total] $item_name"

  # Create temp script
  script_file=$(mktemp).sh

  # Build the prompt
  cat > "$script_file" << SCRIPT
#!/bin/bash
export PATH="$PATH"
cd $WORKING_DIR
claude "Your task description here.

Process the item: $item_name
File path: $item_file

Instructions for what Claude should do..."
SCRIPT

  chmod +x "$script_file"

  # Run in tmux popup or directly
  if [ -n "$TMUX" ]; then
    tmux display-popup -E -w 80% -h 80% "bash $script_file"
  else
    bash "$script_file"
  fi

  rm -f "$script_file"
done

echo ""
echo "Done processing $total items."

Tips

  1. Test with one item first - run the script and cancel after the first popup to verify everything works
  2. Use relative paths - if Claude is editing files, use paths relative to the working directory
  3. Keep prompts focused - each Claude session should do one specific task
  4. Add progress indicators - show [current/total] so you know how far along you are
  5. Handle special characters - if item names contain quotes, the heredoc handles them safely

See Also

-
-