fix: bind 0.0.0.0 by default so remote devices can access OCM

- server.listen was hardcoded to 127.0.0.1, causing ERR_CONNECTION_REFUSED on remote access
- Default to 0.0.0.0, add --host flag to override (e.g. --host 127.0.0.1 for local-only)
- Show LAN IP in startup log for easy remote access
- Startup log and error messages switched to English
- Bump version to v0.5.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 10:12:36 +00:00
co-authored by Claude Opus 4.6
parent 6cca232e9e
commit e38f91ec4a
4 changed files with 57 additions and 17 deletions
+20 -1
View File
@@ -1,7 +1,26 @@
# OpenClaw Manager — 开发日志 # OpenClaw Manager — 开发日志
> 最后更新:2026-02-25 > 最后更新:2026-02-25
> 当前版本:v0.5.1 > 当前版本:v0.5.2
---
## v0.5.2 更新日志(2026-02-25
### 修复
**远程访问无法连接(ERR_CONNECTION_REFUSED**
- `server.listen` 原来绑定 `127.0.0.1`(仅本机),远程通过 `http://<IP>:3333` 访问时被直接拒绝
- 改为默认绑定 `0.0.0.0`(所有网卡),远程设备可通过局域网 IP 访问
- 新增 `--host` 命令行参数:需要限制仅本机访问时可用 `--host 127.0.0.1` 覆盖
- 新增 `getLanIP()` 工具函数,自动检测第一个非内部 IPv4 地址
### 改进
**启动日志改为英文**
- 终端启动信息(目录、地址、提示、错误)全部改为英文
- 绑定 `0.0.0.0` 时自动显示局域网地址,方便远程复制:`🌐 LAN: http://192.168.x.x:3333`
- 端口占用、启动失败等错误提示同步改为英文
--- ---
+33 -12
View File
@@ -1,11 +1,12 @@
#!/usr/bin/env node #!/usr/bin/env node
// ================================================================ // ================================================================
// OpenClaw Manager v0.5.1 // OpenClaw Manager v0.5.2
// 跨平台本地管理工具 (Windows / macOS / Linux) // 跨平台本地管理工具 (Windows / macOS / Linux)
// //
// 用法: // 用法:
// node openclaw-manager.js # 使用默认 ~/.openclaw // node openclaw-manager.js # 使用默认 ~/.openclaw
// node openclaw-manager.js --dir /path/to/.openclaw // node openclaw-manager.js --dir /path/to/.openclaw
// node openclaw-manager.js --host 127.0.0.1 # 仅本机访问(默认 0.0.0.0
// OPENCLAW_DIR=/path/to/.openclaw node openclaw-manager.js // OPENCLAW_DIR=/path/to/.openclaw node openclaw-manager.js
// //
// ================================================================ // ================================================================
@@ -22,12 +23,18 @@ const { exec, execSync, spawn, spawnSync } = require('child_process');
const SCRIPT_DIR = __dirname; const SCRIPT_DIR = __dirname;
const MANAGER_CONFIG = path.join(SCRIPT_DIR, 'manager-config.json'); const MANAGER_CONFIG = path.join(SCRIPT_DIR, 'manager-config.json');
let PORT = 3333; let PORT = 3333;
const APP_VERSION = '0.5.1'; let HOST = '0.0.0.0';
const APP_VERSION = '0.5.2';
// --port 参数 // --port 参数
const portIdx = process.argv.indexOf('--port'); const portIdx = process.argv.indexOf('--port');
if (portIdx !== -1 && process.argv[portIdx + 1]) PORT = parseInt(process.argv[portIdx + 1]) || 3333; if (portIdx !== -1 && process.argv[portIdx + 1]) PORT = parseInt(process.argv[portIdx + 1]) || 3333;
const portEq = process.argv.find(a => a.startsWith('--port=')); const portEq = process.argv.find(a => a.startsWith('--port='));
if (portEq) PORT = parseInt(portEq.split('=')[1]) || 3333; if (portEq) PORT = parseInt(portEq.split('=')[1]) || 3333;
// --host 参数(默认 0.0.0.0 允许远程访问)
const hostIdx = process.argv.indexOf('--host');
if (hostIdx !== -1 && process.argv[hostIdx + 1]) HOST = process.argv[hostIdx + 1];
const hostEq = process.argv.find(a => a.startsWith('--host='));
if (hostEq) HOST = hostEq.split('=').slice(1).join('=');
function loadManagerConfig() { function loadManagerConfig() {
try { return JSON.parse(fs.readFileSync(MANAGER_CONFIG, 'utf8')); } catch { return {}; } try { return JSON.parse(fs.readFileSync(MANAGER_CONFIG, 'utf8')); } catch { return {}; }
@@ -151,6 +158,16 @@ async function listBackups() {
} catch { return []; } } catch { return []; }
} }
function getLanIP() {
const nets = os.networkInterfaces();
for (const name of Object.keys(nets)) {
for (const net of nets[name]) {
if (net.family === 'IPv4' && !net.internal) return net.address;
}
}
return null;
}
function openBrowser(url) { function openBrowser(url) {
if (process.platform === 'darwin') exec(`open "${url}"`); if (process.platform === 'darwin') exec(`open "${url}"`);
else if (process.platform === 'win32') exec(`start "" "${url}"`); else if (process.platform === 'win32') exec(`start "" "${url}"`);
@@ -2985,7 +3002,7 @@ function onCliKey(e){
// ── CLI Tab 补全 ───────────────────────────────────────────── // ── CLI Tab 补全 ─────────────────────────────────────────────
const CLI_SUBCOMMANDS=['openclaw','doctor','gateway','models','agents','backup','config','auth', const CLI_SUBCOMMANDS=['openclaw','doctor','gateway','models','agents','backup','config','auth',
'restart','start','stop','status','logs','list','create','validate','update','onboard','sync', 'restart','start','stop','status','logs','list','create','validate','update','onboard','sync',
'paste-token','--provider','--version','--dir','--port']; 'paste-token','--provider','--version','--dir','--port','--host'];
function cliTabComplete(input){ function cliTabComplete(input){
const val=input.value; const val=input.value;
@@ -3465,23 +3482,27 @@ const server = http.createServer(async (req, res) => {
} }
}); });
server.listen(PORT, '127.0.0.1', () => { server.listen(PORT, HOST, () => {
const url = `http://localhost:${PORT}`; const localUrl = `http://localhost:${PORT}`;
console.log(''); console.log('');
console.log(`🦀 OpenClaw Manager v${APP_VERSION}`); console.log(`🦀 OpenClaw Manager v${APP_VERSION}`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('📂 目录:' + OPENCLAW_DIR); console.log('📂 Dir: ' + OPENCLAW_DIR);
console.log('🌐 地址:' + url); console.log('🌐 Local: ' + localUrl);
console.log('💡 切换目录:node openclaw-manager.js --dir /path/to/.openclaw'); if (HOST === '0.0.0.0') {
const lanIp = getLanIP();
if (lanIp) console.log('🌐 LAN: ' + `http://${lanIp}:${PORT}`);
}
console.log('💡 Switch dir: node openclaw-manager.js --dir /path/to/.openclaw');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('Ctrl+C 停止'); console.log('Ctrl+C to stop');
openBrowser(url); openBrowser(localUrl);
}); });
server.on('error', err => { server.on('error', err => {
if (err.code === 'EADDRINUSE') if (err.code === 'EADDRINUSE')
console.error(`端口 ${PORT} 已占用。请关闭其他程序后重试,或用 --port 指定其他端口。`); console.error(`Port ${PORT} is already in use. Close the other process or use --port to specify a different port.`);
else else
console.error('❌ 启动失败:', err.message); console.error('❌ Failed to start:', err.message);
process.exit(1); process.exit(1);
}); });
+2 -2
View File
@@ -1,6 +1,6 @@
@echo off @echo off
:: ================================================================ :: ================================================================
:: OpenClaw Manager v0.5.1 — Windows 启动脚本 :: OpenClaw Manager v0.5.2 — Windows 启动脚本
:: ::
:: 特性: :: 特性:
:: * 自动检测 Node.js,未安装时给出安装指引(winget/scoop/官网) :: * 自动检测 Node.js,未安装时给出安装指引(winget/scoop/官网)
@@ -19,7 +19,7 @@ set "MIN_NODE_MAJOR=18"
echo. echo.
echo =================================== echo ===================================
echo OpenClaw Manager v0.5.1 echo OpenClaw Manager v0.5.2
echo ----------------------------------- echo -----------------------------------
echo. echo.
+2 -2
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ================================================================ # ================================================================
# OpenClaw Manager v0.5.1 — 跨平台启动脚本 (macOS / Linux) # OpenClaw Manager v0.5.2 — 跨平台启动脚本 (macOS / Linux)
# #
# 特性: # 特性:
# • 自动检测 Node.js,未安装时给出安装指引 # • 自动检测 Node.js,未安装时给出安装指引
@@ -22,7 +22,7 @@ CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; RESET='\033[0m'
banner() { banner() {
echo "" echo ""
echo -e "${CYAN}${BOLD} 🦀 OpenClaw Manager v0.5.1${RESET}" echo -e "${CYAN}${BOLD} 🦀 OpenClaw Manager v0.5.2${RESET}"
echo -e "${DIM} ─────────────────────────────${RESET}" echo -e "${DIM} ─────────────────────────────${RESET}"
echo "" echo ""
} }