- Setup wizard with auto-detection of OpenClaw paths and Claude CLI - Token sync watcher (inotifywait) for real-time credential updates - Auto-refresh trigger timer that runs Claude CLI every 30 min - Supports Claude CLI in Docker container or on host - Temporary ANTHROPIC_BASE_URL override for container environments - Anthropic model configuration for OpenClaw - Auth profile management (fixes key vs access field) - Systemd services and timers for both sync and trigger - Comprehensive documentation and troubleshooting guides - Re-authentication notification system Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
3.4 KiB
Bash
Executable File
113 lines
3.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# trigger-claude-refresh.sh — Triggers Claude CLI to refresh OAuth token when near expiry
|
|
#
|
|
# Runs via systemd timer every 30 minutes.
|
|
# Checks token expiry, triggers CLI only when needed.
|
|
# The existing sync-oauth-token.sh (inotifywait) handles syncing to OpenClaw.
|
|
#
|
|
# Supports two modes:
|
|
# Container mode: Claude CLI runs inside a Docker container
|
|
# Host mode: Claude CLI is installed directly on the system
|
|
|
|
set -uo pipefail
|
|
|
|
CREDS_FILE="@@CREDS_FILE@@"
|
|
REAUTH_FLAG="@@REAUTH_FLAG@@"
|
|
CLI_MODE="@@CLI_MODE@@"
|
|
CLI_CONTAINER="@@CLI_CONTAINER@@"
|
|
CLI_BASE_URL_OVERRIDE="@@CLI_BASE_URL_OVERRIDE@@"
|
|
LOG_PREFIX="[trigger-refresh]"
|
|
THRESHOLD_HOURS=1.5
|
|
TIMEOUT_SECONDS=60
|
|
|
|
log() { echo "$LOG_PREFIX $*"; }
|
|
log_err() { echo "$LOG_PREFIX ERROR: $*" >&2; }
|
|
|
|
# Check prerequisites
|
|
if [ ! -f "$CREDS_FILE" ]; then
|
|
log_err "Credentials file not found: $CREDS_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$CLI_MODE" = "container" ]; then
|
|
if ! docker ps --filter "name=$CLI_CONTAINER" --format '{{.Names}}' | grep -q "$CLI_CONTAINER"; then
|
|
log_err "Container $CLI_CONTAINER is not running"
|
|
exit 1
|
|
fi
|
|
else
|
|
if ! command -v claude &>/dev/null; then
|
|
log_err "Claude CLI not found on system"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Read expiry and decide whether to trigger
|
|
REMAINING=$(python3 -c "
|
|
import json, time
|
|
with open('$CREDS_FILE') as f:
|
|
d = json.load(f)
|
|
expires = d.get('claudeAiOauth', {}).get('expiresAt', 0)
|
|
remaining = (expires / 1000 - time.time()) / 3600
|
|
print(f'{remaining:.2f}')
|
|
")
|
|
|
|
log "Token expires in ${REMAINING}h (threshold: ${THRESHOLD_HOURS}h)"
|
|
|
|
# Compare as integers (multiply by 100 to avoid bash float issues)
|
|
REMAINING_X100=$(python3 -c "print(int(float('$REMAINING') * 100))")
|
|
THRESHOLD_X100=$(python3 -c "print(int(float('$THRESHOLD_HOURS') * 100))")
|
|
|
|
if [ "$REMAINING_X100" -gt "$THRESHOLD_X100" ]; then
|
|
log "Token still fresh, nothing to do"
|
|
exit 0
|
|
fi
|
|
|
|
log "Token near expiry, triggering Claude CLI refresh..."
|
|
|
|
# Record mtime BEFORE
|
|
MTIME_BEFORE=$(stat -c %Y "$CREDS_FILE" 2>/dev/null || stat -f %m "$CREDS_FILE" 2>/dev/null)
|
|
|
|
# Trigger Claude CLI
|
|
if [ "$CLI_MODE" = "container" ]; then
|
|
if [ "$CLI_BASE_URL_OVERRIDE" = "true" ]; then
|
|
CLI_OUTPUT=$(timeout "$TIMEOUT_SECONDS" docker exec \
|
|
-e ANTHROPIC_BASE_URL=https://api.anthropic.com \
|
|
"$CLI_CONTAINER" claude -p "say ok" --no-session-persistence 2>&1)
|
|
else
|
|
CLI_OUTPUT=$(timeout "$TIMEOUT_SECONDS" docker exec \
|
|
"$CLI_CONTAINER" claude -p "say ok" --no-session-persistence 2>&1)
|
|
fi
|
|
else
|
|
CLI_OUTPUT=$(timeout "$TIMEOUT_SECONDS" claude -p "say ok" --no-session-persistence 2>&1)
|
|
fi
|
|
CLI_EXIT=$?
|
|
|
|
if [ "$CLI_EXIT" -eq 124 ]; then
|
|
log_err "CLI command timed out after ${TIMEOUT_SECONDS}s"
|
|
fi
|
|
|
|
log "CLI exit code: $CLI_EXIT, output: $CLI_OUTPUT"
|
|
|
|
# Record mtime AFTER
|
|
sleep 2
|
|
MTIME_AFTER=$(stat -c %Y "$CREDS_FILE" 2>/dev/null || stat -f %m "$CREDS_FILE" 2>/dev/null)
|
|
|
|
if [ "$MTIME_BEFORE" != "$MTIME_AFTER" ]; then
|
|
log "Token refreshed successfully (mtime changed: $MTIME_BEFORE -> $MTIME_AFTER)"
|
|
|
|
if [ -f "$REAUTH_FLAG" ]; then
|
|
rm -f "$REAUTH_FLAG"
|
|
log "Cleared previous REAUTH_NEEDED flag"
|
|
fi
|
|
|
|
exit 0
|
|
else
|
|
log_err "Token refresh FAILED — credentials.json was not updated"
|
|
log_err "Re-authentication may be required (refresh token expired or subscription issue)"
|
|
|
|
echo "Re-authentication needed at $(date -u '+%Y-%m-%dT%H:%M:%SZ')" > "$REAUTH_FLAG"
|
|
log_err "Wrote $REAUTH_FLAG"
|
|
|
|
exit 1
|
|
fi
|