移除 OpenClaw/ClawHub 遗留并更新文档

删除 allowall.sh、旧版 CLI/Web 路由,README 改为 Hermes 专用说明。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
carl
2026-05-17 14:54:14 +08:00
co-authored by Cursor
parent 5341a7617b
commit 08b25e8f87
7 changed files with 42 additions and 172 deletions
+1 -1
View File
@@ -177,7 +177,7 @@ cython_debug/
.env
.DS_Store
# 本地实例数据(默认 hermes-agent-instances/,也可由 OPENCLAW_HOME_DATA_DIR 指向其它路径)
# 本地实例数据(默认 hermes-agent-instances/,也可由 HERMES_HOME_DATA_DIR 指向其它路径)
hermes-agent-instances/
.venv/
__pycache__/
+13 -17
View File
@@ -2,40 +2,36 @@
在本机用 **Docker Compose** 管理多个 **[NousResearch Hermes Agent](https://github.com/NousResearch/hermes-agent)** 实例:CLI + 可选 Web 管理台。
**不是 OpenClaw。** 底层镜像与服务来自官方 `hermes-agent` 仓库;每实例独立数据目录挂载到容器 `/opt/data`(`config.yaml`、`.env`、`sessions/` 等)。
## 与 openclaw-home 的区别
| 项目 | openclaw-home | hermes-agent-home(本仓库) |
|------|---------------|---------------------------|
| 上游仓库 | OpenClaw | **NousResearch/hermes-agent** |
| Compose 服务 | `openclaw-gateway` | **`gateway`** |
| 配置 | `config/openclaw.json` | **`data/config.yaml`** |
| 网关/Dashboard 端口 | 18780+N / 18790+N | **8641+N / 9118+N**(实例 1 → 8642 / 9119) |
| Compose 项目名 | `claw-<N>` | `hermes-<N>` |
每实例独立数据目录挂载到容器 `/opt/data`(`config.yaml`、`.env`、`sessions/` 等)。默认使用官方镜像 `nousresearch/hermes-agent:latest`,无需 clone 源码。
## 快速开始
```bash
git clone https://github.com/NousResearch/hermes-agent.git /path/to/hermes-agent
cd /path/to/hermes-agent-home
cp .env.example .env # 设置 HERMES_SOURCE=/path/to/hermes-agent
cp .env.example .env # 可选:改 HERMES_IMAGE、Web 密码等
./hermes-agent-cli.sh check
./hermes-agent-cli.sh compose-build 1 # 首次构建镜像(较久)
./hermes-agent-cli.sh compose-build 1 # 拉取官方镜像
./hermes-agent-cli.sh setup 1 # 交互配置 API 密钥等(或 Web「Hermes 引导」)
./hermes-agent-cli.sh run 1
# 实例 1:API http://127.0.0.1:8642 · Dashboard http://127.0.0.1:9119
```
本地从源码构建镜像时,在 `.env` 设置 `HERMES_USE_LOCAL_BUILD=1` 与 `HERMES_SOURCE`(指向含 `Dockerfile` 的 hermes-agent 仓库根目录)。
## Web
见 [hermes-agent-web/README.md](hermes-agent-web/README.md)。默认 http://127.0.0.1:8781
## 从旧版(OpenClaw 兼容层)迁移
## 端口与命名
若此前用 `OPENCLAW_SOURCE` 跑过实例,请**销毁旧实例**后按上表重建;旧目录 `hermes-agent-instances/<N>/config/` 与 Hermes 的 `data/` 布局不兼容。
| 项目 | 说明 |
|------|------|
| Compose 项目名 | `hermes-<序号>` |
| 服务名 | `gateway` |
| 容器名示例 | `hermes-1-gateway-1` |
| 网关 API 端口 | `8641 + 序号`(实例 1 → 8642) |
| Dashboard 端口 | `9118 + 序号`(实例 1 → 9119) |
文档:https://hermes-agent.nousresearch.com/docs/user-guide/docker
-96
View File
@@ -1,96 +0,0 @@
mkdir -p ~/.openclaw && python3 - <<'PY'
import json, os, pathlib, copy
base = pathlib.Path(os.path.expanduser("~/.openclaw"))
openclaw_path = base / "openclaw.json"
approvals_path = base / "exec-approvals.json"
def load_json(path, default):
if not path.exists():
return copy.deepcopy(default)
try:
return json.loads(path.read_text(encoding="utf-8"))
except Exception:
return copy.deepcopy(default)
# 1) 修 openclaw.json
cfg = load_json(openclaw_path, {})
cfg.setdefault("tools", {})
cfg["tools"].setdefault("exec", {})
cfg["tools"]["exec"]["security"] = "full"
cfg["tools"]["exec"]["ask"] = "off"
# 可选但实用:把常见会挡住 skill 的 deny 清掉
agents = cfg.get("agents", {}).get("list", [])
if isinstance(agents, list):
for agent in agents:
if not isinstance(agent, dict):
continue
tools = agent.setdefault("tools", {})
deny = tools.get("deny", [])
if isinstance(deny, list):
tools["deny"] = []
openclaw_path.write_text(json.dumps(cfg, ensure_ascii=False, indent=2), encoding="utf-8")
# 2) 修 exec-approvals.json
default_approvals = {
"version": 1,
"socket": {
"path": str(base / "exec-approvals.sock"),
"token": ""
},
"defaults": {
"security": "full",
"ask": "off",
"askFallback": "full",
"autoAllowSkills": True
},
"agents": {}
}
ap = load_json(approvals_path, default_approvals)
# 保留已有 socket,避免你本机原来的 socket/token 被抹掉
if not isinstance(ap, dict):
ap = copy.deepcopy(default_approvals)
ap["version"] = 1
ap.setdefault("socket", {})
ap["socket"].setdefault("path", str(base / "exec-approvals.sock"))
ap["socket"].setdefault("token", "")
ap.setdefault("defaults", {})
ap["defaults"]["security"] = "full"
ap["defaults"]["ask"] = "off"
ap["defaults"]["askFallback"] = "full"
ap["defaults"]["autoAllowSkills"] = True
ap.setdefault("agents", {})
if isinstance(ap["agents"], dict):
for agent_name, agent_cfg in list(ap["agents"].items()):
if isinstance(agent_cfg, dict):
agent_cfg["security"] = "full"
agent_cfg["ask"] = "off"
agent_cfg["askFallback"] = "full"
agent_cfg["autoAllowSkills"] = True
approvals_path.write_text(json.dumps(ap, ensure_ascii=False, indent=2), encoding="utf-8")
print("DONE")
print(openclaw_path)
print(approvals_path)
PY
openclaw gateway start
echo '----- GATEWAY STATUS -----'
openclaw gateway status
echo '----- APPROVALS EFFECTIVE -----'
openclaw approvals get --gateway || true
echo '----- OPENCLAW EXEC CONFIG -----'
python3 - <<'PY'
import json, os, pathlib
p = pathlib.Path(os.path.expanduser("~/.openclaw/openclaw.json"))
cfg = json.loads(p.read_text(encoding="utf-8"))
print(json.dumps(cfg.get("tools", {}).get("exec", {}), ensure_ascii=False, indent=2))
PY
-4
View File
@@ -478,10 +478,6 @@ case "$CMD" in
shift 2
cmd_config "$_id" "$@"
;;
channels|channel|devices|allowall)
echo "子命令 $CMD 为旧版 OpenClaw 专用;请使用: $0 cli <序号> … 或查阅 Hermes 文档。" >&2
exit 1
;;
*)
echo "未知子命令: $CMD" >&2
echo "运行 $0 help 查看说明。" >&2
+25 -44
View File
@@ -1,63 +1,44 @@
# Hermes Agent Web
在浏览器里管理本机多个 Hermes Agent(OpenClaw 兼容)实例:**列表与状态、新建、bootstrap 后启动、停止、重启、销毁**;**引导**在 **「Hermes 引导」** 页用浏览器内终端(PTY + xterm.js)完成 `setup`、`run`、`onboard`、`config`、`channels` 等。服务端用 **Flask + Jinja2**,**单进程 Python** 即可运行。
在浏览器里管理本机多个 **Hermes Agent** 实例:**列表与状态、新建、bootstrap、启动、停止、重启、销毁**;**「Hermes 引导」** 页用浏览器内终端(PTY + xterm.js)完成 `setup`、启动 gateway、进入容器 shell。Flask + Jinja2,单进程即可运行。
所有与 Docker Compose / 实例生命周期相关的操作都通过上级目录的 [`hermes-agent-cli.sh`](../hermes-agent-cli.sh) 完成(含 `check`、`status`、`stop`、`run`、`restart`、`destroy`、`bootstrap`、`cli` 透传容器内 `openclaw-cli`)。实例配置可通过 **`/instance/<序号>/config`** 编辑宿主机上的 `hermes-agent-instances/<序号>/config/openclaw.json`(保存前 JSON 校验并备份 `.bak`)。**销毁**会同时删除该序号下整份实例数据目录。
所有 Docker / 实例操作均通过上级 [`hermes-agent-cli.sh`](../hermes-agent-cli.sh)。配置编辑页读写宿主机 `hermes-agent-instances/<序号>/data/config.yaml`(YAML 校验,备份 `.bak`)。**销毁**会删除该序号下整份实例目录。
## 前置条件
- 本机已安装 **Docker**,且 `docker compose` 可用。
- 已配置 **`hermes-agent-home/.env`**(与 CLI 相同),至少设置 **`HERMES_SOURCE`** 或 **`OPENCLAW_SOURCE`**(OpenClaw 仓库根目录,内含 `docker-compose.yml`)。
- 可选 **`HERMES_HOME_DATA_DIR`**:实例数据父目录;不设置时默认使用 `hermes-agent-home/hermes-agent-instances/`。
- Docker(Desktop / Colima / dockerd)
- Python 3.10+
- 可选:`hermes-agent-home/.env` 中设置 `HERMES_AGENT_WEB_ADMIN_PASSWORD`
默认使用官方镜像,**不必**设置 `HERMES_SOURCE`;仅本地 build 时才需要。
## 安装与启动
```bash
cd /path/to/hermes-agent-home/hermes-agent-web
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
export HERMES_AGENT_WEB_ADMIN_PASSWORD='你的强密码'
.venv/bin/python app.py
cd hermes-agent-web
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# 在 hermes-agent-home 根目录配置 Web 密码后:
export HERMES_AGENT_WEB_ADMIN_PASSWORD='你的密码'
python app.py
# 或: python app.py --admin-password '你的密码' --host 127.0.0.1 --port 8781
```
浏览器访问终端中打印的地址(默认 **http://127.0.0.1:8781**)。
浏览器打开 http://127.0.0.1:8781 ,默认用户 `hermes`(可用 `HERMES_AGENT_WEB_ADMIN_USER` 修改)。
默认监听 **`127.0.0.1`**,仅本机可访问;若需局域网访问,设置 `HERMES_AGENT_WEB_HOST=0.0.0.0` 并自行做好访问控制。
## 功能摘要
## 环境变量
- **实例列表**:数据目录 `hermes-agent-instances/<N>/` 与 Docker 项目 `hermes-<N>` 的并集(含已停止容器),与 `./hermes-agent-cli.sh list-ids` 一致。
- **拉取镜像 / 启动 / 停止 / 重启 / 销毁**:调用 CLI 对应子命令。
- **Hermes 引导**:`/instance/<序号>/guide`,自动 `setup`(如需)→ `run` → 容器 shell。
- **终端**:`/instance/<序号>/docker`,进入运行中 gateway 容器。
- **编辑配置**:`/instance/<序号>/config`,编辑 `data/config.yaml`。
| 变量 | 说明 |
|------|------|
| `HERMES_AGENT_WEB_ADMIN_PASSWORD` | 登录密码(建议必填)。也可设为 Werkzeug 生成的哈希串(以 `pbkdf2:` / `scrypt:` 开头) |
| `HERMES_AGENT_WEB_ADMIN_USER` | 登录用户名,默认 `hermes` |
| `HERMES_AGENT_WEB_SECRET_KEY` | Flask session 签名密钥;不设置则每次进程启动随机,**重启后已登录 session 会失效** |
| `HERMES_AGENT_WEB_HOST` | 监听地址,默认 `127.0.0.1` |
| `HERMES_AGENT_WEB_PORT` | 端口,默认 `8781` |
| `HERMES_AGENT_WEB_LOG_CLI` | 是否在终端打印每次执行的 `hermes-agent-cli.sh` 命令、`exit` 码与 stdout/stderr(默认开启;`0` / `false` 关闭)。单条输出超过约 64KB 会截断 |
应用会加载 **`hermes-agent-home/.env`**(与 `HERMES_SOURCE` 等共用),无需在 `hermes-agent-web` 目录再复制一份,除非你希望单独覆盖。
## 功能简述
- **实例列表**:序号为 **数据目录下数字文件夹** 与 **Docker 里仍存在的 `hermes-<N>` 项目 / `hermes-<N>-openclaw-gateway-*` 容器** 的并集(**已停止的容器**也会出现在列表里)。与同目录 `./hermes-agent-cli.sh list-ids` 一致。
- **新建实例**:分配新序号、创建目录并执行脚本的 `bootstrap`。
- **启动**:`run --quick <序号>`。
- **停止 / 重启 / 销毁**:分别对应脚本的 `stop`、`restart`、`destroy`(**销毁**会先 `compose down`,再 **`rm -rf` 宿主上该实例目录**,不可恢复)。
- **Hermes 引导**:在实例行点 **「Hermes 引导」** 打开 **`/instance/<序号>/guide`**。进入后工作目录为 **hermes-agent-home**,可执行 `./hermes-agent-cli.sh setup`、`cli <序号> onboard` 等;旧链接 **`/instance/<N>/channels`** 会重定向到本引导页。
## CLI 对照(调试)
## Docker 核对
```bash
cd /path/to/hermes-agent-home
./hermes-agent-cli.sh check
./hermes-agent-cli.sh status 1
./hermes-agent-cli.sh stop 1
./hermes-agent-cli.sh cli 1 --help
docker ps -a --filter name=openclaw-gateway
docker ps -a --filter name=hermes-1-gateway
```
更多子命令见脚本内 `help`。
## Docker 里找不到网关?
本仓库脚本为**每个实例**创建独立 Compose **项目名** `hermes-<序号>`,网关服务名为 **`openclaw-gateway`**,容器名大致为 **`hermes-<序号>-openclaw-gateway-1`**。在 Docker Desktop 可搜 **`hermes-1`**(或你的序号)或 **`openclaw-gateway`**。执行 `docker ps -a --filter name=hermes-1-openclaw-gateway` 核对。
项目名 `hermes-<序号>`,服务 `gateway`,容器名约 `hermes-<序号>-gateway-1`。
+2 -9
View File
@@ -206,7 +206,7 @@ def _run_cli(
def _cli_compose_check() -> str | None:
"""通过脚本的 check 子命令校验 Docker、HERMES_SOURCE 与 compose(含 docker compose config)。"""
"""通过脚本的 check 子命令校验 Docker 与 compose(含 docker compose config)。"""
cp = _run_cli("check", timeout=60)
if cp.returncode != 0:
return (cp.stderr or cp.stdout or "check 失败").strip()
@@ -846,7 +846,7 @@ def docker_pty_ws(ws, iid: int):
@app.route("/instance/<int:iid>/guide")
@login_required
def instance_guide(iid):
"""引导终端:自动执行 setup(如需)→ 启动网关 → onboard,用户只应答交互提示。"""
"""引导终端:自动执行 setup(如需)→ 启动网关 → 容器 shell,用户只应答交互提示。"""
if sys.platform == "win32":
flash("网页引导终端仅支持 macOS / Linux。", "error")
return redirect(url_for("index"))
@@ -877,13 +877,6 @@ def instance_docker_terminal(iid):
)
@app.route("/instance/<int:iid>/channels")
@app.route("/instance/<int:iid>/channels/term")
@login_required
def legacy_channels_redirect(iid):
return redirect(url_for("instance_guide", iid=iid))
def main():
logging.basicConfig(
level=logging.INFO,
@@ -3,7 +3,7 @@
{% block body %}
<p><a href="{{ url_for('index') }}">← 返回实例列表</a></p>
<h2 style="margin-top:0;">实例 <code>{{ iid }}</code> · 引导终端</h2>
<p class="muted">打开本页后会<strong>自动</strong>在后台执行官方引导链路(未完成 setup 时先跑向导,再启动网关,再进入 <code>onboard</code>)。
<p class="muted">打开本页后会<strong>自动</strong>执行引导链路(未完成 setup 时先跑向导,再启动 gateway,再进入容器 shell)。
你一般<strong>不用输入命令</strong>,只需在终端里按程序提问操作;需要改配置可用「编辑配置」。</p>
<div id="term-wrap" style="height:min(75vh,620px);border:1px solid var(--border);border-radius:8px;padding:2px;background:#0c1017;"></div>
<p class="muted" style="margin-top:0.75rem;">关闭本页请先 <kbd>Ctrl+C</kbd> 结束当前命令。需联网加载 xterm(CDN)。</p>