Skip to content

Instantly share code, notes, and snippets.

@chrisregner
Created May 14, 2026 19:30
Show Gist options
  • Select an option

  • Save chrisregner/dab44c1ee367b3e84daee90da7ed06f4 to your computer and use it in GitHub Desktop.

Select an option

Save chrisregner/dab44c1ee367b3e84daee90da7ed06f4 to your computer and use it in GitHub Desktop.
Claude Code CLI Wrapper to allow auto start new session with next prompt when printing <<<LOOP_RESTART prompt-here>>>
#!/usr/bin/env bash
set -u
set -o pipefail
# Force C locale so ASCII byte ranges in regexes ([@-~] etc.) behave.
export LC_ALL=C
raw_file="${TMPDIR:-/tmp}/claude-loop.$$.raw"
payload_file="${TMPDIR:-/tmp}/claude-loop.$$.payload"
trap 'rm -f "$raw_file" "$payload_file"' EXIT
max_iters=50
iter=0
keep_raw=0
claude_flags=()
next_cmd=""
pty_helper="$(dirname "$(readlink -f "$0")")/claude-loop-pty"
if [[ ! -x "$pty_helper" ]]; then
printf '[claude-loop] missing helper: %s\n' "$pty_helper" >&2
exit 3
fi
for arg in "$@"; do
if [[ "$arg" == "--keep-raw" ]]; then
keep_raw=1
elif [[ "$arg" == -* ]]; then
claude_flags+=("$arg")
elif [[ -z "$next_cmd" ]]; then
next_cmd="$arg"
else
printf '[claude-loop] unexpected extra positional arg: %s\n' "$arg" >&2
exit 2
fi
done
export CLAUDE_LOOP_RAW="$raw_file"
export CLAUDE_LOOP_PAYLOAD_OUT="$payload_file"
while (( iter < max_iters )); do
(( iter++ ))
rm -f "$raw_file" "$payload_file"
cmd=(claude "${claude_flags[@]}")
if [[ -n "$next_cmd" ]]; then
cmd+=(-- "$next_cmd")
fi
printf '[claude-loop] (%d/%d) launching: %s\n' \
"$iter" "$max_iters" "${cmd[*]}"
"$pty_helper" "${cmd[@]}"
rc=$?
if (( keep_raw )); then
debug_path="${TMPDIR:-/tmp}/claude-loop.debug.$$.iter${iter}.raw"
cp "$raw_file" "$debug_path" 2>/dev/null && \
printf '[claude-loop] kept raw transcript: %s\n' "$debug_path" >&2
fi
# Recover terminal state (TUI + nested PTYs sometimes leave it weird).
stty sane 2>/dev/null || true
printf '\033[?1049l\033[?25h\033[?2004l\033[?1000l\033[?1002l\033[?1003l\033[?1006l'
if (( rc == 42 )) && [[ -s "$payload_file" ]]; then
next_cmd=$(cat "$payload_file")
printf '\n[claude-loop] trigger detected, restarting with: %s\n\n' "$next_cmd"
else
printf '\n[claude-loop] claude exited without a trigger (rc=%d), stopping.\n' "$rc"
exit 0
fi
done
printf '\n[claude-loop] hit max_iters=%d, stopping to avoid runaway loop.\n' "$max_iters" >&2
exit 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment