diff --git a/README.md b/README.md index ea4d349..6c71210 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # OAuth Fix for OpenClaw + Claude Max +> Created by **ROOH** — [www.rooh.red](https://www.rooh.red) + Automatic Anthropic OAuth token refresh for OpenClaw. Keeps your Claude Max tokens alive indefinitely. ## The Problem @@ -26,19 +28,22 @@ Timer (every 30min) Claude Code CLI sync-oauth-token.sh Op ## Quick Start ```bash -git clone https://github.com/YOUR_USER/oauth-fix-openclaw-final.git -cd oauth-fix-openclaw-final +git clone https://git.eeqj.de/ROOH/openclaw_oauth_sync.git +cd openclaw_oauth_sync sudo ./setup.sh ``` The interactive wizard will: -1. Detect your OpenClaw installation paths -2. Find Claude CLI credentials -3. Configure the Anthropic model (if not already set up) -4. Install the token sync watcher (inotifywait) -5. Detect Claude CLI (container or host) and install the auto-refresh trigger -6. Test the CLI invocation to confirm it works -7. Verify everything works +1. Check prerequisites (offers to install python3, curl, inotify-tools if missing) +2. Detect your OpenClaw installation paths +3. Find Claude CLI credentials (offers to install CLI and help with sign-in if needed) +4. Configure the Anthropic model (if not already set up) +5. Install the token sync watcher (inotifywait or timer fallback) +6. Detect Claude CLI (container or host) and install the auto-refresh trigger +7. Test the CLI invocation to confirm it works +8. Verify everything works + +Every install step asks for your confirmation first — you have full control over what gets installed. ## Prerequisites @@ -46,9 +51,10 @@ The interactive wizard will: - **Docker** + **Docker Compose v2** - **OpenClaw** installed and running - **Claude Max subscription** with OAuth credentials -- **Claude Code CLI** — either in a Docker container or installed on the host -- **python3** -- **inotify-tools** (optional, installed by wizard if missing) +- **Claude Code CLI** — either in a Docker container or installed on the host (wizard can install it) +- **python3** (wizard offers to install if missing) +- **curl** (wizard offers to install if missing) +- **inotify-tools** (optional, wizard offers to install if missing) ## How It Works @@ -257,6 +263,10 @@ See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for common issues: - [Token Refresh](docs/HOW-TOKEN-REFRESH-WORKS.md) — How Claude CLI refreshes tokens - [Field Mapping](docs/FIELD-MAPPING.md) — Credential format reference +## Author + +**ROOH** — [www.rooh.red](https://www.rooh.red) + ## License MIT diff --git a/setup.sh b/setup.sh index 0c50325..439403f 100755 --- a/setup.sh +++ b/setup.sh @@ -68,6 +68,8 @@ echo " ╔═══════════════════════ echo " ║ OAuth Fix for OpenClaw + Claude Max ║" echo " ║ Automatic Anthropic Token Refresh ║" echo " ║ v${VERSION} ║" +echo " ║ ║" +echo " ║ Created by ROOH — www.rooh.red ║" echo " ╚══════════════════════════════════════════════════════╝" echo -e "${NC}" echo -e "${DIM} Keeps your Anthropic OAuth tokens fresh by syncing" @@ -81,11 +83,12 @@ header "Step 1: Checking Prerequisites" MISSING=0 -for cmd in docker python3 curl systemctl; do +# --- Required (cannot be installed by wizard) --- +for cmd in systemctl docker; do if command -v "$cmd" &>/dev/null; then success "$cmd found" else - error "$cmd not found" + error "$cmd not found — required, cannot be installed by this wizard" MISSING=$((MISSING + 1)) fi done @@ -94,19 +97,57 @@ done if docker compose version &>/dev/null; then success "docker compose found ($(docker compose version --short 2>/dev/null || echo 'v2'))" else - error "docker compose v2 not found" + error "docker compose v2 not found — required" MISSING=$((MISSING + 1)) fi -# Check inotifywait +# --- python3 (offer to install) --- +if command -v python3 &>/dev/null; then + success "python3 found" +else + warn "python3 not found (required for JSON processing)" + if confirm " Install python3 now?" "Y"; then + apt-get install -y python3 2>&1 | tail -3 + if command -v python3 &>/dev/null; then + success "python3 installed" + else + error "python3 installation failed" + MISSING=$((MISSING + 1)) + fi + else + error "python3 is required — install it manually and re-run" + MISSING=$((MISSING + 1)) + fi +fi + +# --- curl (offer to install) --- +if command -v curl &>/dev/null; then + success "curl found" +else + warn "curl not found" + if confirm " Install curl now?" "Y"; then + apt-get install -y curl 2>&1 | tail -3 + if command -v curl &>/dev/null; then + success "curl installed" + else + error "curl installation failed" + MISSING=$((MISSING + 1)) + fi + else + error "curl is required — install it manually and re-run" + MISSING=$((MISSING + 1)) + fi +fi + +# --- inotifywait (offer to install, optional) --- if command -v inotifywait &>/dev/null; then success "inotifywait found" USE_INOTIFY=true else warn "inotifywait not found (inotify-tools package)" - echo -e " ${DIM}Install with: apt install inotify-tools${NC}" + echo -e " ${DIM}Provides real-time credential sync. Without it, a 6-hour timer is used instead.${NC}" if confirm " Install inotify-tools now?" "Y"; then - apt-get install -y inotify-tools 2>&1 | tail -1 + apt-get install -y inotify-tools 2>&1 | tail -3 if command -v inotifywait &>/dev/null; then success "inotifywait installed" USE_INOTIFY=true @@ -197,17 +238,22 @@ OPENCLAW_OAUTH_FILE="$OPENCLAW_CONFIG_DIR/credentials/oauth.json" success "OAuth file: $OPENCLAW_OAUTH_FILE" # ============================================================================ -# STEP 3: Detect Claude CLI Credentials +# STEP 3: Claude CLI & Credentials # ============================================================================ -header "Step 3: Detecting Claude CLI Credentials" +header "Step 3: Claude CLI & Credentials" CLAUDE_CREDS_FILE="" +EARLY_CLI_MODE="" +EARLY_CLI_CONTAINER="" +CLI_INSTALLED=false -# Strategy 1: Find claude-proxy or similar container +# --- Phase 1: Search for existing credentials --- +info "Searching for Claude CLI credentials..." + +# Strategy 1: Find claude container and check mounts CLAUDE_CONTAINER=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -i 'claude' | head -1) if [ -n "$CLAUDE_CONTAINER" ]; then info "Found Claude container: $CLAUDE_CONTAINER" - # Get its volume mounts and find credentials MOUNT_SOURCE=$(docker inspect "$CLAUDE_CONTAINER" --format '{{range .Mounts}}{{if or (eq .Destination "/root") (eq .Destination "/root/.claude") (eq .Destination "/home/node/.claude")}}{{.Source}}{{end}}{{end}}' 2>/dev/null) if [ -n "$MOUNT_SOURCE" ]; then for suffix in "/.claude/.credentials.json" "/.credentials.json"; do @@ -241,16 +287,185 @@ if [ -z "$CLAUDE_CREDS_FILE" ]; then done fi +# --- Phase 2: If no credentials found, detect CLI and help user --- if [ -z "$CLAUDE_CREDS_FILE" ] || [ ! -f "$CLAUDE_CREDS_FILE" ]; then - warn "Could not auto-detect Claude CLI credentials" - CLAUDE_CREDS_FILE=$(ask "Enter path to Claude CLI .credentials.json") - if [ ! -f "$CLAUDE_CREDS_FILE" ]; then - error "File not found: $CLAUDE_CREDS_FILE" - exit 1 + warn "No Claude CLI credentials found" + echo "" + + # Detect if Claude CLI is installed + if [ -n "$CLAUDE_CONTAINER" ] && docker exec "$CLAUDE_CONTAINER" which claude &>/dev/null; then + CLI_INSTALLED=true + EARLY_CLI_MODE="container" + EARLY_CLI_CONTAINER="$CLAUDE_CONTAINER" + info "Claude Code CLI found in container: $CLAUDE_CONTAINER" + elif command -v claude &>/dev/null; then + CLI_INSTALLED=true + EARLY_CLI_MODE="host" + info "Claude Code CLI found on host: $(which claude)" + fi + + # --- CLI not installed: offer to install --- + if ! $CLI_INSTALLED; then + echo -e " ${BOLD}Claude Code CLI is not installed.${NC}" + echo " It's required for automatic OAuth token refresh." + echo "" + echo " Options:" + echo " 1) Install Claude Code CLI now (requires npm/Node.js)" + echo " 2) Show me the install instructions (exit wizard)" + echo " 3) Skip — I'll provide the credentials path manually" + CHOICE=$(ask "Select" "1") + case "$CHOICE" in + 1) + if command -v npm &>/dev/null; then + info "Installing Claude Code CLI via npm..." + npm install -g @anthropic-ai/claude-code 2>&1 | tail -5 + if command -v claude &>/dev/null; then + success "Claude Code CLI installed successfully" + CLI_INSTALLED=true + EARLY_CLI_MODE="host" + else + error "Installation failed. Check npm/Node.js setup." + fi + else + warn "npm not found. Node.js is required to install Claude Code CLI." + echo "" + echo " Install Node.js first:" + echo " curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -" + echo " apt install -y nodejs" + echo "" + if confirm " Install Node.js + Claude Code CLI now?" "N"; then + info "Installing Node.js LTS..." + curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - 2>&1 | tail -3 + apt-get install -y nodejs 2>&1 | tail -3 + if command -v npm &>/dev/null; then + info "Installing Claude Code CLI..." + npm install -g @anthropic-ai/claude-code 2>&1 | tail -5 + if command -v claude &>/dev/null; then + success "Claude Code CLI installed successfully" + CLI_INSTALLED=true + EARLY_CLI_MODE="host" + else + error "Claude CLI installation failed" + fi + else + error "Node.js installation failed" + fi + fi + fi + ;; + 2) + echo "" + info "Install Claude Code CLI:" + echo "" + echo " # Option A: npm (recommended)" + echo " npm install -g @anthropic-ai/claude-code" + echo "" + echo " # Option B: Run directly with npx" + echo " npx @anthropic-ai/claude-code" + echo "" + echo " # More info:" + echo " https://docs.anthropic.com/en/docs/claude-code" + echo "" + info "After installing and signing in, re-run: sudo ./setup.sh" + exit 0 + ;; + 3) + info "Continuing without Claude CLI..." + ;; + esac + fi + + # --- CLI installed but no credentials: offer sign-in --- + if $CLI_INSTALLED && ([ -z "$CLAUDE_CREDS_FILE" ] || [ ! -f "$CLAUDE_CREDS_FILE" ]); then + echo "" + warn "Claude Code CLI is installed but not signed in (no OAuth credentials)." + info "You need to authenticate with your Claude Max subscription." + info "This will open an OAuth flow — you'll get a URL to visit in your browser." + echo "" + if confirm " Launch Claude CLI now to sign in?" "Y"; then + echo "" + echo -e " ${BOLD}Complete the OAuth sign-in in your browser.${NC}" + echo -e " ${BOLD}After signing in, press Ctrl+C or type /exit to return here.${NC}" + echo "" + if [ "$EARLY_CLI_MODE" = "container" ]; then + docker exec -it "$EARLY_CLI_CONTAINER" claude || true + else + claude || true + fi + echo "" + info "Checking for credentials after sign-in..." + + # Re-search for credentials + for path in \ + /root/.claude/.credentials.json \ + "$HOME/.claude/.credentials.json"; do + if [ -f "$path" ]; then + CLAUDE_CREDS_FILE="$path" + break + fi + done + + # Also check container mounts again + if [ -z "$CLAUDE_CREDS_FILE" ] && [ -n "$CLAUDE_CONTAINER" ]; then + MOUNT_SOURCE=$(docker inspect "$CLAUDE_CONTAINER" --format '{{range .Mounts}}{{if or (eq .Destination "/root") (eq .Destination "/root/.claude") (eq .Destination "/home/node/.claude")}}{{.Source}}{{end}}{{end}}' 2>/dev/null) + if [ -n "$MOUNT_SOURCE" ]; then + for suffix in "/.claude/.credentials.json" "/.credentials.json"; do + if [ -f "${MOUNT_SOURCE}${suffix}" ]; then + CLAUDE_CREDS_FILE="${MOUNT_SOURCE}${suffix}" + break + fi + done + fi + fi + fi + fi + + # --- Last resort: ask for manual path --- + if [ -z "$CLAUDE_CREDS_FILE" ] || [ ! -f "$CLAUDE_CREDS_FILE" ]; then + echo "" + warn "Could not find credentials automatically." + CLAUDE_CREDS_FILE=$(ask "Enter path to .credentials.json (or 'quit' to exit)") + if [ "$CLAUDE_CREDS_FILE" = "quit" ] || [ "$CLAUDE_CREDS_FILE" = "q" ]; then + echo "" + info "To set up credentials:" + info " 1. Install Claude Code CLI: npm install -g @anthropic-ai/claude-code" + info " 2. Sign in: claude" + info " 3. Re-run this wizard: sudo ./setup.sh" + exit 1 + fi + if [ ! -f "$CLAUDE_CREDS_FILE" ]; then + error "File not found: $CLAUDE_CREDS_FILE" + exit 1 + fi fi fi -# Validate credentials +# --- Phase 3: Validate credentials --- +HAS_OAUTH=$(python3 -c " +import json +with open('$CLAUDE_CREDS_FILE') as f: + d = json.load(f) +oauth = d.get('claudeAiOauth', {}) +print('yes' if oauth.get('accessToken') else 'no') +" 2>/dev/null || echo "no") + +if [ "$HAS_OAUTH" != "yes" ]; then + error "Credentials file exists but contains no OAuth tokens." + info "Claude CLI may not be signed in with a Claude Max subscription." + echo "" + if $CLI_INSTALLED; then + info "Sign in to Claude CLI and re-run this wizard:" + info " claude # sign in with OAuth" + info " sudo ./setup.sh # re-run wizard" + else + info "Install Claude Code CLI, sign in, and re-run:" + info " npm install -g @anthropic-ai/claude-code" + info " claude # sign in with OAuth" + info " sudo ./setup.sh # re-run wizard" + fi + exit 1 +fi + TOKEN_INFO=$(python3 -c " import json, time with open('$CLAUDE_CREDS_FILE') as f: @@ -850,3 +1065,5 @@ fi echo " ./scripts/verify.sh # Health check" echo " ./setup.sh --uninstall # Remove everything" echo "" +echo -e " ${DIM}Created by ROOH — www.rooh.red${NC}" +echo ""