Skip to main content
Manifest headers are comment declarations at the top of a plugin file. autClaw reads them to show plugin metadata, match messages, generate configuration forms, install dependencies, and register routes.
Regular plugin authors only need the fields on this page. IM platform adapter fields are not covered here.

Basic syntax

//[author: your-name]
//[runtime: [email protected]]
//[title: Hello]
//[description: Reply hello]
//[rule: hello]
const { Sender, getSenderID } = require('./middleware.js')

const sender = new Sender(getSenderID())
await sender.reply('hello')

Parsing rules

  • JavaScript uses //[key: value].
  • Python uses #[key: value].
  • Declarations must be in the continuous comment block at the top of the file. Declarations after the first non-comment code line are ignored as headers.
  • key is case-insensitive. Use lowercase for consistency.
  • author is required. Without author, the plugin is marked as invalid.
  • For most duplicate fields, the last value wins. rule, event, method, param, dependency, and selector fields can repeat.
  • Boolean values support true/false, 1/0, and yes/no.

Common fields

HeaderRequiredExamplePurpose
authorYesyour-namePlugin author. Use a stable English or pinyin identifier.
titleNoOrder lookupDisplay name.
descriptionNoLook up status by order IDShort description that tells users what the plugin does.
versionNo1.0.0Plugin version.
runtimeNo[email protected], [email protected]Runtime environment.
languageNojavascript, pythonUsually inferred from the file extension.
classNoToolsCategory or display group.
iconNobotDisplay icon.
disableNotrueDisable the plugin.
adminNotrueOnly administrators can trigger the plugin.
priorityNo10Trigger priority. Higher numbers run first.

Message trigger: rule

rule matches user messages. You can write multiple rule headers.
//[rule: hello]
//[rule: query (.+)]
Read regex captures with sender.param(1).
//[rule: query (.+)]
const { Sender, getSenderID } = require('./middleware.js')
const sender = new Sender(getSenderID())
const keyword = await sender.param(1)
await sender.reply(`You want to query: ${keyword}`)

Events and scheduled triggers

HeaderExamplePurpose
eventqq-notice-group_decrease-kickListen for an event. Use getEventType() / getEventData() in the plugin.
cron0 9 * * *Trigger the plugin on a schedule.
Write cron only once. It supports common 5-field expressions, expressions with seconds, and cron descriptors.
// Trigger every day at 09:00
//[cron: 0 9 * * *]

Trigger scope

Use selectors to limit which IM channels, users, or groups can trigger a plugin.
//[imtype+: qq,wx]
//[groupid+: 123456]
//[userid-: 10001,10002]
HeaderModeDescription
imtype / imtype+AllowlistOnly allow specific IM channels.
imtype-BlocklistExclude specific IM channels.
userid / userid+AllowlistOnly allow specific users.
userid-BlocklistExclude specific users.
groupid / groupid+AllowlistOnly allow specific groups or chats.
groupid-BlocklistExclude specific groups or chats.
If you write both allowlist and blocklist selectors of the same type, the allowlist wins. Avoid mixing them.

Configuration parameters: param

Use JSON in param headers to declare configuration fields. Declare one field per line.
//[param: {"key":"api_key","name":"API Key","type":"secret","required":true,"placeholder":"sk-..."}]
//[param: {"key":"enabled","name":"Enabled","type":"boolean","default":true}]
//[param: {"key":"mode","name":"Mode","type":"select","options":["fast","safe"],"default":"safe"}]
//[param: {"spliter":true,"name":"Advanced settings"}]
FieldRequiredDescription
keyYesConfig key. Separator items with spliter: true do not need it.
nameNoDisplay name. Defaults to key.
descNoConfig description.
placeholderNoInput placeholder.
requiredNoWhether the field is required.
typeNostring, boolean, number, secret, or select. Defaults to string.
secretNoTreat the field as a secret when true.
defaultNoDefault value.
optionsNoOptions for select.
scopeNoglobal or account. Defaults to global.
bindNoCurrently supports ingress_token.
spliterNoSeparator title for organizing the configuration form.

Dependencies: dependency

Use dependency to declare packages that the plugin needs. Each line is a JSON object.
//[dependency: {"name":"axios","manager":"npm","version":"1.7.9"}]
#[dependency: {"name":"httpx","manager":"pip","version":"0.27.2"}]
FieldRequiredDescription
nameYesPackage name.
managerNoPackage manager, such as npm, pip, or go.
versionNoVersion.
You can also import on demand in code: JavaScript uses importModule(...); Python uses import_module(...).

HTTP route plugins

Declare router to let a plugin handle HTTP requests.
//[author: your-name]
//[runtime: [email protected]]
//[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 })
HeaderExampleDescription
router/demo/{id}Public route path. It must start with /.
methodget, postHTTP method. Can repeat or use commas. Supports get, post, put, and delete.
serverdemoOptional service group name.
Do not use /api, /open, or /healthz as route prefixes.

Marketplace fields

If you want to publish a plugin publicly, add these fields.
//[public: true]
//[open_source: false]
//[price: 9.90]
//[billing_mode: monthly]
//[monthly_price: 3.00]
//[auto_renew_default: true]
HeaderExampleDescription
publictrueWhether to show the plugin publicly.
open_sourcefalseWhether to expose the source code.
pintrueWhether to pin the plugin.
price9.90One-time price. Non-negative with up to two decimals.
billing_modeone_time / monthlyBilling mode.
monthly_price3.00Monthly price. Non-negative with up to two decimals.
auto_renew_defaulttrueWhether auto-renew is enabled by default.

Complete example

//[author: demo]
//[runtime: [email protected]]
//[title: Claim card]
//[description: Let a user send claim-card to claim one card code]
//[version: 1.0.0]
//[rule: claim-card]
//[admin: false]
//[priority: 10]
//[param: {"key":"period_limit","name":"Period limit","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('You have already claimed a card')
  return
}

await bucketSet('card_claims', user, String(Date.now()))
await sender.reply('Claimed successfully')

Machine-readable files

Last modified on June 3, 2026