npm
Documentation

Hold Rein 文档

01

安装

本地安装

本地安装依赖 Node.js 22 及以上版本。确认 Node 环境满足要求后,可以通过 npm 全局安装 Hold Rein CLI。

npm install @hold-rein/cli -g

Docker 安装

Docker 方式适合把运行时固定在容器环境中,并通过数据卷保存本地配置与运行数据。

Dockerfile
FROM node:22-bookworm-slim

ARG HOLD_REIN_VERSION=latest
ARG NPM_REGISTRY=https://registry.npmmirror.com

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    git \
    ca-certificates \
    openssh-client \
    python3 \
    make \
    g++ \
  && rm -rf /var/lib/apt/lists/*

ENV PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ENV GIT_BINARY="/usr/bin/git"
ENV PYTHON="/usr/bin/python3"
ENV npm_config_python="/usr/bin/python3"
ENV npm_config_registry="https://registry.npmmirror.com"
ENV NPM_CONFIG_REGISTRY="https://registry.npmmirror.com"

RUN npm config set registry "${NPM_REGISTRY}" \
  && npm install --global "@hold-rein/cli@${HOLD_REIN_VERSION}" \
  && npm cache clean --force

EXPOSE 3001

VOLUME ["/root/.hold-rein"]

CMD ["hold-rein", "start", "--host", "0.0.0.0", "--port", "3001"]
docker-compose.yml
services:
  hold-rein:
    build:
      context: .
      args:
        HOLD_REIN_VERSION: latest
        NPM_REGISTRY: https://registry.npmmirror.com
    ports:
      - "3001:3001"
    volumes:
      - hold-rein-data:/root/.hold-rein
    environment:
      npm_config_registry: https://registry.npmmirror.com
      NPM_CONFIG_REGISTRY: https://registry.npmmirror.com
    restart: unless-stopped

volumes:
  hold-rein-data:
启动命令
docker compose build
docker compose up -d
02

启动

启动本地服务

安装完成后,在需要工作的项目目录中执行启动命令。Hold Rein 会启动内置 API 运行时与 Web 控制台,默认监听127.0.0.1:3001

hold-rein start
  • API 运行时负责加载 Agent、工具、插件与本地配置。
  • Web 控制台启动后直接在浏览器中访问,用来查看和操作当前工作台。
  • 工作目录建议在项目根目录启动,让文件夹自然成为当前工作台边界。

自定义监听地址与端口

默认只监听本机地址。如果需要在容器、局域网或远程开发环境中访问,可以通过--host--port 指定监听方式。

hold-rein start --host 0.0.0.0 --port 4000
--host指定监听地址。使用 0.0.0.0 时,服务会接受外部网络访问。
--port指定 Web 控制台与 API 服务端口,适合避开本机已有服务。

插件开发模式

开发本地插件时,使用 --plugin-dev 加载插件源码。源码变化后运行时会自动重载,适合调试工具、 前端扩展和设置页。

hold-rein start --plugin-dev ./plugins/my-plugin

Docker 启动后访问

如果使用上面的 Docker Compose 配置,容器会把内部 3001 端口映射到宿主机 3001 端口。启动完成后访问http://127.0.0.1:3001 即可进入控制台。

查看运行状态
docker compose ps
03

插件开发

初始化

hold-rein plugin init 是插件脚手架命令。直接执行时会在当前目录生成插件包; 通过 --path 指定插件根目录,通过 --name 指定新插件文件夹名,两者可以组合使用。

hold-rein plugin init --path ./plugins --name my-plugin
输出
Initialized plugin package hold-rein-plugin-my-plugin

生成时包名会使用目标文件夹名拼出 hold-rein-plugin-<folder-name>,插件 id 会写入src/plugin-id.ts,格式是 __<folder-name>__plugin。如果目标文件已存在, 初始化会拒绝覆盖,避免误删已有插件代码。

生成目录结构
my-plugin/
├─ package.json
├─ tsconfig.json
├─ vite.config.ts
├─ vite.web.config.ts
└─ src/
   ├─ plugin-id.ts
   ├─ server.ts
   └─ web.ts
  • package.json声明 server/web 两个导出入口、构建脚本,以及 @hold-rein/plugin-server、@hold-rein/plugin-web、React、Ant Design 等 peerDependencies。
  • vite.config.ts构建服务端入口 src/server.ts,输出 ESM 与 CJS,Node 内置模块、Express 与 Hold Rein 运行时依赖会作为 external。
  • vite.web.config.ts构建浏览器端入口 src/web.ts,开发时接入共享依赖插件,产物默认是 web.umd.cjs 与 style.css。
  • tsconfig.json启用 strict、declaration、Bundler moduleResolution 与 react-jsx,声明文件会输出到 dist。
  • src/plugin-id.ts集中导出 PLUGIN_ID,服务端与 Web 端共用同一个插件身份。
  • src/server.ts默认导出 ServerPlugin.Plugin,可继续补 registerRoutes 与 contributionResolver。
  • src/web.ts默认导出 WebPlugin.Plugin,可继续补面板、设置页、发送区动作和工具渲染。

服务端 API

服务端插件实现 ServerPlugin.Plugin。最小字段是 id;需要扩展 API 时实现registerRoutes,需要影响 Agent 运行时则实现 contributionResolver;需要在加载后初始化时实现onLoaded

registerRoutes(context)返回 Express Router,宿主会挂载到 /plugin/<plugin-id>。context 提供 sendSuccess、sendError 与响应码定义。
contributionResolver(context)可返回静态 Contribution,也可以按 RuntimeContext 动态构建插件能力。
onLoaded({ hostApi })每次服务端插件加载或开发热重载后依次执行,可通过插件作用域的宿主 API 完成初始化;钩子失败会中止本次加载。
tools、skills、skillDirs、systemPrompts把工具、内联技能、技能目录和系统提示注入 Agent 运行时。
subscribe、onAgentEnd订阅 AgentHarnessEvent,或在一轮 Agent 结束后返回 AgentContinuation 继续任务。

RuntimeContext 会带上当前 agentName、env、session、model、thinkingLevel、prompt、taskId 等信息;RunAgentInputAgentEndInput 则用于收尾和续跑场景。

src/server.ts
import type { ServerPlugin } from "@hold-rein/plugin-server";
import { Router } from "express";

import { PLUGIN_ID } from "./plugin-id";

const serverPlugin: ServerPlugin.Plugin = {
  id: PLUGIN_ID,
  async onLoaded({ hostApi }) {
    const result = await hostApi.plugins.list();
    console.log(result.data);
  },
  registerRoutes({ sendSuccess }) {
    const router = Router();
    router.get("/status", (_request, response) => {
      sendSuccess(response, { ready: true });
    });
    return router;
  },
  contributionResolver: (context) => ({
    tools: [],
    skills: [],
    systemPrompts: [
      `Current workspace: ${context.env.cwd}`
    ]
  })
};

export default serverPlugin;

Web 端 API

Web 插件实现 WebPlugin.Plugin,通过 contributionResolver 返回界面扩展。 resolver 的 RuntimeContext 提供 request<TData> 调用插件服务端 API, 也提供 subscribeAppUi 订阅当前 UI 状态。

rightPanels、settings注册右侧面板和设置项,组件可以读取消息、任务状态、工作区路径等 props。
senderActions、senderSuggestions扩展输入区动作与触发式建议,适合插入模板、命令或上下文片段。
toolRenders、turnFooterRenders自定义工具调用展示和单轮消息尾部渲染,让插件数据进入会话流。
tools、skills、systemPrompts声明浏览器运行时工具、浏览器技能与提示词,工具参数使用 TypeBox schema 描述。

构建请求时传入 pathmethodqueryheadersbody。例如 request<TData>({ path: "/plugin/__my__plugin/status", method: "GET" })会返回统一的 { code, data, msg } 结果。

src/web.ts
import type { WebPlugin } from "@hold-rein/plugin-web";

import { PLUGIN_ID } from "./plugin-id";

const webPlugin: WebPlugin.Plugin = {
  id: PLUGIN_ID,
  contributionResolver: ({ request }) => ({
    rightPanels: [],
    senderActions: [],
    tools: [],
    settings: []
  })
};

export default webPlugin;