Skip to content

Instantly share code, notes, and snippets.

@peterhartree
Created June 9, 2026 09:41
Show Gist options
  • Select an option

  • Save peterhartree/ae82a7c0aa20e2fe8d9093e4daffe54f to your computer and use it in GitHub Desktop.

Select an option

Save peterhartree/ae82a7c0aa20e2fe8d9093e4daffe54f to your computer and use it in GitHub Desktop.
c2: send one prompt to both Claude Code and Codex in side-by-side Warp panes
# c2: pick a project (same switcher as cc/cx), then run Codex in THIS pane and
# Claude in a new split pane to the right - both seeded with the same prompt.
# Companion to https://wow.pjh.is/journal/claude-code-project-switcher
# Usage: c2 <prompt...> (interactive picker, then both agents)
# c2 3 <prompt...> (quick-select project/recent slot 3)
# c2 r2 <prompt...> (quick-select recent-dir slot 2)
# c2 (no prompt -> opens $EDITOR; or pipe via stdin)
c2() {
if [[ "$TERM_PROGRAM" != "WarpTerminal" ]]; then
echo "c2: built for Warp - the second pane is created with Warp's split shortcut." >&2
fi
local select_arg=""
case "$1" in
[1-9]|r[1-9]) select_arg="--select $1"; shift ;;
esac
local prompt="$*"
if [ -z "$prompt" ]; then
if [ ! -t 0 ]; then
prompt="$(cat)"
else
# No prompt on the command line: compose one in $EDITOR. macOS Cmd-
# based line editing (Cmd+Left, Cmd+Backspace) and Shift+Enter only
# work in a GUI editor - terminal line readers never receive Cmd
# chords. $EDITOR may carry args (e.g. "code --wait"), which zsh
# won't word-split, so use ${=...}; fall back to vi if missing.
local edit ed
edit=$(mktemp /tmp/c2-edit.XXXXXX)
ed=${EDITOR:-vi}
command -v ${ed%% *} >/dev/null 2>&1 || ed=vi
${=ed} "$edit"
prompt="$(cat "$edit")"
rm -f "$edit"
fi
fi
if [ -z "${prompt//[[:space:]]/}" ]; then
echo "c2: no prompt provided." >&2
return 1
fi
local result
result=$(python3 ~/.agents/scripts/agents/coding_agent_launcher.py "$PWD" ${=select_arg})
local exit_code=$?
if [ $exit_code -ne 0 ] || [ -z "$result" ] || [ ! -d "$result" ]; then
return $exit_code
fi
_agent_record_recent_dir "$result"
# Stash the prompt and a self-cleaning runner so the new pane only ever has a
# plain /tmp path typed into it (no quotes/parens for Warp's editor to mangle).
local promptfile runner
promptfile=$(mktemp /tmp/c2-prompt.XXXXXX)
runner=$(mktemp /tmp/c2-claude.XXXXXX)
printf '%s' "$prompt" > "$promptfile"
cat > "$runner" <<RUNNER
#!/bin/zsh
cd ${(q)result}
claude --model opus "\$(cat ${(q)promptfile})"
rm -f ${(q)promptfile} ${(q)runner}
RUNNER
chmod +x "$runner"
cd "$result"
# Split right (Cmd+D), run the runner in the new pane, refocus this pane
# (Ctrl+[ = pane_group:navigate_prev). Tune the post-split delay if the first
# characters get dropped on a slow shell start.
osascript - "$runner" <<'APPLESCRIPT'
on run argv
set runnerPath to item 1 of argv
tell application "Warp" to activate
delay 0.2
tell application "System Events"
keystroke "d" using command down
delay 1.0
keystroke runnerPath
delay 0.1
key code 36
delay 0.2
key code 33 using control down
end tell
end run
APPLESCRIPT
if [ $? -ne 0 ]; then
echo "c2: couldn't drive Warp - grant Accessibility to Warp in System Settings > Privacy & Security > Accessibility, then retry. Running Codex only." >&2
rm -f "$promptfile" "$runner"
fi
codex "$prompt"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment