#!/bin/bash # UserPromptSubmit hook: 文脈が閾値を超えたら /checkpoint・引き継ぎメモ → /clear を促す(通知のみ。送信は止めない) # # 閾値は CLAUDE_CHECKPOINT_TOKENS(既定 200000)。自動 compact は CLAUDE_CODE_AUTO_COMPACT_WINDOW が安全網。 # 自動 compact は設定値ちょうどではなく、手元では約 33k 手前で走った。残量はこの差を引いて見積もる。 # # 閾値を超えた後も STEP_TOKENS ごとに残量を添えて再通知する。1 回きりだとモデルが先送りし、 # そのまま自動 compact が走ることがある。保存の指示は stop-bye-trigger.sh が受け持つ。 # # 前提: statusline が実トークン数を /tmp/claude-context-tokens- に書き出していること # (statusline-tokens.sh を参照)。jq を使う。 THRESHOLD_TOKENS=${CLAUDE_CHECKPOINT_TOKENS:-200000} STEP_TOKENS=25000 COMPACT_WINDOW=${CLAUDE_CODE_AUTO_COMPACT_WINDOW:-1000000} COMPACT_AT=$((COMPACT_WINDOW - 33000)) input=$(cat) session_id=$(echo "$input" | jq -r '.session_id // empty' 2>/dev/null) [ -z "$session_id" ] && exit 0 cwd=$(echo "$input" | jq -r '.cwd // empty' 2>/dev/null) # stop-auto-resume.sh と同じく、Bash の cd でずれない起動ディレクトリをメモ名に使う key=${CLAUDE_PROJECT_DIR:-$cwd} handoff="$HOME/.claude/handoff/${key//\//-}.md" # statusline.sh が書いたキャッシュから現在の文脈トークン数を取得 tokens=$(cat "/tmp/claude-context-tokens-${session_id}" 2>/dev/null) [ -z "$tokens" ] && exit 0 # 旗には最後に通知した段(閾値からの STEP_TOKENS 刻み)を書く FLAG_FILE="/tmp/claude-bye-warned-${session_id}" # compact・/clear 後に閾値を下回ったら次の周回でもう一度警告できるよう旗を下ろす if [ "$tokens" -lt "$THRESHOLD_TOKENS" ]; then rm -f "$FLAG_FILE" exit 0 fi step=$(( (tokens - THRESHOLD_TOKENS) / STEP_TOKENS )) last=$(cat "$FLAG_FILE" 2>/dev/null) [ -n "$last" ] && [ "$step" -le "$last" ] && exit 0 echo "$step" >"$FLAG_FILE" remaining=$(( (COMPACT_AT - tokens) / 1000 )) [ "$remaining" -lt 0 ] && remaining=0 # herdr 上ではターン末に stop-auto-resume.sh が自動で /clear → 再開する if [ "${HERDR_ENV:-}" = 1 ] && [ "${CLAUDE_AUTO_RESUME:-1}" != 0 ]; then closing="ターンが終わると自動で /clear して引き継ぎメモから再開する。区切りが悪い時だけ ${handoff%.md}.noauto を touch して止める。" else closing="返答の最後に「区切りがよければ /clear と打てば、引き継ぎメモから続きを再開する」と一言添える。" fi if [ -z "$last" ]; then msg=$(printf '⚠️ 文脈が %dk トークンに達した(閾値 %dk、自動 compact まで残り約 %dk)。返答の前に /checkpoint を実行し、引き継ぎメモ(目的・作業中のファイル・未コミットの変更・決まったこと・次の一手)を %s に書き出すこと。ツール呼び出しは最小にし、メモリ本体・MEMORY.md 索引の追記・引き継ぎメモは可能なら 1 回の Bash(heredoc)でまとめる。「随時保存してきた」は省略の理由にならない。%s' \ "$((tokens / 1000))" "$((THRESHOLD_TOKENS / 1000))" "$remaining" "$handoff" "$closing") else msg=$(printf '⚠️ 文脈 %dk トークン、自動 compact まで残り約 %dk。引き継ぎメモ %s を最新の状態に書き直すこと。%s' \ "$((tokens / 1000))" "$remaining" "$handoff" "$closing") fi jq -nc --arg m "$msg" '{hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:$m}}'