Improve wizard UX: CLI install/sign-in flow, user-controlled installs, ROOH credit

- Add ROOH credit (www.rooh.red) to banner, summary, and README
- Step 1: Offer to install python3 and curl instead of hard-failing
- Step 3: Detect missing Claude CLI and offer to install via npm
- Step 3: Detect not-signed-in CLI and offer interactive OAuth sign-in
- Step 3: Provide clear instructions and exit paths at every decision point
- Update README with correct git clone URL and wizard capabilities
- All install steps now require user confirmation before proceeding

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shamid202 2026-02-27 02:08:50 +07:00
parent 22731fff60
commit 32a4e739dc
2 changed files with 255 additions and 28 deletions

View File

@ -1,5 +1,7 @@
# OAuth Fix for OpenClaw + Claude Max # 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. Automatic Anthropic OAuth token refresh for OpenClaw. Keeps your Claude Max tokens alive indefinitely.
## The Problem ## The Problem
@ -26,19 +28,22 @@ Timer (every 30min) Claude Code CLI sync-oauth-token.sh Op
## Quick Start ## Quick Start
```bash ```bash
git clone https://github.com/YOUR_USER/oauth-fix-openclaw-final.git git clone https://git.eeqj.de/ROOH/openclaw_oauth_sync.git
cd oauth-fix-openclaw-final cd openclaw_oauth_sync
sudo ./setup.sh sudo ./setup.sh
``` ```
The interactive wizard will: The interactive wizard will:
1. Detect your OpenClaw installation paths 1. Check prerequisites (offers to install python3, curl, inotify-tools if missing)
2. Find Claude CLI credentials 2. Detect your OpenClaw installation paths
3. Configure the Anthropic model (if not already set up) 3. Find Claude CLI credentials (offers to install CLI and help with sign-in if needed)
4. Install the token sync watcher (inotifywait) 4. Configure the Anthropic model (if not already set up)
5. Detect Claude CLI (container or host) and install the auto-refresh trigger 5. Install the token sync watcher (inotifywait or timer fallback)
6. Test the CLI invocation to confirm it works 6. Detect Claude CLI (container or host) and install the auto-refresh trigger
7. Verify everything works 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 ## Prerequisites
@ -46,9 +51,10 @@ The interactive wizard will:
- **Docker** + **Docker Compose v2** - **Docker** + **Docker Compose v2**
- **OpenClaw** installed and running - **OpenClaw** installed and running
- **Claude Max subscription** with OAuth credentials - **Claude Max subscription** with OAuth credentials
- **Claude Code CLI** — either in a Docker container or installed on the host - **Claude Code CLI** — either in a Docker container or installed on the host (wizard can install it)
- **python3** - **python3** (wizard offers to install if missing)
- **inotify-tools** (optional, installed by wizard if missing) - **curl** (wizard offers to install if missing)
- **inotify-tools** (optional, wizard offers to install if missing)
## How It Works ## 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 - [Token Refresh](docs/HOW-TOKEN-REFRESH-WORKS.md) — How Claude CLI refreshes tokens
- [Field Mapping](docs/FIELD-MAPPING.md) — Credential format reference - [Field Mapping](docs/FIELD-MAPPING.md) — Credential format reference
## Author
**ROOH** — [www.rooh.red](https://www.rooh.red)
## License ## License
MIT MIT

243
setup.sh
View File

@ -68,6 +68,8 @@ echo " ╔═══════════════════════
echo " ║ OAuth Fix for OpenClaw + Claude Max ║" echo " ║ OAuth Fix for OpenClaw + Claude Max ║"
echo " ║ Automatic Anthropic Token Refresh ║" echo " ║ Automatic Anthropic Token Refresh ║"
echo " ║ v${VERSION}" echo " ║ v${VERSION}"
echo " ║ ║"
echo " ║ Created by ROOH — www.rooh.red ║"
echo " ╚══════════════════════════════════════════════════════╝" echo " ╚══════════════════════════════════════════════════════╝"
echo -e "${NC}" echo -e "${NC}"
echo -e "${DIM} Keeps your Anthropic OAuth tokens fresh by syncing" echo -e "${DIM} Keeps your Anthropic OAuth tokens fresh by syncing"
@ -81,11 +83,12 @@ header "Step 1: Checking Prerequisites"
MISSING=0 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 if command -v "$cmd" &>/dev/null; then
success "$cmd found" success "$cmd found"
else else
error "$cmd not found" error "$cmd not found — required, cannot be installed by this wizard"
MISSING=$((MISSING + 1)) MISSING=$((MISSING + 1))
fi fi
done done
@ -94,19 +97,57 @@ done
if docker compose version &>/dev/null; then if docker compose version &>/dev/null; then
success "docker compose found ($(docker compose version --short 2>/dev/null || echo 'v2'))" success "docker compose found ($(docker compose version --short 2>/dev/null || echo 'v2'))"
else else
error "docker compose v2 not found" error "docker compose v2 not found — required"
MISSING=$((MISSING + 1)) MISSING=$((MISSING + 1))
fi 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 if command -v inotifywait &>/dev/null; then
success "inotifywait found" success "inotifywait found"
USE_INOTIFY=true USE_INOTIFY=true
else else
warn "inotifywait not found (inotify-tools package)" 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 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 if command -v inotifywait &>/dev/null; then
success "inotifywait installed" success "inotifywait installed"
USE_INOTIFY=true USE_INOTIFY=true
@ -197,17 +238,22 @@ OPENCLAW_OAUTH_FILE="$OPENCLAW_CONFIG_DIR/credentials/oauth.json"
success "OAuth file: $OPENCLAW_OAUTH_FILE" 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="" 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) CLAUDE_CONTAINER=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -i 'claude' | head -1)
if [ -n "$CLAUDE_CONTAINER" ]; then if [ -n "$CLAUDE_CONTAINER" ]; then
info "Found Claude container: $CLAUDE_CONTAINER" 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) 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 if [ -n "$MOUNT_SOURCE" ]; then
for suffix in "/.claude/.credentials.json" "/.credentials.json"; do for suffix in "/.claude/.credentials.json" "/.credentials.json"; do
@ -241,16 +287,185 @@ if [ -z "$CLAUDE_CREDS_FILE" ]; then
done done
fi fi
# --- Phase 2: If no credentials found, detect CLI and help user ---
if [ -z "$CLAUDE_CREDS_FILE" ] || [ ! -f "$CLAUDE_CREDS_FILE" ]; then if [ -z "$CLAUDE_CREDS_FILE" ] || [ ! -f "$CLAUDE_CREDS_FILE" ]; then
warn "Could not auto-detect Claude CLI credentials" warn "No Claude CLI credentials found"
CLAUDE_CREDS_FILE=$(ask "Enter path to Claude CLI .credentials.json") 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 if [ ! -f "$CLAUDE_CREDS_FILE" ]; then
error "File not found: $CLAUDE_CREDS_FILE" error "File not found: $CLAUDE_CREDS_FILE"
exit 1 exit 1
fi fi
fi
fi
# --- 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 fi
# Validate credentials
TOKEN_INFO=$(python3 -c " TOKEN_INFO=$(python3 -c "
import json, time import json, time
with open('$CLAUDE_CREDS_FILE') as f: with open('$CLAUDE_CREDS_FILE') as f:
@ -850,3 +1065,5 @@ fi
echo " ./scripts/verify.sh # Health check" echo " ./scripts/verify.sh # Health check"
echo " ./setup.sh --uninstall # Remove everything" echo " ./setup.sh --uninstall # Remove everything"
echo "" echo ""
echo -e " ${DIM}Created by ROOH — www.rooh.red${NC}"
echo ""