Skip to content

Instantly share code, notes, and snippets.

@tomo3141592653
Created June 15, 2026 15:48
Show Gist options
  • Select an option

  • Save tomo3141592653/dfdecc6a2f00cc228cab0c5ce25b52b1 to your computer and use it in GitHub Desktop.

Select an option

Save tomo3141592653/dfdecc6a2f00cc228cab0c5ce25b52b1 to your computer and use it in GitHub Desktop.
claude --print (claude -p) の tmux 代替ラッパー: サブスクで --print が使えない時に Claude CLI を非対話駆動。__SESSION_COMPLETE__ で完了検出、--resume/--continue/--model/--allowed-tools 対応。
#!/bin/bash
# claude_tmux_runner.sh
#
# claude -p の代替。tmux経由でClaude CLIを駆動する。
# サブスク制限で --print が使えなくなった場合の代替手段。
#
# Usage:
# ./claude_tmux_runner.sh -p "prompt" # 新規セッション(--printと同等)
# ./claude_tmux_runner.sh --resume SESSION_ID "prompt" # セッション継続
# ./claude_tmux_runner.sh --continue "prompt" # 既存tmuxセッションに追加送信
#
# 完了検出: __SESSION_COMPLETE__ マーカーをポーリング(タイムアウトで強制終了)
#
# 環境変数:
# CLAUDE_TMUX_SESSION tmuxセッション名(デフォルト: ayumu_claude)
# CLAUDE_TMUX_TIMEOUT タイムアウト秒(デフォルト: 3600 = 60分)
# CLAUDE_MODEL モデル名(デフォルト: sonnet)
set -euo pipefail
SESSION="${CLAUDE_TMUX_SESSION:-ayumu_claude}"
TIMEOUT="${CLAUDE_TMUX_TIMEOUT:-3600}"
MODEL="${CLAUDE_MODEL:-sonnet}"
STARTUP_WAIT=5
POLL_INTERVAL=10
MODE="new"
RESUME_ID=""
# デフォルト: auto + enable-auto-mode(非対話モード相当)
# allowlist外の権限は通知経由で承認する運用を想定
EXTRA_ARGS="--permission-mode auto --enable-auto-mode"
# 引数パース
while [[ $# -gt 0 ]]; do
case "$1" in
-p|--print)
MODE="new"
shift
;;
--resume)
MODE="resume"
RESUME_ID="$2"
shift 2
;;
--continue)
MODE="continue"
shift
;;
--timeout)
TIMEOUT="$2"
shift 2
;;
--model)
MODEL="$2"
shift 2
;;
--permission-mode)
# デフォルトの --permission-mode auto を上書き
EXTRA_ARGS="${EXTRA_ARGS/--permission-mode auto/} --permission-mode $2"
shift 2
;;
--allowed-tools)
# 使用ツールを制限(read-only相当: 例 "Read,Glob,Grep,WebSearch,WebFetch")。
# 信頼できない入力元(外部ユーザー等)で書き込み・Bash実行を封じる用途。
EXTRA_ARGS="$EXTRA_ARGS --allowedTools $2"
shift 2
;;
--no-auto-mode)
EXTRA_ARGS="${EXTRA_ARGS/--enable-auto-mode/}"
shift
;;
--)
shift
break
;;
*)
break
;;
esac
done
PROMPT="${*:-}"
if [[ -z "$PROMPT" ]]; then
echo "Error: no prompt provided" >&2
echo "Usage: $0 [-p|--resume ID|--continue] [--timeout N] \"prompt text\"" >&2
exit 1
fi
# ログファイル(pipeで全出力を記録)
LOG_FILE="/tmp/ayumu_claude_$(date +%s)_$$.log"
cleanup() {
tmux pipe-pane -t "$SESSION" 2>/dev/null || true
rm -f "$LOG_FILE"
}
trap cleanup EXIT
# ----- セッション準備 -----
if [[ "$MODE" == "new" ]]; then
# 新規: 既存セッションを破棄してから作り直す
tmux kill-session -t "$SESSION" 2>/dev/null || true
tmux new-session -d -s "$SESSION"
CLAUDE_CMD="claude --model $MODEL $EXTRA_ARGS"
echo "[claude_tmux_runner] Starting new session: $CLAUDE_CMD" >&2
tmux send-keys -t "$SESSION" "$CLAUDE_CMD" C-m
sleep "$STARTUP_WAIT"
elif [[ "$MODE" == "resume" ]]; then
# resume: 既存セッションを破棄して --resume で起動
tmux kill-session -t "$SESSION" 2>/dev/null || true
tmux new-session -d -s "$SESSION"
CLAUDE_CMD="claude --resume $RESUME_ID --model $MODEL $EXTRA_ARGS"
echo "[claude_tmux_runner] Resuming session $RESUME_ID: $CLAUDE_CMD" >&2
tmux send-keys -t "$SESSION" "$CLAUDE_CMD" C-m
sleep "$STARTUP_WAIT"
elif [[ "$MODE" == "continue" ]]; then
# continue: 既存 tmux セッションに追加送信(Claudeは起動済み前提)
if ! tmux has-session -t "$SESSION" 2>/dev/null; then
echo "Error: tmux session '$SESSION' not found. Use -p to start." >&2
exit 1
fi
echo "[claude_tmux_runner] Continuing existing session." >&2
fi
# プロンプト送信
# C-m を一緒に渡すと bracketed paste mode で Enter が無視されるので Enter は別送り
echo "[claude_tmux_runner] Sending prompt..." >&2
tmux send-keys -t "$SESSION" "$PROMPT"
sleep 0.3
tmux send-keys -t "$SESSION" "" Enter
# Enter の後から pane 出力をファイルに流す(プロンプトエコーを除外)
sleep 1
tmux pipe-pane -t "$SESSION" "cat >> $LOG_FILE"
# ----- 完了待機 -----
# grep は行頭・行末アンカーで絞る(プロンプト文中に埋まった偽陽性を避ける)
echo "[claude_tmux_runner] Waiting for __SESSION_COMPLETE__ (timeout: ${TIMEOUT}s)..." >&2
ELAPSED=0
while [[ $ELAPSED -lt $TIMEOUT ]]; do
sleep "$POLL_INTERVAL"
ELAPSED=$((ELAPSED + POLL_INTERVAL))
if grep -q "^__SESSION_COMPLETE__$" "$LOG_FILE" 2>/dev/null; then
echo "[claude_tmux_runner] Session completed (elapsed: ${ELAPSED}s)." >&2
# gateway の _run_claude_session がマーカーを stdout で検出するために echo
echo "__SESSION_COMPLETE__"
exit 0
fi
done
echo "[claude_tmux_runner] Timeout after ${TIMEOUT}s." >&2
exit 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment