refactor: перенос файлов в claude/ + мульти-продуктовая структура
- Все claude-файлы перенесены в claude/ (uclaude_updater.py, скрипты, config) - claude/README.md с инструкцией для Claude Code - Корневой README — общий для всех продуктов (claude, codex, gemini, qwen, antigravity) - Node.js v24.13+ автоустановка через nodesource - Sparse checkout: клиент скачивает только latest версию cli.js Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
102
README.md
102
README.md
@@ -1,92 +1,36 @@
|
||||
# Unlimited Coding — Claude Code Patches
|
||||
# Unlimited Coding
|
||||
|
||||
Patched Claude Code CLI for use with custom API endpoints. Automatic updater included.
|
||||
Patched AI coding tools for use with custom API endpoints.
|
||||
|
||||
## Products
|
||||
|
||||
| Folder | Tool | Status |
|
||||
|--------|------|--------|
|
||||
| [claude/](claude/) | Claude Code | Active |
|
||||
| codex/ | OpenAI Codex CLI | Planned |
|
||||
| gemini/ | Gemini CLI | Planned |
|
||||
| qwen/ | Qwen Code | Planned |
|
||||
| antigravity/ | Antigravity | Planned |
|
||||
|
||||
## Quick Start
|
||||
|
||||
### First Install
|
||||
See README in each product folder for installation instructions.
|
||||
|
||||
### Claude Code
|
||||
|
||||
```bash
|
||||
# 1. Install Claude Code (if not installed)
|
||||
npm install -g @anthropic-ai/claude-code
|
||||
bash <(curl -s https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/claude/uclaude_install.sh)
|
||||
```
|
||||
|
||||
# 2. Clone and install (one command — downloads only latest version)
|
||||
bash <(curl -s https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/uclaude_install.sh)
|
||||
|
||||
# Or manually:
|
||||
git clone --depth 1 --no-checkout https://git.sensey24.ru/aibot777/unlimitedcoding.git
|
||||
Or manually:
|
||||
```bash
|
||||
git clone --depth 1 https://git.sensey24.ru/aibot777/unlimitedcoding.git
|
||||
cd unlimitedcoding
|
||||
git sparse-checkout set '/*' 'claude/releases/index.json'
|
||||
git checkout
|
||||
# Read latest version from index, then checkout only that version:
|
||||
VER=$(python3 -c "import json; print(json.load(open('claude/releases/index.json'))['latest'])")
|
||||
git sparse-checkout add "claude/releases/v${VER}"
|
||||
git checkout
|
||||
sudo python3 uclaude_updater.py --force
|
||||
```
|
||||
|
||||
### Update
|
||||
|
||||
```bash
|
||||
cd unlimitedcoding
|
||||
sudo bash uclaude_update.sh
|
||||
```
|
||||
|
||||
The updater will automatically:
|
||||
- Pull latest releases from the repo
|
||||
- Detect installed Claude Code version
|
||||
- Install the latest patched cli.js (with backup)
|
||||
- Configure settings for all users on the system
|
||||
|
||||
### Check for Updates (without installing)
|
||||
|
||||
```bash
|
||||
cd unlimitedcoding
|
||||
bash uclaude_update.sh --check
|
||||
```
|
||||
|
||||
### Other Options
|
||||
|
||||
```bash
|
||||
sudo bash uclaude_update.sh --force # Force reinstall even if up to date
|
||||
sudo bash uclaude_update.sh --settings-only # Only update settings, don't touch cli.js
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```cmd
|
||||
uclaude_update.bat
|
||||
```
|
||||
or PowerShell:
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File uclaude_update.ps1
|
||||
```
|
||||
|
||||
## What's Patched (15 patches)
|
||||
|
||||
- Custom API endpoint support (base URL, auth token, models)
|
||||
- Auth/OAuth bypass for custom endpoints
|
||||
- Telemetry disabled (Datadog, Segment)
|
||||
- Permission prompts auto-accepted
|
||||
- Root/sudo check removed
|
||||
- Custom model picker with configurable model list
|
||||
|
||||
## What's Inside
|
||||
|
||||
```
|
||||
uclaude_updater.py — main updater script
|
||||
uclaude_update.sh — Linux/macOS wrapper (git pull + run updater)
|
||||
uclaude_update.bat — Windows CMD wrapper
|
||||
uclaude_update.ps1 — Windows PowerShell wrapper
|
||||
patcher.config.json — API endpoint configuration
|
||||
claude/releases/ — patched cli.js files per version
|
||||
index.json — version index (latest, release list)
|
||||
v2.1.50/cli.js — patched CLI for v2.1.50
|
||||
sudo bash claude/uclaude_update.sh --force
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js 18+
|
||||
- Claude Code (`npm install -g @anthropic-ai/claude-code`)
|
||||
- Python 3
|
||||
- Git
|
||||
- Python 3
|
||||
- Node.js v24.13+ (auto-installed if missing/outdated)
|
||||
|
||||
61
claude/README.md
Normal file
61
claude/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Claude Code — Patched CLI
|
||||
|
||||
Patched Claude Code CLI for use with custom API endpoints. 15 patches applied.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js v24.13+ ([nodejs.org](https://nodejs.org/)) — updater will auto-install if missing or outdated
|
||||
- Python 3
|
||||
- Git
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
# Install Claude Code
|
||||
npm install -g @anthropic-ai/claude-code
|
||||
|
||||
# One-line install (from repo root):
|
||||
sudo bash claude/uclaude_update.sh --force
|
||||
```
|
||||
|
||||
## Update
|
||||
|
||||
```bash
|
||||
sudo bash claude/uclaude_update.sh
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
```bash
|
||||
sudo bash claude/uclaude_update.sh --check # check for updates
|
||||
sudo bash claude/uclaude_update.sh --force # force reinstall
|
||||
sudo bash claude/uclaude_update.sh --settings-only # only patch settings
|
||||
```
|
||||
|
||||
## Windows
|
||||
|
||||
```cmd
|
||||
claude\uclaude_update.bat
|
||||
```
|
||||
|
||||
## What's Patched
|
||||
|
||||
- Custom API endpoint (base URL, auth token)
|
||||
- Custom model picker (configurable model list)
|
||||
- Auth/OAuth bypass for custom endpoints
|
||||
- Telemetry disabled (Datadog, Segment)
|
||||
- Permission prompts auto-accepted
|
||||
- Root/sudo check removed
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `uclaude_updater.py` | Main updater — version check, cli.js install, settings patch |
|
||||
| `uclaude_update.sh` | Linux/macOS wrapper |
|
||||
| `uclaude_update.bat` | Windows CMD wrapper |
|
||||
| `uclaude_update.ps1` | Windows PowerShell wrapper |
|
||||
| `uclaude_install.sh` | One-line installer (curl-friendly) |
|
||||
| `patcher.config.json` | API endpoint config (base_url, api_key, models) |
|
||||
| `releases/index.json` | Version index |
|
||||
| `releases/v*/cli.js` | Patched cli.js per version |
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
# UClaude — one-line installer
|
||||
# Usage: bash <(curl -s https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/uclaude_install.sh)
|
||||
# Or: curl -s URL | bash
|
||||
# Usage: bash <(curl -s https://git.sensey24.ru/aibot777/unlimitedcoding/raw/branch/master/claude/uclaude_install.sh)
|
||||
set -e
|
||||
|
||||
REPO_URL="https://git.sensey24.ru/aibot777/unlimitedcoding.git"
|
||||
@@ -13,7 +12,8 @@ echo " Install dir: $INSTALL_DIR"
|
||||
# Check prerequisites
|
||||
command -v git >/dev/null 2>&1 || { echo "ERROR: git not found. Install git first."; exit 1; }
|
||||
command -v python3 >/dev/null 2>&1 || { echo "ERROR: python3 not found. Install Python 3 first."; exit 1; }
|
||||
command -v node >/dev/null 2>&1 || { echo "ERROR: node not found. Install Node.js 18+ first."; exit 1; }
|
||||
# Node.js check — will be auto-installed by updater if needed
|
||||
command -v node >/dev/null 2>&1 || echo "WARNING: node not found. Updater will attempt auto-install."
|
||||
|
||||
if [ -d "$INSTALL_DIR/.git" ]; then
|
||||
echo " Already cloned, updating..."
|
||||
@@ -27,12 +27,12 @@ else
|
||||
git clone --depth 1 --no-checkout "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
|
||||
# Enable sparse checkout: root files + index.json only (first pass)
|
||||
# Enable sparse checkout: root + claude core files + index.json (first pass)
|
||||
git sparse-checkout init --no-cone
|
||||
git sparse-checkout set '/*' 'claude/releases/index.json'
|
||||
git sparse-checkout set '/*' 'claude/*' '!claude/releases/v*' 'claude/releases/index.json'
|
||||
git checkout 2>/dev/null
|
||||
|
||||
# Now read latest version from index.json and add that release dir
|
||||
# Read latest version from index.json and add only that release dir
|
||||
if [ -f claude/releases/index.json ]; then
|
||||
VER=$(python3 -c "import json; print(json.load(open('claude/releases/index.json'))['latest'])")
|
||||
echo " Latest version: v${VER}"
|
||||
@@ -46,12 +46,12 @@ echo " Running updater..."
|
||||
|
||||
# Run updater (needs root for cli.js replacement)
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
python3 uclaude_updater.py --force
|
||||
python3 claude/uclaude_updater.py --force
|
||||
else
|
||||
echo " Root privileges required to install cli.js."
|
||||
sudo python3 uclaude_updater.py --force
|
||||
sudo python3 claude/uclaude_updater.py --force
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Installation complete ==="
|
||||
echo " To update later: cd $INSTALL_DIR && sudo bash uclaude_update.sh"
|
||||
echo " To update later: cd $INSTALL_DIR && sudo bash claude/uclaude_update.sh"
|
||||
@@ -1,16 +1,16 @@
|
||||
@echo off
|
||||
REM UClaude Updater — automatic Claude Code patch updater
|
||||
REM Usage: uclaude_update.bat [--check] [--force] [--settings-only]
|
||||
REM Usage: claude\uclaude_update.bat [--check] [--force] [--settings-only]
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
cd /d "%SCRIPT_DIR%"
|
||||
cd /d "%SCRIPT_DIR%\.."
|
||||
|
||||
REM Pull latest artifacts
|
||||
git pull --quiet 2>nul
|
||||
|
||||
REM Run updater
|
||||
python uclaude_updater.py %*
|
||||
python claude\uclaude_updater.py %*
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo If you see permission errors, run this script as Administrator.
|
||||
@@ -1,9 +1,10 @@
|
||||
# UClaude Updater — automatic Claude Code patch updater
|
||||
# Usage: powershell -ExecutionPolicy Bypass -File uclaude_update.ps1 [--check] [--force] [--settings-only]
|
||||
# Usage: powershell -ExecutionPolicy Bypass -File claude\uclaude_update.ps1 [--check] [--force] [--settings-only]
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
Set-Location $ScriptDir
|
||||
$RepoRoot = Split-Path -Parent $ScriptDir
|
||||
Set-Location $RepoRoot
|
||||
|
||||
# Pull latest artifacts
|
||||
git pull --quiet 2>$null
|
||||
@@ -17,4 +18,4 @@ if (-not $isAdmin) {
|
||||
}
|
||||
|
||||
# Run updater
|
||||
& python uclaude_updater.py @args
|
||||
& python claude\uclaude_updater.py @args
|
||||
@@ -1,10 +1,11 @@
|
||||
#!/bin/bash
|
||||
# UClaude Updater — automatic Claude Code patch updater
|
||||
# Usage: sudo bash uclaude_update.sh [--check] [--force] [--settings-only]
|
||||
# Usage: sudo bash claude/uclaude_update.sh [--check] [--force] [--settings-only]
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Fetch latest commit (shallow — no history)
|
||||
git fetch --depth 1 origin master 2>/dev/null && git reset --hard origin/master 2>/dev/null || git pull --quiet 2>/dev/null || true
|
||||
@@ -20,8 +21,8 @@ fi
|
||||
|
||||
# Run updater
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
python3 uclaude_updater.py "$@"
|
||||
python3 claude/uclaude_updater.py "$@"
|
||||
else
|
||||
echo "Root privileges required. Re-running with sudo..."
|
||||
sudo python3 uclaude_updater.py "$@"
|
||||
sudo python3 claude/uclaude_updater.py "$@"
|
||||
fi
|
||||
@@ -30,7 +30,8 @@ try:
|
||||
except ImportError:
|
||||
HAS_PWD = False
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) # claude/
|
||||
REPO_ROOT = os.path.dirname(SCRIPT_DIR) # unlimitedcoding/
|
||||
|
||||
# ANSI colors
|
||||
G = "\033[92m" # green
|
||||
@@ -68,6 +69,82 @@ def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Node.js check and auto-install
|
||||
# ============================================================
|
||||
|
||||
MIN_NODE_VERSION = (24, 13, 0)
|
||||
|
||||
|
||||
def get_node_version():
|
||||
"""Get installed Node.js version as tuple, or None."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["node", "--version"],
|
||||
capture_output=True, text=True, timeout=10,
|
||||
)
|
||||
m = re.match(r"v?(\d+)\.(\d+)\.(\d+)", result.stdout.strip())
|
||||
if m:
|
||||
return (int(m.group(1)), int(m.group(2)), int(m.group(3)))
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired):
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def install_node():
|
||||
"""Auto-install Node.js v24+ using the official nodesource setup."""
|
||||
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}")
|
||||
return False
|
||||
|
||||
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,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
ver = get_node_version()
|
||||
if ver:
|
||||
print(f" {G}Node.js v{'.'.join(map(str, ver))} installed{D}")
|
||||
return True
|
||||
|
||||
# Fallback: try nvm-like approach or direct download
|
||||
eprint(f" {R}Auto-install failed. Install manually: https://nodejs.org/{D}")
|
||||
if result.stderr:
|
||||
eprint(f" {result.stderr.strip()[:200]}")
|
||||
return False
|
||||
except Exception as e:
|
||||
eprint(f" {R}Auto-install error: {e}{D}")
|
||||
return False
|
||||
|
||||
|
||||
def ensure_node():
|
||||
"""Check Node.js version, auto-install/update if needed. Returns True if OK."""
|
||||
ver = get_node_version()
|
||||
|
||||
if ver is None:
|
||||
print(f" {Y}Node.js not found.{D}")
|
||||
if is_admin():
|
||||
return install_node()
|
||||
else:
|
||||
eprint(f" {R}Install Node.js v{'.'.join(map(str, MIN_NODE_VERSION))}+: https://nodejs.org/{D}")
|
||||
return False
|
||||
|
||||
if ver < MIN_NODE_VERSION:
|
||||
print(f" {Y}Node.js v{'.'.join(map(str, ver))} found, need v{'.'.join(map(str, MIN_NODE_VERSION))}+{D}")
|
||||
if is_admin():
|
||||
return install_node()
|
||||
else:
|
||||
eprint(f" {R}Update Node.js: https://nodejs.org/{D}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Version detection
|
||||
# ============================================================
|
||||
@@ -126,7 +203,7 @@ def get_installed_version():
|
||||
|
||||
def get_latest_version():
|
||||
"""Read latest version from local index.json."""
|
||||
index_path = os.path.join(SCRIPT_DIR, "claude", "releases", "index.json")
|
||||
index_path = os.path.join(SCRIPT_DIR, "releases", "index.json")
|
||||
if not os.path.isfile(index_path):
|
||||
return None
|
||||
try:
|
||||
@@ -153,13 +230,13 @@ def git_pull():
|
||||
# Shallow fetch + reset — downloads only latest commit, not full history
|
||||
result = subprocess.run(
|
||||
["git", "fetch", "--depth", "1", "origin", "master"],
|
||||
cwd=SCRIPT_DIR, capture_output=True, text=True, timeout=60,
|
||||
cwd=REPO_ROOT, capture_output=True, text=True, timeout=60,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
# Fallback to regular pull
|
||||
result = subprocess.run(
|
||||
["git", "pull", "--quiet"],
|
||||
cwd=SCRIPT_DIR, capture_output=True, text=True, timeout=60,
|
||||
cwd=REPO_ROOT, capture_output=True, text=True, timeout=60,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
eprint(f" {Y}git pull warning: {result.stderr.strip()}{D}")
|
||||
@@ -168,7 +245,7 @@ def git_pull():
|
||||
# Reset to fetched state
|
||||
subprocess.run(
|
||||
["git", "reset", "--hard", "origin/master"],
|
||||
cwd=SCRIPT_DIR, capture_output=True, text=True, timeout=10,
|
||||
cwd=REPO_ROOT, capture_output=True, text=True, timeout=10,
|
||||
)
|
||||
|
||||
# Setup sparse checkout to download only latest version's cli.js
|
||||
@@ -189,7 +266,7 @@ def _setup_sparse_checkout():
|
||||
This avoids downloading cli.js for ALL versions (each ~12MB).
|
||||
Only the latest version's cli.js is checked out.
|
||||
"""
|
||||
index_path = os.path.join(SCRIPT_DIR, "claude", "releases", "index.json")
|
||||
index_path = os.path.join(SCRIPT_DIR, "releases", "index.json")
|
||||
if not os.path.isfile(index_path):
|
||||
return
|
||||
|
||||
@@ -205,10 +282,10 @@ def _setup_sparse_checkout():
|
||||
# Enable sparse checkout
|
||||
subprocess.run(
|
||||
["git", "config", "core.sparseCheckout", "true"],
|
||||
cwd=SCRIPT_DIR, capture_output=True,
|
||||
cwd=REPO_ROOT, capture_output=True,
|
||||
)
|
||||
|
||||
sparse_file = os.path.join(SCRIPT_DIR, ".git", "info", "sparse-checkout")
|
||||
sparse_file = os.path.join(REPO_ROOT, ".git", "info", "sparse-checkout")
|
||||
os.makedirs(os.path.dirname(sparse_file), exist_ok=True)
|
||||
|
||||
patterns = [
|
||||
@@ -223,7 +300,7 @@ def _setup_sparse_checkout():
|
||||
# Apply sparse checkout
|
||||
subprocess.run(
|
||||
["git", "checkout", "HEAD", "--", "."],
|
||||
cwd=SCRIPT_DIR, capture_output=True, timeout=30,
|
||||
cwd=REPO_ROOT, capture_output=True, timeout=30,
|
||||
)
|
||||
|
||||
|
||||
@@ -233,7 +310,7 @@ def _setup_sparse_checkout():
|
||||
|
||||
def install_cli_js(version, cli_js_path):
|
||||
"""Install patched cli.js for the given version."""
|
||||
release_cli = os.path.join(SCRIPT_DIR, "claude", "releases", f"v{version}", "cli.js")
|
||||
release_cli = os.path.join(SCRIPT_DIR, "releases", f"v{version}", "cli.js")
|
||||
if not os.path.isfile(release_cli):
|
||||
eprint(f" {R}Release cli.js not found: {release_cli}{D}")
|
||||
return False
|
||||
@@ -529,10 +606,14 @@ def cmd_check():
|
||||
|
||||
def cmd_update(force=False, settings_only=False):
|
||||
"""Full update: git pull → install cli.js → patch settings."""
|
||||
installed, cli_js = get_installed_version()
|
||||
|
||||
print(f"\n{W}=== UClaude Updater ==={D}")
|
||||
|
||||
# Check Node.js version
|
||||
if not ensure_node():
|
||||
return 1
|
||||
|
||||
installed, cli_js = get_installed_version()
|
||||
|
||||
# Git pull to get latest artifacts
|
||||
print(f"\n Pulling latest updates...")
|
||||
git_pull()
|
||||
Reference in New Issue
Block a user