# Init Hooks

> 管理 OpenClaw 容器启动时自动执行的脚本钩子。gateway 重启、pod 重启、pod 重建均不丢失（数据持久化在 workspace/.init-hooks/）。 支持 inline 命令、本地脚本（shell/python）、CDN URL（zip/tar.gz 自动下载解压）三种钩子类型。 用于：新增/查看/修改/禁用/删除启动钩子、立即测试运行、查看执行日志。 触发词：init-hooks、启动钩子、startup hook、重启初始化、pod重启执行、开机自启。 安装触发词：帮我安装 init-hooks、初始化 init-hooks、设置 init-hooks、执行 init-hooks 安装。 配置变更触发词：修改 openclaw.json、改 gateway 配置、改配置文件 → 执行后自动调用 sync_openclaw_config.py。

- Skill: `songhonglei/init-hooks` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add songhonglei/init-hooks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/songhonglei/init-hooks/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Songhonglei (https://skillmd.com/u/songhonglei)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/songhonglei/init-hooks

---


# init-hooks

- **Version**: 1.0.0
- **License**: MIT
- **Author**: Evan Song · [github.com/Songhonglei](https://github.com/Songhonglei)
- **Repository**: https://github.com/Songhonglei/better-agent-skills (skills/init-hooks)

> 管理 OpenClaw 容器/主机启动时自动执行的脚本钩子。gateway 重启、容器重启、容器重建均不丢失（数据持久化在 `workspace/.init-hooks/`）。支持 inline 命令 / 本地脚本（shell·python）/ CDN URL（zip·tar.gz 自动下载解压）三种钩子类型。

## 路径约定

```
~/.openclaw/workspace/.init-hooks/
├── hooks.json        # 注册表（truth）
├── dispatcher.sh     # 自动生成，post-init.sh 调用这个
├── last-run.log      # 每次启动执行日志
└── downloads/        # CDN URL 钩子下载缓存
    └── hook_<id>.*
```

脚本路径：

```
~/.openclaw/workspace/skills/init-hooks/scripts/
├── manage.py               # 主入口（所有 CRUD + run + install）
└── sync_openclaw_config.py # openclaw.json 多路径同步工具
```

## 操作命令速查

所有操作通过 `exec` 运行，工作目录任意：

```bash
SCRIPT="$HOME/.openclaw/workspace/skills/init-hooks/scripts/manage.py"

python3 $SCRIPT install          # 首次安装
python3 $SCRIPT list             # 列出所有钩子
python3 $SCRIPT show <id>        # 查看钩子详情
python3 $SCRIPT add ...          # 新增（见下方）
python3 $SCRIPT edit <id> ...    # 修改
python3 $SCRIPT enable <id>      # 启用
python3 $SCRIPT disable <id>     # 禁用
python3 $SCRIPT delete <id>      # 删除（需二次确认）
python3 $SCRIPT delete <id> --force  # 强制删除不确认
python3 $SCRIPT run              # 立即运行所有启用的钩子
python3 $SCRIPT run <id>         # 立即运行指定钩子
python3 $SCRIPT status           # 查看安装状态
```

## 新增钩子：三种类型

### inline（内嵌 shell 命令）

```bash
python3 $SCRIPT add \
  --name "初始化日志目录" \
  --type inline \
  --content "mkdir -p ~/logs && echo 'started' >> ~/logs/boot.log"
```

多行命令用 `\n` 分隔：

```bash
python3 $SCRIPT add \
  --name "环境变量初始化" \
  --type inline \
  --content $'export MY_VAR=hello\nmkdir -p ~/tmp'
```

### script（本地 shell 脚本）

```bash
python3 $SCRIPT add \
  --name "凭证/账号启动恢复" \
  --type script \
  --path "~/.openclaw/workspace/scripts/restore-credentials.sh"
```

### python（本地 Python 脚本）

```bash
python3 $SCRIPT add \
  --name "Agent workspace 配置" \
  --type python \
  --path "~/.openclaw/workspace/scripts/set-agents.py"
```

### CDN URL（zip/tar.gz 自动下载解压）

```bash
python3 $SCRIPT add \
  --name "远程初始化包" \
  --type script \
  --url "https://cdn.example.com/my-init.zip" \
  --entry "run.sh"         # 压缩包内入口文件名（不指定则自动找第一个 .sh/.py）
```

首次执行（启动或 `run` 命令）时自动下载解压到 `downloads/hook_<id>/`，缓存存在则直接使用，pod 重建后缓存丢失会自动重新下载。

### 追加 --order 控制执行顺序（默认步进 10）

```bash
python3 $SCRIPT add --name "..." --type inline --content "..." --order 5
```

## 修改钩子

```bash
# 改名称
python3 $SCRIPT edit 2 --name "新名称"
# 改内容
python3 $SCRIPT edit 2 --content "new command"
# 改路径
python3 $SCRIPT edit 1 --path ~/scripts/new.sh
# 改顺序
python3 $SCRIPT edit 1 --order 15
# 改为 URL 模式
python3 $SCRIPT edit 1 --url https://... --entry run.sh
```

## openclaw.json 变更必须同步持久化路径

**触发场景：** 用户说「修改 openclaw.json」「改 gateway 配置」「给我改配置」，或者用户直接提供了修改 openclaw.json 的脚本/内容。

**必须在改完后立即执行：**

```bash
SYNC="$HOME/.openclaw/workspace/skills/init-hooks/scripts/sync_openclaw_config.py"

# 场景1：Agent 直接 patch（最常用）
python3 $SYNC --patch '{"acp": {"enabled": true}}'

# 场景2：用户提供了修改脚本，执行完后自动同步
python3 $SYNC --run ~/scripts/patch_config.py

# 场景3：inline 命令修改后同步
python3 $SYNC --run-inline "sed -i 's/old/new/' ~/.openclaw/openclaw.json"

# 场景4：只同步（已手动改了 runtime）
python3 $SYNC

# 检查各处是否一致
python3 $SYNC --check
```

**同步路径（跨部署环境可配置）：**
1. `~/.openclaw/openclaw.json`（runtime，source of truth，始终维护）
2. 额外持久化目标：由环境变量 `INIT_HOOKS_SYNC_PATHS`（冒号分隔）配置，不存在的路径自动跳过

```bash
# 纯本地/单机：通常无需额外同步，留空即可（只维护 runtime 一份）

# 容器/K8s：把 runtime 之外的持久化挂载点填进来（按你自己的挂载布局替换示例）
export INIT_HOOKS_SYNC_PATHS="/app/clawconfig/openclaw.json:/app/k8s-config/clawconfig/openclaw.json"
```

未配置 `INIT_HOOKS_SYNC_PATHS` 时只维护 runtime 一份（本地环境属正常）。

## 安装流程（install）

`install` 是幂等的，可重复执行：

1. 创建 `~/.openclaw/workspace/.init-hooks/` 目录
2. 初始化 `hooks.json`（若已存在则跳过）
3. 生成 `dispatcher.sh`
4. 检查 `~/.openclaw/workspace/scripts/post-init.sh`：
   - 存在 → 在末尾追加 dispatcher 调用（有标记防重复注入）
   - 不存在 → 创建，内容只有 dispatcher 调用
5. 检查容器启动脚本（`/app/start.sh`，可用 `INIT_HOOKS_START_SH` 覆盖；本地无此文件时跳过）：
   - 已有 `# post-init hook` → 间接调用，跳过
   - 否则在末尾追加 dispatcher 直接调用

## 执行行为

- **宽松模式**：单个钩子失败不中断后续
- **顺序执行**：按 `order` 字段从小到大
- **日志**：每次执行追加到 `last-run.log`，同时 tee 到 stdout
- **执行摘要**：每次执行结束后打印成功/失败列表

## 关于 start.sh 注入

`install` 会尝试向容器启动脚本（默认 `/app/start.sh`，可用 `INIT_HOOKS_START_SH` 覆盖）注入 dispatcher 调用。大多数用户没有写权限、或本地环境根本没有这个文件，都属**正常情况**，不影响使用：
- `post-init.sh` 已注入 → dispatcher 经由 post-init.sh 间接调用
- 启动脚本注入失败/不存在提示 `ℹ️` 而非 `⚠️` 或 `❌`，无需担心

## 用户意图识别

| 用户说 | Agent 动作 |
|--------|-----------|
| 帮我安装 / 初始化 / 设置 init-hooks | `install` |
| 添加一个启动钩子 / 加一个开机执行 | `add` |
| 列出 / 查看所有钩子 | `list` |
| 查看钩子 #2 / 第2个钩子内容 | `show 2` |
| 修改钩子 #1 | `edit 1 ...` |
| 禁用 / 停用 / 关闭 钩子 #3 | `disable 3` |
| 删除钩子 #2 | `delete 2`（展示详情后二次确认） |
| 立即运行 / 测试一下 / 跑一遍 | `run` |
| 只运行钩子 #1 | `run 1` |
| 查看状态 / 安装了吗 | `status` |
| 修改 openclaw.json / 改 gateway 配置 | 改完后 `sync_openclaw_config.py` |
| 查看上次执行日志 | `read ~/.openclaw/workspace/.init-hooks/last-run.log` |

## 钩子编写规范

详见 `references/best-practices.md`，包含三种类型的完整示例、路径规范、执行顺序建议。

**核心规则：** 钩子内容禁止硬编码 `/home/node/`，必须用 `$HOME`（shell）或 `Path.home()`（Python）。

---

## 注意事项

- 每次 `add` / `edit` / `enable` / `disable` / `delete` 后，`dispatcher.sh` 自动重新生成
- CDN URL 钩子：首次 `run` 时下载，缓存在 `downloads/`；re-install 不清除缓存（需手动删 `downloads/hook_<id>/`）
- `delete --force` 跳过确认，Agent 不应使用（除非用户明确说"直接删"）
- hooks.json 是 truth，dispatcher.sh 是生成物，手动改 dispatcher.sh 会在下次操作时被覆盖

