> ## Documentation Index
> Fetch the complete documentation index at: https://autclaw.shop/llms.txt
> Use this file to discover all available pages before exploring further.

# autClaw 插件 manifest 声明头

> 在 autClaw 插件文件顶部声明 author、runtime、rule、param、dependency、router 和 cron 等 manifest headers。

Manifest headers 是插件文件顶部的注释声明。autClaw 读取这些声明来显示插件信息、匹配消息、生成配置表单、安装依赖和注册路由。

<Note>
  普通插件作者只需要关注本页字段。连接新 IM 平台时，请继续看 [`适配器插件开发规范`](/cn/plugin-sdk/adapter-development)。
</Note>

## 基本写法

<Tabs>
  <Tab title="JavaScript">
    ```js theme={null}
    //[author: your-name]
    //[runtime: node@22.22.1]
    //[title: Hello]
    //[description: 回复 hello]
    //[rule: hello]
    const { Sender, getSenderID } = require('./middleware.js')

    const sender = new Sender(getSenderID())
    await sender.reply('hello')
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    #[author: your-name]
    #[runtime: python@3.12]
    #[title: Hello]
    #[description: 回复 hello]
    #[rule: hello]
    from middleware import Sender, getSenderID

    sender = Sender(getSenderID())
    sender.reply("hello")
    ```
  </Tab>
</Tabs>

## 解析规则

* JavaScript 使用 `//[key: value]`。
* Python 使用 `#[key: value]`。
* 声明必须放在文件顶部的连续注释区；遇到第一行非注释代码后，后面的声明不会作为头部声明读取。
* `key` 不区分大小写，建议统一写小写。
* `author` 必填。缺少 `author` 时插件会被标记为 manifest 无效。
* 大多数字段重复时采用最后一个值；`rule`、`event`、`method`、`param`、`dependency` 和选择器字段可以重复。
* 布尔值支持 `true/false`、`1/0`、`yes/no`。

## 常用字段

| Header        |  必填 | 示例                           | 作用                  |
| ------------- | :-: | ---------------------------- | ------------------- |
| `author`      |  是  | `your-name`                  | 插件作者。建议使用稳定英文或拼音标识。 |
| `title`       |  否  | `订单查询`                       | 展示名称。               |
| `description` |  否  | `按订单号查询状态`                   | 简短说明，让用户知道插件能做什么。   |
| `version`     |  否  | `1.0.0`                      | 插件版本。               |
| `runtime`     |  否  | `node@22.22.1`、`python@3.12` | 指定运行环境。             |
| `language`    |  否  | `javascript`、`python`        | 通常可由文件扩展名自动识别。      |
| `class`       |  否  | `工具`                         | 分类或展示分组。            |
| `icon`        |  否  | `bot`                        | 展示图标。               |
| `disable`     |  否  | `true`                       | 禁用插件。               |
| `admin`       |  否  | `true`                       | 仅管理员可触发。            |
| `priority`    |  否  | `10`                         | 触发优先级，数字越高越优先。      |

## 适配器补充字段

这些头注主要给 `plugin/adapters/` 下的适配器 worker 使用。完整接入流程见 [`适配器插件开发规范`](/cn/plugin-sdk/adapter-development)。

| Header              | 示例                            | 作用                                                                                                               |
| ------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `im_type`           | `qq`                          | 渠道稳定标识。                                                                                                          |
| `transport`         | `ws`、`http`                   | 外部入站传输方式。                                                                                                        |
| `account_id_key`    | `bot_id`                      | 账号配置里用于生成 `account_id` 的字段。                                                                                      |
| `receive_token_key` | `token`                       | 外部平台请求里 token 的 query key。                                                                                       |
| `supports_qr_login` | `true`                        | 声明适配器提供扫码登录入口。它只影响设置页入口展示；真正发起扫码流程还要求当前 worker 在 `adapter_worker_ready.aut_params.supports_qr_login` 中同步声明运行时能力。 |
| `media`             | `{"requires_file_path":true}` | 只有本地 SDK 必须读取文件路径时才声明。                                                                                           |

## 消息触发：rule

`rule` 用来匹配用户消息。你可以写多个 `rule`。

```js theme={null}
//[rule: hello]
//[rule: 查询 (.+)]
```

正则捕获的内容可以通过 `sender.param(1)` 读取。

<CodeGroup>
  ```js JavaScript theme={null}
  //[rule: 查询 (.+)]
  const { Sender, getSenderID } = require('./middleware.js')
  const sender = new Sender(getSenderID())
  const keyword = await sender.param(1)
  await sender.reply(`你要查询：${keyword}`)
  ```

  ```python Python theme={null}
  #[rule: 查询 (.+)]
  from middleware import Sender, getSenderID
  sender = Sender(getSenderID())
  keyword = sender.param(1)
  sender.reply(f"你要查询：{keyword}")
  ```
</CodeGroup>

## 事件和定时触发

| Header  | 示例                              | 作用                                                    |
| ------- | ------------------------------- | ----------------------------------------------------- |
| `event` | `qq-notice-group_decrease-kick` | 监听事件。插件内用 `getEventType()` / `getEventData()` 读取事件信息。 |
| `cron`  | `0 9 * * *`                     | 定时触发插件。                                               |

`cron` 只能写一次。支持常见 5 段表达式，也支持带秒的表达式和 cron 描述符。

```js theme={null}
// 每天 9 点触发
//[cron: 0 9 * * *]
```

## 触发范围

用选择器限制插件在哪些 IM、用户或群里生效。

```js theme={null}
//[imtype+: qq,wx]
//[groupid+: 123456]
//[userid-: 10001,10002]
```

| Header                 | 模式   | 说明             |
| ---------------------- | ---- | -------------- |
| `imtype` / `imtype+`   | 允许名单 | 只允许指定 IM 渠道触发。 |
| `imtype-`              | 排除名单 | 排除指定 IM 渠道。    |
| `userid` / `userid+`   | 允许名单 | 只允许指定用户触发。     |
| `userid-`              | 排除名单 | 排除指定用户。        |
| `groupid` / `groupid+` | 允许名单 | 只允许指定群或会话触发。   |
| `groupid-`             | 排除名单 | 排除指定群或会话。      |

同一类选择器同时写允许名单和排除名单时，按允许名单处理。建议不要混用。

## 配置参数：param

`param` 用 JSON 声明配置项。每一行声明一个配置项。

```js theme={null}
//[param: {"key":"api_key","name":"API Key","type":"secret","required":true,"placeholder":"sk-..."}]
//[param: {"key":"enabled","name":"启用","type":"boolean","default":true}]
//[param: {"key":"mode","name":"模式","type":"select","options":["fast","safe"],"default":"safe"}]
//[param: {"spliter":true,"name":"高级设置"}]
```

| 字段            |  必填 | 说明                                                         |
| ------------- | :-: | ---------------------------------------------------------- |
| `key`         |  是  | 配置键。`spliter: true` 的分隔项不需要。                               |
| `name`        |  否  | 展示名称；不填时使用 `key`。                                          |
| `desc`        |  否  | 配置说明。                                                      |
| `placeholder` |  否  | 输入框占位提示。                                                   |
| `required`    |  否  | 是否必填。                                                      |
| `type`        |  否  | `string`、`boolean`、`number`、`secret`、`select`。默认 `string`。 |
| `secret`      |  否  | 设为 `true` 时按密钥类型处理。                                        |
| `default`     |  否  | 默认值。                                                       |
| `options`     |  否  | `select` 的选项。                                              |
| `scope`       |  否  | `global` 或 `account`。默认 `global`。                          |
| `bind`        |  否  | 当前支持 `ingress_token`。                                      |
| `spliter`     |  否  | 分隔标题，用来组织配置表单。                                             |

## 依赖：dependency

用 `dependency` 提前声明插件需要的包。每一行是一个 JSON 对象。

```js theme={null}
//[dependency: {"name":"axios","manager":"npm","version":"1.7.9"}]
```

```python theme={null}
#[dependency: {"name":"httpx","manager":"pip","version":"0.27.2"}]
```

| 字段        |  必填 | 说明                        |
| --------- | :-: | ------------------------- |
| `name`    |  是  | 包名。                       |
| `manager` |  否  | 包管理器，例如 `npm`、`pip`、`go`。 |
| `version` |  否  | 版本号。                      |

也可以在代码里按需导入：JavaScript 使用 `importModule(...)`，Python 使用 `import_module(...)`。

## HTTP 路由插件

声明 `router` 后，插件可以处理 HTTP 请求。

<CodeGroup>
  ```js JavaScript theme={null}
  //[author: your-name]
  //[runtime: node@22.22.1]
  //[title: Demo API]
  //[router: /demo/{id}]
  //[method: post]
  const { Sender, getSenderID } = require('./middleware.js')

  const sender = new Sender(getSenderID())
  const params = await sender.getRouterParams()
  const body = await sender.getRouterBody()
  await sender.response({ ok: true, id: params.id, body })
  ```

  ```python Python theme={null}
  #[author: your-name]
  #[runtime: python@3.12]
  #[title: Demo API]
  #[router: /demo/{id}]
  #[method: post]
  from middleware import Sender, getSenderID

  sender = Sender(getSenderID())
  params = sender.getRouterParams()
  body = sender.getRouterBody()
  sender.response({"ok": True, "id": params.get("id"), "body": body})
  ```
</CodeGroup>

| Header   | 示例           | 说明                                               |
| -------- | ------------ | ------------------------------------------------ |
| `router` | `/demo/{id}` | 公开路由路径，必须以 `/` 开头。                               |
| `method` | `get`、`post` | 请求方法。可重复，也可用逗号分隔。支持 `get`、`post`、`put`、`delete`。 |
| `server` | `demo`       | 服务分组名称，可选。                                       |

不要使用 `/api`、`/open`、`/healthz` 作为路由前缀。

## Marketplace 字段

如果你要公开发布插件，可以补充这些字段。

```js theme={null}
//[public: true]
//[open_source: false]
//[price: 9.90]
//[billing_mode: monthly]
//[monthly_price: 3.00]
//[auto_renew_default: true]
```

| Header               | 示例                     | 说明               |
| -------------------- | ---------------------- | ---------------- |
| `public`             | `true`                 | 是否公开展示。          |
| `open_source`        | `false`                | 是否公开代码内容。        |
| `pin`                | `true`                 | 是否置顶。            |
| `price`              | `9.90`                 | 一次性价格，非负，最多两位小数。 |
| `billing_mode`       | `one_time` / `monthly` | 收费模式。            |
| `monthly_price`      | `3.00`                 | 月付价格，非负，最多两位小数。  |
| `auto_renew_default` | `true`                 | 默认是否自动续费。        |

## 完整示例

```js theme={null}
//[author: demo]
//[runtime: node@22.22.1]
//[title: 领卡]
//[description: 用户发送 claim-card 后领取一次卡密]
//[version: 1.0.0]
//[rule: claim-card]
//[admin: false]
//[priority: 10]
//[param: {"key":"period_limit","name":"周期限制","type":"number","default":1}]
//[dependency: {"name":"dayjs","manager":"npm"}]
const { Sender, getSenderID, bucketGet, bucketSet } = require('./middleware.js')

const sender = new Sender(getSenderID())
const user = await sender.getUserID()
const claimed = await bucketGet('card_claims', user)

if (claimed) {
  await sender.reply('你已经领取过了')
  return
}

await bucketSet('card_claims', user, String(Date.now()))
await sender.reply('领取成功')
```

## 机器可读文件

* JSON Schema：[`schemas/plugin-manifest.schema.json`](https://autclaw.shop/cn/plugin-sdk/schemas/plugin-manifest.schema.json)
* JavaScript 类型声明：[`types/middleware-js.d.ts`](https://autclaw.shop/cn/plugin-sdk/types/middleware-js.d.ts)
