开发了一个随时随地控制服务器claude code的工具

OpenClaw最近爆火出圈,每当人别人问有没有部署的时候,我都在一个问题,你打算做什么?因为本质上,我只需要一个服务器连接Claude Code就能实现OpenClaw的绝大部分功能了。

有一个功能我是特别喜欢,那就是 OpenClaw 可以通过不同的终端发送指令,而这是 Claude Code 目前所不能实现的。

比方说,我有多个服务器,每个服务器都运行着 Claude Code。

这些服务器运行完之后通常需要手动确认,但如果我当时刚好不在服务器旁边,操作起来就会比较麻烦。所以我想,有没有可能我自己搞一个网页终端?这样我就可以通过网页终端随时获取当前状态,并进行确认工作。

之所以有这个需求,是因为:

  1. OpenClaw 的权限特别大,操作不当可能会把服务器搞乱。
  2. Claude Code 比较谨慎,权限控制相对严格,需要频繁点击确认。

如果我有这样一个网页工具,能帮我随时随地确认状态,就完全符合我的需求了,甚至不再需要 OpenClaw。

我跟 ChatGPT 进行了交流,向它输入了流程思路,咨询大概需要什么工具以及具体的实现方法。

最后我决定使用 Go 语言作为后端,主要基于以下考虑:

  1. 部署简单:Go 可以直接编译成二进制文件,资源占用非常小,直接分发到服务器上即可。
  2. 项目需求:这个项目总体比较简单,后端只需要监控我的 Terminal(终端),前端负责网页展示。相比之下,Python 众多的第三方库在本项目中并非必需。

至于前端部分,因为逻辑比较简单,我没有使用任何框架,只是进行了原生的 Native 开发。

经过跟 Cursor 的交流,我们制定了以下开发流程:

  1. 计划阶段:使用 GPT 5.2 (Extra High) 进行整体规划
  2. 编程操作:使用 GPT 5.3 CodeX Extra High)进行核心代码编写
  3. 模型优化:中间穿插使用了 Opus 4.6 模型

大概经过这十几次 Commit,我们最终完成了代码。开发过程中,发现其中比较复杂的部分在于如何渲染终端和前端页面样式的可视化,难点主要是如何更适合手机端操作。

我最初的一些想法都在后续的反复开发中不断进行了重构。目前整体设计还是相对比较简洁的,因为 UI 比较简单,绝大部分功能都是通过 API 实现的,所以后面衔接其他程序也会相对容易一些。

代码开源在 GitHub 上,https://github.com/xuzhougeng/agent-control

接下来介绍如何去部署这个工作:

首先我们需要从 GitHub 上克隆这个项目,然后对其进行编译。

git clone https://github.com/xuzhougeng/agent-control
cd agent-control
cd cc-control
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o cc-control ./cmd/cc-control
cd ../cc-agent
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o cc-agent ./cmd/cc-agent

这个项目分为两个部分:其中一个部分是需要一个公网 IP 的服务器,因为我的服务器主要集中在境内,所以我们可以购买一个国内的服务器。

这里选择购买一个腾讯云服务器,不需要域名,只需要IP即可。

image

服务器购买后,我们需要打开防火墙,在里面添加 443 端口。

之所以需要增加 443 端口,是因为如果使用 HTTP 端口,传输过程就是明文的。这样很有可能导致服务器暴露在外面,尤其是涉及敏感服务器时会非常危险。毕竟我们的权限还是比较大的,所以一定要通过 HTTPS 协议进行传输。

image-1770797207565

然后根据服务器的 IP 地址、用户名和密码登录到服务器上。接着在服务器上做如下的配置操作:

第一步:建立相关的文件夹并赋予其权限

sudo mkdir -p /opt/cc-control
sudo chown ubuntu:ubuntu /opt/cc-control

无域名时无法使用 Let’s Encrypt,可用自签名证书在 Nginx 上启用 TLS,传输仍加密;浏览器和 agent 需接受自签名(浏览器手动信任,agent 用 -tls-skip-verify)。

下面的1.2.3.4得改成实际的IP地址

mkdir -p /opt/cc-control/tls
cd /opt/cc-control/tls

# openssl 配置文件:证书包含 IP
cat > openssl.cnf << 'EOF'
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = cc-control
[v3_req]
subjectAltName = @alt
[alt]
IP.1 = 1.2.3.4
EOF

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout key.pem -out cert.pem -config openssl.cnf -extensions v3_req

接着我们需要安装 Nginx

sudo apt install nginx

增加配置文件 /etc/nginx/conf.d/cc.conf

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name _;

    ssl_certificate     /opt/cc-control/tls/cert.pem;
    ssl_certificate_key /opt/cc-control/tls/key.pem;

    location /ws/ {
        proxy_pass http://127.0.0.1:18080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    location / {
        proxy_pass http://127.0.0.1:18080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

重启nginx服务

sudo nginx -t 
sudo systemctl reload nginx

在服务器这部分操作结束后,我们需要回到本地,将我们编译的代码进行上传。

scp cc-control ubuntu@106.54.201.18:/opt/cc-control/
scp -r ../ui ubuntu@106.54.201.18:/opt/cc-control/ui

然后是非常关键的一步,需要生成两个 token,分别是 AGENT_TOKEN 和 UI_TOKEN:

  1. AGENT_TOKEN

    负责本地 agent 与服务器端进行连接(Service Network)。

  2. UI_TOKEN

    相当于一个密码。当别人访问页面时,在没有授权的情况下无法直接查看,需要输入这个密码才能够查看你的网页。

AGENT_TOKEN=$(openssl rand -hex 32)
UI_TOKEN=$(openssl rand -hex 32)
echo "AGENT_TOKEN=$AGENT_TOKEN"
echo "UI_TOKEN=$UI_TOKEN"

增加一个服务文件,/etc/systemd/system/cc-control.service,这样可以保证开机或重启之后,它会自动启动。

不然的话,可能服务器会重启,或者程序在某种情况下不小心中断了。如果它不能重连的话,处理起来就比较麻烦,你还得专门打开服务器去配置它,而设置为服务之后,它就会在这些情况下自动重启。

[Unit]
Description=CC Control Plane
After=network.target

[Service]
Type=simple
User=cc
Group=cc
WorkingDirectory=/opt/cc-control
ExecStart=/opt/cc-control/cc-control \
  -addr 127.0.0.1:18080 \
  -ui-dir /opt/cc-control/ui \
  -agent-token ${AGENT_TOKEN} \
  -ui-token ${UI_TOKEN} \
  -audit-path /opt/cc-control/audit.jsonl \
  -offline-after-sec 30
EnvironmentFile=/opt/cc-control/.env
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

需要注意的是,这里面涉及到一个环境文件/opt/cc-control/.env,里面的 token 都是我们刚才生成的。

AGENT_TOKEN=<your-agent-token>
UI_TOKEN=<your-ui-token>

为了安全,我们继续新建一个不允许被登录的账号。同时,把刚才环境变量的权限改一改,进一步增加安全性,然后重启该服务。

sudo useradd -r -s /sbin/nologin cc
sudo chown -R cc:cc /opt/cc-control
sudo chmod 600 /opt/cc-control/.env
sudo systemctl daemon-reload
sudo systemctl enable --now cc-control

等这些配置完成后,我们就可以打开浏览器访问我们的网站了。

由于 TLS 或者说 HTTP 协议(也就是 SSL 证书)是我们自签名的,浏览器会提示该连接不安全。但这没有关系,只需按照以下步骤操作:

  1. 在浏览器提示界面选择“高级”
  2. 点击“继续访问”即可进入网站

手机端访问时也会出现同样的情况,无需担心。

image-1770797247465

接着我们需要填写里面的 UI Token,也就是我们刚才生成的。不然的话,我们是看不到连接服务的。当然,现在连上去也看不到服务,毕竟我们本地agent都还没有连上去。

image-1770797259218

然后需要启动本地端的 agent 了。

  1. IP 地址:我们现在写的是 1234,你得改成我们实际的 IP 地址
  2. Agent Token:也一样,也要改成实际的 Agent Token

当然,服务器上必须安装 Claude 并配置 Claude 的相关信息,这部分内容就不在这里过多介绍了。

cc-agent \
  -control-url wss://1.2.3.4/ws/agent \
  -tls-skip-verify \
  -agent-token "$AGENT_TOKEN" \
  -server-id srv-gpu-01 \
  -allow-root /home/deploy/repos \
  -claude-path /usr/local/bin/claude

实际效果如下:

image-1770797278994

# AI 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×