mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-21 21:15:09 +00:00
feat: add auto-start on boot and restructure README (v1.5.0)
- setup.mjs: install launchd plist (macOS) or systemd user service (Linux) after proxy starts; logs to ~/.openclaw/logs/proxy.log - Add uninstall.mjs to stop and remove the auto-start entry - README: Quick Start (Node.js) first, Security section, Docker moved to Server/Advanced - Bump version to 1.5.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,33 +26,13 @@ The proxy translates OpenAI-compatible `/v1/chat/completions` requests into `cla
|
|||||||
- **Claude CLI** installed and authenticated (`claude login`)
|
- **Claude CLI** installed and authenticated (`claude login`)
|
||||||
- **OpenClaw** installed
|
- **OpenClaw** installed
|
||||||
|
|
||||||
## Quick Install
|
## Quick Start (Node.js)
|
||||||
|
|
||||||
### Docker (recommended)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git
|
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git
|
||||||
cd openclaw-claude-proxy
|
cd openclaw-claude-proxy
|
||||||
cp .env.example .env # add your CLAUDE_SESSION_TOKEN / CLAUDE_COOKIES
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
Or as a single command if you already have a `.env` ready:
|
# Auto-configure OpenClaw + start proxy + install auto-start
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git && cd openclaw-claude-proxy && docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
Health check: `curl http://localhost:3456/health`
|
|
||||||
|
|
||||||
### Node.js (local)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Clone
|
|
||||||
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git
|
|
||||||
cd openclaw-claude-proxy
|
|
||||||
|
|
||||||
# Auto-configure OpenClaw + start proxy
|
|
||||||
node setup.mjs
|
node setup.mjs
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -61,6 +41,7 @@ That's it. The setup script will:
|
|||||||
2. Add `claude-local` provider to `openclaw.json`
|
2. Add `claude-local` provider to `openclaw.json`
|
||||||
3. Add auth profiles to all agents
|
3. Add auth profiles to all agents
|
||||||
4. Start the proxy
|
4. Start the proxy
|
||||||
|
5. Install auto-start on login (launchd on macOS, systemd on Linux)
|
||||||
|
|
||||||
Then set your preferred Claude model as default:
|
Then set your preferred Claude model as default:
|
||||||
```bash
|
```bash
|
||||||
@@ -68,6 +49,17 @@ openclaw config set agents.defaults.model.primary "claude-local/claude-opus-4-6"
|
|||||||
openclaw gateway restart
|
openclaw gateway restart
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- **Localhost only** — the proxy binds to `127.0.0.1` and is not exposed to the internet or your local network
|
||||||
|
- **No API keys** — authentication goes through Claude CLI's OAuth session, no credentials are stored in the proxy
|
||||||
|
- **Auto-start via launchd/systemd** — `node setup.mjs` installs a user-level launch agent (macOS) or systemd user service (Linux) so the proxy starts automatically on login
|
||||||
|
- **Remove auto-start** at any time:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node uninstall.mjs
|
||||||
|
```
|
||||||
|
|
||||||
## Manual Install
|
## Manual Install
|
||||||
|
|
||||||
### 1. Start the proxy
|
### 1. Start the proxy
|
||||||
@@ -148,13 +140,25 @@ openclaw gateway restart
|
|||||||
- `POST /v1/chat/completions` — Chat completion (streaming + non-streaming)
|
- `POST /v1/chat/completions` — Chat completion (streaming + non-streaming)
|
||||||
- `GET /health` — Health check
|
- `GET /health` — Health check
|
||||||
|
|
||||||
## Auto-start on Login (macOS)
|
## Server / Advanced: Docker
|
||||||
|
|
||||||
|
For server deployments or if you prefer Docker:
|
||||||
|
|
||||||
Add to your `~/.zshrc`:
|
|
||||||
```bash
|
```bash
|
||||||
bash ~/.openclaw/projects/claude-proxy/start.sh 2>/dev/null
|
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git
|
||||||
|
cd openclaw-claude-proxy
|
||||||
|
cp .env.example .env # add your CLAUDE_SESSION_TOKEN / CLAUDE_COOKIES
|
||||||
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or as a single command if you already have a `.env` ready:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git && cd openclaw-claude-proxy && docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Health check: `curl http://localhost:3456/health`
|
||||||
|
|
||||||
## Recovery after OpenClaw upgrade
|
## Recovery after OpenClaw upgrade
|
||||||
|
|
||||||
OpenClaw upgrades (`npm update -g openclaw`) **do not overwrite** the user config at `~/.openclaw/openclaw.json`. However, if the claude-local models stop working after an upgrade, follow these steps:
|
OpenClaw upgrades (`npm update -g openclaw`) **do not overwrite** the user config at `~/.openclaw/openclaw.json`. However, if the claude-local models stop working after an upgrade, follow these steps:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "openclaw-claude-proxy",
|
"name": "openclaw-claude-proxy",
|
||||||
"version": "1.4.0",
|
"version": "1.5.0",
|
||||||
"description": "OpenAI-compatible proxy that routes requests through Claude CLI — use your Claude Pro/Max subscription as an OpenClaw model provider",
|
"description": "OpenAI-compatible proxy that routes requests through Claude CLI — use your Claude Pro/Max subscription as an OpenClaw model provider",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -279,3 +279,96 @@ if (!SKIP_START && !DRY_RUN) {
|
|||||||
execSync(`bash "${startPath}"`, { stdio: "inherit" });
|
execSync(`bash "${startPath}"`, { stdio: "inherit" });
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Step 7: Install auto-start on boot ──────────────────────────────────
|
||||||
|
if (!DRY_RUN) {
|
||||||
|
console.log("\n🔄 Installing auto-start on login...\n");
|
||||||
|
|
||||||
|
const platform = process.platform;
|
||||||
|
const nodeBin = process.execPath;
|
||||||
|
|
||||||
|
// Ensure logs dir exists
|
||||||
|
const logsDir = join(OPENCLAW_DIR, "logs");
|
||||||
|
if (!existsSync(logsDir)) mkdirSync(logsDir, { recursive: true });
|
||||||
|
|
||||||
|
if (platform === "darwin") {
|
||||||
|
// macOS: launchd
|
||||||
|
const plistDir = join(HOME, "Library", "LaunchAgents");
|
||||||
|
if (!existsSync(plistDir)) mkdirSync(plistDir, { recursive: true });
|
||||||
|
|
||||||
|
const plistPath = join(plistDir, "ai.openclaw.proxy.plist");
|
||||||
|
const logPath = join(logsDir, "proxy.log");
|
||||||
|
|
||||||
|
const plistXml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>ai.openclaw.proxy</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>${nodeBin}</string>
|
||||||
|
<string>${serverPath}</string>
|
||||||
|
</array>
|
||||||
|
<key>EnvironmentVariables</key>
|
||||||
|
<dict>
|
||||||
|
<key>CLAUDE_PROXY_PORT</key>
|
||||||
|
<string>${PORT}</string>
|
||||||
|
</dict>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>${logPath}</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>${logPath}</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
`;
|
||||||
|
|
||||||
|
writeFileSync(plistPath, plistXml);
|
||||||
|
log(`Plist written: ${plistPath}`);
|
||||||
|
|
||||||
|
// Unload first (in case it was already loaded) then load
|
||||||
|
try { execSync(`launchctl unload "${plistPath}" 2>/dev/null`); } catch { /* ignore */ }
|
||||||
|
execSync(`launchctl load "${plistPath}"`);
|
||||||
|
log(`launchctl loaded ai.openclaw.proxy`);
|
||||||
|
|
||||||
|
} else if (platform === "linux") {
|
||||||
|
// Linux: systemd user service
|
||||||
|
const systemdDir = join(HOME, ".config", "systemd", "user");
|
||||||
|
if (!existsSync(systemdDir)) mkdirSync(systemdDir, { recursive: true });
|
||||||
|
|
||||||
|
const servicePath = join(systemdDir, "openclaw-proxy.service");
|
||||||
|
const logPath = join(logsDir, "proxy.log");
|
||||||
|
|
||||||
|
const serviceUnit = `[Unit]
|
||||||
|
Description=OpenClaw Claude Proxy
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=${nodeBin} ${serverPath}
|
||||||
|
Environment=CLAUDE_PROXY_PORT=${PORT}
|
||||||
|
Restart=always
|
||||||
|
StandardOutput=append:${logPath}
|
||||||
|
StandardError=append:${logPath}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
`;
|
||||||
|
|
||||||
|
writeFileSync(servicePath, serviceUnit);
|
||||||
|
log(`Service file written: ${servicePath}`);
|
||||||
|
|
||||||
|
execSync(`systemctl --user daemon-reload`);
|
||||||
|
execSync(`systemctl --user enable openclaw-proxy`);
|
||||||
|
execSync(`systemctl --user start openclaw-proxy`);
|
||||||
|
log(`systemd user service enabled and started`);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
warn(`Auto-start not supported on ${platform} — start manually with: bash ${startPath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\n✅ Auto-start installed — proxy will start automatically on login\n");
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* openclaw-claude-proxy uninstaller
|
||||||
|
*
|
||||||
|
* Stops and removes the launchd (macOS) or systemd (Linux) auto-start entry.
|
||||||
|
* Run: node uninstall.mjs
|
||||||
|
*/
|
||||||
|
import { existsSync, unlinkSync } from "node:fs";
|
||||||
|
import { execSync } from "node:child_process";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { homedir } from "node:os";
|
||||||
|
|
||||||
|
const HOME = homedir();
|
||||||
|
|
||||||
|
function log(msg) { console.log(` ✓ ${msg}`); }
|
||||||
|
function warn(msg) { console.log(` ⚠ ${msg}`); }
|
||||||
|
|
||||||
|
console.log("\n🗑 Uninstalling openclaw-claude-proxy auto-start...\n");
|
||||||
|
|
||||||
|
const platform = process.platform;
|
||||||
|
|
||||||
|
if (platform === "darwin") {
|
||||||
|
const plistPath = join(HOME, "Library", "LaunchAgents", "ai.openclaw.proxy.plist");
|
||||||
|
|
||||||
|
if (existsSync(plistPath)) {
|
||||||
|
try {
|
||||||
|
execSync(`launchctl unload "${plistPath}" 2>/dev/null`);
|
||||||
|
log("launchd service stopped and unloaded");
|
||||||
|
} catch {
|
||||||
|
warn("launchctl unload failed (service may not have been running)");
|
||||||
|
}
|
||||||
|
unlinkSync(plistPath);
|
||||||
|
log(`Plist removed: ${plistPath}`);
|
||||||
|
} else {
|
||||||
|
warn(`Plist not found: ${plistPath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (platform === "linux") {
|
||||||
|
const servicePath = join(HOME, ".config", "systemd", "user", "openclaw-proxy.service");
|
||||||
|
|
||||||
|
try { execSync(`systemctl --user stop openclaw-proxy 2>/dev/null`); } catch { /* ignore */ }
|
||||||
|
log("systemd service stopped");
|
||||||
|
|
||||||
|
try { execSync(`systemctl --user disable openclaw-proxy 2>/dev/null`); } catch { /* ignore */ }
|
||||||
|
log("systemd service disabled");
|
||||||
|
|
||||||
|
if (existsSync(servicePath)) {
|
||||||
|
unlinkSync(servicePath);
|
||||||
|
log(`Service file removed: ${servicePath}`);
|
||||||
|
} else {
|
||||||
|
warn(`Service file not found: ${servicePath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try { execSync(`systemctl --user daemon-reload`); } catch { /* ignore */ }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
warn(`Auto-start not supported on ${platform} — nothing to remove`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\n✅ Auto-start removed — proxy will no longer start on login\n");
|
||||||
Reference in New Issue
Block a user