feat: full auto-install chain for all platforms
- Wire ensure_claude_code() into cmd_update() — auto npm install if missing - uclaude_install.sh: auto-install git, python3, curl via apt/dnf/yum/brew - uclaude_update.bat: prereq checks with winget install suggestions - uclaude_update.ps1: auto-install via winget (git, python, node) - install_node(): macOS support via brew, RHEL/Fedora via rpm.nodesource - Increased npm install timeout to 300s for slow connections
This commit is contained in:
@@ -92,16 +92,34 @@ def get_node_version():
|
||||
|
||||
|
||||
def install_node():
|
||||
"""Auto-install Node.js v24+ using the official nodesource setup."""
|
||||
"""Auto-install Node.js v24+ using the official nodesource setup (Linux) or brew (macOS)."""
|
||||
print(f" {Y}Node.js v{'.'.join(map(str, MIN_NODE_VERSION))}+ required.{D}")
|
||||
|
||||
if IS_WINDOWS:
|
||||
print(f" {R}Please install Node.js manually: https://nodejs.org/{D}")
|
||||
print(f" Or run: winget install OpenJS.NodeJS")
|
||||
return False
|
||||
|
||||
if IS_MACOS:
|
||||
print(f" Installing Node.js via Homebrew...")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["brew", "install", "node"],
|
||||
timeout=120, capture_output=True, text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
ver = get_node_version()
|
||||
if ver and ver >= MIN_NODE_VERSION:
|
||||
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
eprint(f" {R}Install Homebrew first: https://brew.sh/ then: brew install node{D}")
|
||||
return False
|
||||
|
||||
# Linux — nodesource
|
||||
print(f" Installing Node.js v24 via nodesource...")
|
||||
try:
|
||||
# Use nodesource setup script
|
||||
result = subprocess.run(
|
||||
["bash", "-c", "curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && apt-get install -y nodejs"],
|
||||
timeout=120, capture_output=True, text=True,
|
||||
@@ -112,7 +130,20 @@ def install_node():
|
||||
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
||||
return True
|
||||
|
||||
# Fallback: try nvm-like approach or direct download
|
||||
# Try dnf/yum fallback for RHEL/Fedora
|
||||
for pkg_mgr in ["dnf", "yum"]:
|
||||
if shutil.which(pkg_mgr):
|
||||
result = subprocess.run(
|
||||
["bash", "-c", f"curl -fsSL https://rpm.nodesource.com/setup_24.x | bash - && {pkg_mgr} install -y nodejs"],
|
||||
timeout=120, capture_output=True, text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
ver = get_node_version()
|
||||
if ver:
|
||||
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
||||
return True
|
||||
break
|
||||
|
||||
eprint(f" {R}Auto-install failed. Install manually: https://nodejs.org/{D}")
|
||||
if result.stderr:
|
||||
eprint(f" {result.stderr.strip()[:200]}")
|
||||
@@ -145,6 +176,43 @@ def ensure_node():
|
||||
return True
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Claude Code auto-install
|
||||
# ============================================================
|
||||
|
||||
def ensure_claude_code():
|
||||
"""Install Claude Code via npm if not present. Returns True if OK."""
|
||||
cli_js = find_cli_js()
|
||||
if cli_js:
|
||||
return True
|
||||
|
||||
print(f" {Y}Claude Code not found. Installing via npm...{D}")
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["npm", "install", "-g", "@anthropic-ai/claude-code"],
|
||||
capture_output=True, text=True, timeout=300,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
cli_js = find_cli_js()
|
||||
if cli_js:
|
||||
print(f" {G}Claude Code installed{D}")
|
||||
return True
|
||||
|
||||
eprint(f" {R}npm install failed{D}")
|
||||
if result.stderr:
|
||||
eprint(f" {result.stderr.strip()[:300]}")
|
||||
return False
|
||||
except FileNotFoundError:
|
||||
eprint(f" {R}npm not found. Install Node.js first.{D}")
|
||||
return False
|
||||
except subprocess.TimeoutExpired:
|
||||
eprint(f" {R}npm install timed out{D}")
|
||||
return False
|
||||
except Exception as e:
|
||||
eprint(f" {R}Error: {e}{D}")
|
||||
return False
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Version detection
|
||||
# ============================================================
|
||||
@@ -589,7 +657,7 @@ def cmd_check():
|
||||
print(f" Latest: {latest or 'unknown'}")
|
||||
|
||||
if not installed:
|
||||
print(f" {Y}Claude Code not found. Install it first: npm install -g @anthropic-ai/claude-code{D}")
|
||||
print(f" {Y}Claude Code not found. Run without --check to auto-install.{D}")
|
||||
return 1
|
||||
|
||||
if not latest:
|
||||
@@ -612,6 +680,11 @@ def cmd_update(force=False, settings_only=False):
|
||||
if not ensure_node():
|
||||
return 1
|
||||
|
||||
# Ensure Claude Code is installed (npm install if missing)
|
||||
if not settings_only:
|
||||
if not ensure_claude_code():
|
||||
return 1
|
||||
|
||||
installed, cli_js = get_installed_version()
|
||||
|
||||
# Git pull to get latest artifacts
|
||||
@@ -642,7 +715,7 @@ def cmd_update(force=False, settings_only=False):
|
||||
if not cli_js:
|
||||
cli_js = find_cli_js()
|
||||
if not cli_js:
|
||||
eprint(f" {R}Claude Code cli.js not found. Install Claude Code first.{D}")
|
||||
eprint(f" {R}Claude Code cli.js not found even after install attempt.{D}")
|
||||
return 1
|
||||
|
||||
if not is_admin():
|
||||
|
||||
Reference in New Issue
Block a user