Created
June 15, 2026 15:48
-
-
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 対応。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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