v1.1.0: 支持 Windows 服务端部署
- 新增跨平台进程终止 killProcess(),Windows 使用 taskkill,Linux 使用 SIGTERM/SIGKILL - spawn 增加 windowsHide 参数,HOME 路径增加 USERPROFILE fallback - 新增 start.bat 一键启动脚本 - README 快速开始分 Linux/Windows 两部分,新增 Windows 部署章节 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
48
README.md
48
README.md
@@ -38,21 +38,28 @@ https://github.com/ZgDaniel/cc-web 给我装!
|
||||
|
||||
## 快速开始
|
||||
|
||||
### Linux / macOS
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://github.com/your-username/cc-web.git
|
||||
git clone https://github.com/ZgDaniel/cc-web.git
|
||||
cd cc-web
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 创建配置文件(可选,不设密码则首次启动自动生成)
|
||||
cp .env.example .env
|
||||
|
||||
# 启动
|
||||
cp .env.example .env # 可选,不设密码则首次启动自动生成
|
||||
npm start
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```cmd
|
||||
git clone https://github.com/ZgDaniel/cc-web.git
|
||||
cd cc-web
|
||||
npm install
|
||||
copy .env.example .env & REM 可选
|
||||
```
|
||||
然后双击 `start.bat`,或在终端运行 `node server.js`。
|
||||
|
||||
---
|
||||
|
||||
启动后访问 `http://localhost:8002`,输入密码即可使用。
|
||||
|
||||
## 配置
|
||||
@@ -106,6 +113,7 @@ cc-web/
|
||||
├── sessions/ # 对话历史 JSON 文件(运行时生成)
|
||||
├── logs/ # 进程生命周期日志(运行时生成)
|
||||
├── .env.example # 环境变量模板
|
||||
├── start.bat # Windows 一键启动脚本
|
||||
├── .gitignore
|
||||
├── package.json
|
||||
└── README.md
|
||||
@@ -210,6 +218,24 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
### Windows 部署
|
||||
|
||||
适用于在个人电脑上运行 CC-Web,通过手机远程控制 Claude Code。
|
||||
|
||||
**启动方式**:双击 `start.bat`,或在终端运行:
|
||||
```cmd
|
||||
cd cc-web
|
||||
npm install
|
||||
node server.js
|
||||
```
|
||||
|
||||
**局域网访问**(手机和电脑在同一 WiFi):
|
||||
- 直接访问 `http://电脑局域网IP:8002`
|
||||
|
||||
**远程访问**(外出时用手机控制家里电脑):
|
||||
- 推荐使用 [Tailscale](https://tailscale.com/) — 电脑和手机各安装一个,自动组网,免费够用
|
||||
- 或使用 [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)(需域名)
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **后端**:Node.js + [ws](https://github.com/websockets/ws)(唯一依赖)
|
||||
@@ -219,5 +245,5 @@ server {
|
||||
|
||||
## 补充说明
|
||||
|
||||
- 暂时只支持linux服务器,后续再vibe电脑端
|
||||
- 暂时只支持claude code,后续再vibe codex
|
||||
- 支持 Linux 服务器和 Windows 个人电脑部署
|
||||
- 暂时只支持 Claude Code,后续再 vibe codex
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cc-web",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
|
||||
25
server.js
25
server.js
@@ -284,6 +284,8 @@ function modelShortName(fullModel) {
|
||||
return entry ? entry[0] : null;
|
||||
}
|
||||
|
||||
const IS_WIN = process.platform === 'win32';
|
||||
|
||||
function isProcessRunning(pid) {
|
||||
try {
|
||||
process.kill(pid, 0);
|
||||
@@ -293,6 +295,18 @@ function isProcessRunning(pid) {
|
||||
}
|
||||
}
|
||||
|
||||
function killProcess(pid, force = false) {
|
||||
try {
|
||||
if (IS_WIN) {
|
||||
const args = ['/T', '/PID', String(pid)];
|
||||
if (force) args.unshift('/F');
|
||||
spawn('taskkill', args, { windowsHide: true });
|
||||
} else {
|
||||
process.kill(pid, force ? 'SIGKILL' : 'SIGTERM');
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function cleanRunDir(sessionId) {
|
||||
const dir = runDir(sessionId);
|
||||
try {
|
||||
@@ -731,7 +745,7 @@ function handleSlashCommand(ws, text, sessionId) {
|
||||
if (session) {
|
||||
if (activeProcesses.has(sessionId)) {
|
||||
const entry = activeProcesses.get(sessionId);
|
||||
try { process.kill(entry.pid, 'SIGTERM'); } catch {}
|
||||
killProcess(entry.pid);
|
||||
if (entry.tailer) entry.tailer.stop();
|
||||
activeProcesses.delete(sessionId);
|
||||
cleanRunDir(sessionId);
|
||||
@@ -899,7 +913,7 @@ function handleLoadSession(ws, sessionId) {
|
||||
function handleDeleteSession(ws, sessionId) {
|
||||
if (activeProcesses.has(sessionId)) {
|
||||
const entry = activeProcesses.get(sessionId);
|
||||
try { process.kill(entry.pid, 'SIGTERM'); } catch {}
|
||||
try { killProcess(entry.pid); } catch {}
|
||||
if (entry.tailer) entry.tailer.stop();
|
||||
activeProcesses.delete(sessionId);
|
||||
if (entry.ws) wsSend(entry.ws, { type: 'done', sessionId });
|
||||
@@ -961,9 +975,9 @@ function handleAbort(ws) {
|
||||
if (!entry) return;
|
||||
|
||||
plog('INFO', 'user_abort', { sessionId: sessionId.slice(0, 8), pid: entry.pid });
|
||||
try { process.kill(entry.pid, 'SIGTERM'); } catch {}
|
||||
killProcess(entry.pid);
|
||||
setTimeout(() => {
|
||||
try { process.kill(entry.pid, 'SIGKILL'); } catch {}
|
||||
killProcess(entry.pid, true);
|
||||
}, 3000);
|
||||
// handleProcessComplete will be triggered by the PID monitor
|
||||
}
|
||||
@@ -1061,9 +1075,10 @@ function handleMessage(ws, msg) {
|
||||
try {
|
||||
proc = spawn(CLAUDE_PATH, args, {
|
||||
env,
|
||||
cwd: process.env.HOME || process.cwd(),
|
||||
cwd: process.env.HOME || process.env.USERPROFILE || process.cwd(),
|
||||
stdio: [inputFd, outputFd, errorFd],
|
||||
detached: true,
|
||||
windowsHide: true,
|
||||
});
|
||||
} catch (err) {
|
||||
fs.closeSync(inputFd);
|
||||
|
||||
20
start.bat
Normal file
20
start.bat
Normal file
@@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
chcp 65001 >nul 2>&1
|
||||
cd /d "%~dp0"
|
||||
|
||||
where node >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo [ERROR] Node.js not found. Please install Node.js first.
|
||||
echo https://nodejs.org/
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist node_modules (
|
||||
echo Installing dependencies...
|
||||
npm install
|
||||
)
|
||||
|
||||
echo Starting CC-Web...
|
||||
node server.js
|
||||
pause
|
||||
Reference in New Issue
Block a user