Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

OpenClaw A2UI

v1.0.2

为 OpenClaw webchat 回复增加个性化富 UI 展示,基于 HTML 直出渲染。 【默认启用】凡是结构化内容(列表、数据、步骤、表格、摘要、状态、代码等)一律用 HTML 卡片回复。 纯文字聊天(简单问答、闲聊)不强制套卡片。 当用户要求安装/迁移 openclaw-a2ui、启用 HTML 渲染、...

0· 213·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for suuuy/openclaw-a2ui.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "OpenClaw A2UI" (suuuy/openclaw-a2ui) from ClawHub.
Skill page: https://clawhub.ai/suuuy/openclaw-a2ui
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install openclaw-a2ui

ClawHub CLI

Package manager switcher

npx clawhub@latest install openclaw-a2ui
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
Purpose & Capability
Name/description (HTML-rich card rendering for OpenClaw webchat) align with the provided code and configs: ui-config.json expands DOMPurify/markdown rules, skill-ui-bridge.js patches client behavior to detect and render <div class="a2ui"> cards, and the plugin scripts inject the bootstrap into control-ui. Files and behaviors are coherent with the stated feature.
Instruction Scope
SKILL.md instructs the agent to emit HTML cards and documents the installation steps; it does not ask the agent to read unrelated system files or secrets at runtime. The runtime JS runs in the browser to transform chat DOM elements—this is consistent with the skill's UI purpose.
!
Install Mechanism
Installation is local (no remote downloads) but the plugin injects a static JS into control-ui/index.html and writes a skill-ui-init.js into the control-ui static directory. Modifying index.html and adding same-origin script is a high-impact operation (runs arbitrary JS in every client's browser). The install script copies plugin files into extensions and edits openclaw.json — this is necessary for the plugin approach but is a privileged change that should be reviewed and backed up.
!
Credentials
The skill declares no environment variables, which is appropriate. However, the client bootstrap (skill-ui-bridge.js) reads location.hash and localStorage keys (openclaw.device.auth.v1 and openclaw.control.settings.v1) to build an Authorization header when fetching /plugins/skill-ui/manifest. The server-side manifest handler is registered with Access-Control-Allow-Origin: "*" (CORS wildcard). While the code does not transmit tokens to third-party servers, reading browser-stored tokens and exposing a manifest endpoint with permissive CORS raise privacy/attack-surface concerns you should consider.
!
Persistence & Privilege
The plugin requires persistent, system-level changes: copying files into the OpenClaw extensions directory, registering the plugin in openclaw.json, and injecting a script into control-ui/index.html that will execute in all client browsers. always:false mitigates forced global enablement, but the installation grants broad privilege (arbitrary JS execution in UI) — review and backup steps are recommended.
What to consider before installing
What to consider before installing: - This skill intentionally modifies server-side files: it copies a plugin into your OpenClaw extensions folder, edits openclaw.json, and injects a script into control-ui/index.html. Those changes will run code in every user's browser and should be reviewed and backed up before installation. - The injected client script reads certain localStorage keys and location.hash to build an Authorization header for an internal manifest fetch; it does not send those tokens to external servers in the provided code, but any script injected into index.html can be a powerful vector—ensure you trust the author and review the injected JS line-by-line. - The manifest HTTP handler sets CORS to '*'. That makes UI config manifests retrievable cross-origin; assess whether your ui-config.json files contain any sensitive information (e.g., external URLs or CSS that could leak internal data). - Recommended actions: (1) review assets/skill-ui-bridge-plugin.js and assets/skill-ui-bridge.js fully, (2) run the install in a staging instance first, (3) back up control-ui/index.html (the install script creates an .orig but confirm), (4) consider restricting CORS or adding auth checks in the manifest handler if you operate in a sensitive environment, and (5) if you are not comfortable with server-side file changes or broad client-side JS injection, do not install.
!
assets/skill-ui-bridge-plugin.js:83
File read combined with network send (possible exfiltration).
About static analysis
These patterns were detected by automated regex scanning. They may be normal for skills that integrate with external APIs. Check the VirusTotal and OpenClaw results above for context-aware analysis.

Like a lobster shell, security has layers — review code before you run it.

latestvk974eehs7s2a6m778maftp733h834bcr
213downloads
0stars
3versions
Updated 11h ago
v1.0.2
MIT-0

openclaw-a2ui

本技能已验证(2026-03-18):style / div / grid / flex / table / img / svg 全部渲染正常。 除非用户要求纯文字,否则所有结构化内容必须用 HTML 卡片输出。

Changelog

  • v1.0.2(2026-03-18):骨架屏优化
    • 骨架插入到 .chat-text 直接父节点(气泡本身),并设 inline-block + min-width: 320px 撑开气泡
    • .sui-skeleton 固定 width: 320px; display: block,解决 inline-block 气泡宽度塌陷问题
    • 骨架行结构调整:标题行 12px / 正文行 8px / 底部两段不等宽细线,比例更自然
    • 移除骨架时还原气泡 displayminWidth
  • v1.0.1(2026-03-09):流式骨架屏 + 淡入动画,findBubble 隐藏整体气泡
  • v1.0.0(待更新)单卡片模式 - 默认所有结构化回复使用单一 CompositeCard 统一承载,减少多卡片的视觉碎片化。

⚠️ HTML 不渲染?先看这里

如果 webchat 中 HTML 被显示为纯文本、标签被转义、或样式无效,不要尝试手动修改 DOMPurify 配置。根本原因是 skill-ui-bridge 插件未安装,解决方式:

现象原因解决方式
HTML 标签显示为文本(如 &lt;div&gt;marked.js 未开启 rawHTML安装 skill-ui-bridge 插件(见底部安装章节)
样式被剥离,只剩裸文字/标签DOMPurify 未 patch,style/div 等被过滤安装 skill-ui-bridge 插件(见底部安装章节)
部分标签渲染,部分不渲染插件未加载成功检查安装验证步骤 5、6

skill-ui-bridge 插件安装后会自动 patch DOMPurify 和 marked.js,无需手动配置白名单。


触发规则(优先级由高到低)

场景处理方式
结构化内容(列表、步骤、数据、表格、统计、对比、状态)必须用单一卡片显示,无文本前后缀
有标题 + 正文的摘要/说明用单一 CompositeCard 承载所有内容(单卡片模式)
代码 + 说明优先用单一 CodeCard,必要时在 Card内嵌入代码块
简单一句话回答⚪ 纯文字即可
用户明确说"纯文字"/"不要卡片"❌ 不用卡片

💡 单卡片模式强制规则:

所有结构化内容必须只用卡片显示,不要有文本 + 卡片的组合形式。

  • 正确:所有内容(标题、要点、数据)都在一个 CompositeCard 内展示
  • 错误:先写一段文字说明,再跟一个卡片
  • 错误:卡片后再追加额外解释性文本

**目标:**每张回复只出现一张卡片(或无卡片),避免视觉碎片化和信息重复。

例如:

❌ 错误写法(多元素组合):
这是关于 AI Agent 的最新趋势,请查看下方卡片。

<div class="a2ui">...

以上数据截至 3 月 18 日。

---

✅ 正确写法(单卡片模式):
<div class="a2ui">
  <!-- 标题:AI Agent 最新趋势 -->
  <!-- 数据内容 -->
  <!-- 数据来源说明 -->
  <!-- 截止时间戳 -->
</div>

输出方式(唯一方式)

直接在回复正文中输出 HTML,不要包裹在代码块里,webchat 会直接渲染。

⚠️ 强制要求:每张卡片最外层必须带 class="a2ui"

skill-ui-bridge 通过检测 class="a2ui" 识别需要渲染的 HTML,缺少此 class 的卡片不会被渲染

<!-- ✅ 正确 -->
<div class="a2ui" style="...">
  <!-- 你的卡片内容 -->
</div>

<!-- ❌ 错误,不会被渲染 -->
<div style="...">卡片内容</div>

⚠️ 关键规则:HTML 与文字必须分段

marked.js 在解析时,如果 HTML 和普通文字混在同一段落,会把 HTML 标签转义成文本显示。

❌ 错误写法(HTML 夹在文字中间):

以下是热榜内容:<div class="a2ui" style="..."></div> 感兴趣可以点击查看。

✅ 正确写法(HTML 单独成段,前后空行隔开):

以下是热榜内容:

<div class="a2ui" style=".">
  <!-- 卡片内容 -->
</div>

感兴趣可以点击查看。

规则:

  • HTML 卡片前后必须有空行(不能紧跟文字)
  • 文字说明放在卡片之前之后,单独成段
  • 单卡片模式优先:多卡片连续输出时,考虑合并为一个 CompositeCard

设计规范(所有卡片统一)

背景:    #ffffff
圆角:    12px(卡片)/ 8px(内部元素)/ 999px(badge/tag)
阴影:    0 2px 12px rgba(0,0,0,0.08)
主色:    #5865f2(蓝紫)
成功:    #22c55e
警告:    #f59e0b
错误:    #ef4444
信息:    #3b82f6
标题色:  #1a1a2e
正文色:  #374151
说明色:  #6b7280
分割线:  #f0f0f0
底色块:  #f8fafc
最大宽:  600px
外边距:  margin:8px 0
字体:    -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif

卡片模板速查

TextCard — 文字摘要

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#5865f2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
    <strong style="font-size:16px;color:#1a1a2e">【标题】</strong>
  </div>
  <hr style="border:none;border-top:1px solid #f0f0f0;margin:0 0 14px">
  <p style="color:#374151;line-height:1.7;margin:0;font-size:14px">【正文内容】</p>
</div>

ListCard — 列表/要点

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <strong style="font-size:16px;color:#1a1a2e;display:block;margin-bottom:12px">【标题】</strong>
  <hr style="border:none;border-top:1px solid #f0f0f0;margin:0 0 14px">
  <ul style="list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:10px">
    <li style="display:flex;align-items:flex-start;gap:10px">
      <svg style="flex-shrink:0;margin-top:2px" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
      <span style="color:#374151;font-size:14px;line-height:1.5">【列表项】</span>
    </li>
  </ul>
</div>

DataCard — 键值对 / 参数

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
    <strong style="font-size:16px;color:#1a1a2e">【标题】</strong>
    <span style="background:#dcfce7;color:#16a34a;font-size:12px;padding:3px 10px;border-radius:999px;font-weight:600">【状态 badge,可选】</span>
  </div>
  <hr style="border:none;border-top:1px solid #f0f0f0;margin:0 0 14px">
  <div style="display:flex;flex-direction:column;gap:0">
    <div style="display:flex;justify-content:space-between;align-items:center;padding:9px 0;border-bottom:1px solid #f8fafc">
      <span style="color:#6b7280;font-size:14px">【字段名】</span>
      <span style="color:#1a1a2e;font-weight:500;font-size:14px">【字段值】</span>
    </div>
  </div>
</div>

StatsCard — 统计数字

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <strong style="font-size:16px;color:#1a1a2e;display:block;margin-bottom:14px">【标题】</strong>
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px">
    <div style="text-align:center;padding:14px 8px;background:#f8fafc;border-radius:10px">
      <div style="font-size:26px;font-weight:800;color:#5865f2;line-height:1">【数字】</div>
      <div style="font-size:11px;color:#6b7280;margin-top:4px">【说明】</div>
    </div>
  </div>
</div>

AlertCard — 提示/警告/成功/错误

<!-- info -->
<div class="a2ui" style="background:#eff6ff;border-left:4px solid #3b82f6;border-radius:0 8px 8px 0;padding:12px 16px;display:inline-flex;gap:10px;align-items:flex-start;font-family:-apple-system,sans-serif;margin:8px 0">
  <span style="font-size:16px;flex-shrink:0">ℹ️</span>
  <div><div style="font-size:13px;font-weight:600;color:#1e40af;margin-bottom:2px">【标题】</div><div style="font-size:13px;color:#1e3a8a">【内容】</div></div>
</div>
<!-- success: bg=#f0fdf4 border=#22c55e title-color=#15803d text-color=#14532d emoji=✅ -->
<!-- warning: bg=#fffbeb border=#f59e0b title-color=#b45309 text-color=#92400e emoji=⚠️ -->
<!-- error:   bg=#fef2f2 border=#ef4444 title-color=#b91c1c text-color=#991b1b emoji=❌ -->

StepsCard — 步骤流程

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <strong style="font-size:16px;color:#1a1a2e;display:block;margin-bottom:16px">【标题】</strong>
  <div style="display:flex;flex-direction:column;gap:0">
    <!-- 非最后一步(有连接线) -->
    <div style="display:flex;gap:14px">
      <div style="display:flex;flex-direction:column;align-items:center">
        <div style="width:28px;height:28px;border-radius:50%;background:#5865f2;color:#fff;font-size:13px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0">1</div>
        <div style="width:2px;background:#e5e7eb;flex:1;margin:4px 0"></div>
      </div>
      <div style="padding-bottom:16px">
        <div style="font-size:14px;font-weight:600;color:#1a1a2e;margin-bottom:4px">【步骤标题】</div>
        <div style="font-size:13px;color:#6b7280">【步骤说明】</div>
      </div>
    </div>
    <!-- 最后一步(绿色圆圈,无连接线) -->
    <div style="display:flex;gap:14px">
      <div style="display:flex;flex-direction:column;align-items:center">
        <div style="width:28px;height:28px;border-radius:50%;background:#22c55e;color:#fff;font-size:13px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0">N</div>
      </div>
      <div>
        <div style="font-size:14px;font-weight:600;color:#1a1a2e;margin-bottom:4px">【最后步骤】</div>
        <div style="font-size:13px;color:#6b7280">【说明】</div>
      </div>
    </div>
  </div>
</div>

TableCard — 数据表格

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0;overflow-x:auto">
  <strong style="font-size:16px;color:#1a1a2e;display:block;margin-bottom:14px">【标题】</strong>
  <table style="width:100%;border-collapse:collapse;font-size:13px">
    <thead>
      <tr style="background:#f8fafc">
        <th style="text-align:left;padding:8px 12px;color:#6b7280;font-weight:600;border-bottom:2px solid #f0f0f0">【列名】</th>
      </tr>
    </thead>
    <tbody>
      <tr style="border-bottom:1px solid #f0f0f0">
        <td style="padding:9px 12px;color:#374151">【值】</td>
      </tr>
    </tbody>
  </table>
</div>

Badge 色值参考:

  • 成功/完成:background:#dcfce7;color:#16a34a
  • 进行中:background:#fef9c3;color:#b45309
  • 失败/错误:background:#fee2e2;color:#b91c1c
  • 中性/待定:background:#f1f5f9;color:#475569

ProgressCard — 进度条

<div class="a2ui" style="background:#fff;border-radius:12px;padding:20px;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <strong style="font-size:16px;color:#1a1a2e;display:block;margin-bottom:14px">【标题】</strong>
  <div style="display:flex;flex-direction:column;gap:12px">
    <div>
      <div style="display:flex;justify-content:space-between;margin-bottom:5px">
        <span style="font-size:13px;color:#374151">【项目名】</span>
        <span style="font-size:13px;font-weight:600;color:#22c55e">【百分比】</span>
      </div>
      <div style="background:#f0f0f0;border-radius:999px;height:8px;overflow:hidden">
        <div style="width:【百分比】;height:100%;background:linear-gradient(90deg,#22c55e,#4ade80);border-radius:999px"></div>
      </div>
    </div>
  </div>
</div>

CompositeCard — 推荐:单一复合卡片(承载所有内容)

✅ 单卡片模式最佳实践示例:

<div class="a2ui" style="background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <div style="background:linear-gradient(135deg,#5865f2,#7c3aed);padding:20px 20px 16px">
    <div style="font-size:18px;font-weight:700;color:#fff;margin-bottom:4px">🔥 今日热门新闻精选</div>
    <div style="font-size:13px;color:rgba(255,255,255,0.8)">3 月 18 日 • AI | 国际局势 | 国家发展 | 体育快讯</div>
  </div>
  <div style="padding:16px 20px">
    <!-- 使用 flex/grid 布局嵌入所有子内容 -->
    <div style="display:flex;flex-direction:column;gap:14px">
      <!-- 国际焦点模块 -->
      <div style="background:#f8fafc;border-radius:8px;padding:12px">
        <div style="font-size:13px;font-weight:600;color:#5865f2;margin-bottom:6px">📰 国际焦点</div>
        <div style="font-weight:600;color:#1a1a2e;margin-bottom:4px;font-size:14px">中东冲突升级:以军击毙伊朗高级官员,霍尔木兹海峡受阻影响全球能源</div>
        <p style="color:#374151;font-size:13px;line-height:1.6;margin:0">以色列国防部长宣称在空袭中击毙两名伊朗高级官员,其中包括前核谈判战略顾问拉里贾尼和志愿民兵指挥官苏莱曼尼。受霍尔木兹海峡袭击影响,全球油价大幅上涨,布伦特原油突破100美元/桶。</p>
        <div style="font-size:12px;color:#6b7280;margin-top:8px">📍 来源:新华社/央视新闻</div>
      </div>
      <!-- 科技前沿模块 -->
      <div style="background:#f8fafc;border-radius:8px;padding:12px">
        <div style="font-size:13px;font-weight:600;color:#22c55e;margin-bottom:6px">💻 科技前沿</div>
        <div style="font-weight:600;color:#1a1a2e;margin-bottom:4px;font-size:14px">AI技术迎来重大突破:英伟达推开源AI代理平台,阿里巴巴发布"悟空"AI工作平台</div>
        <p style="color:#374151;font-size:13px;line-height:1.6;margin:0">英伟达推出开源AI代理平台NemoClaw,预测业务规模有望突破1万亿美元。阿里巴巴发布全球首个企业原生AI工作平台"悟空",将嵌入钉钉。</p>
        <div style="font-size:12px;color:#6b7280;margin-top:8px">📍 来源:财新/36氪</div>
      </div>
    </div>
    <!-- 底部标签栏 -->
    <div style="display:flex;gap:8px;margin-top:14px;padding-top:12px;border-top:1px solid #f0f0f0">
      <a href="#" style="background:#5865f2;color:#fff;font-size:13px;font-weight:600;padding:8px 16px;border-radius:8px;text-decoration:none;display:inline-block">🔗 查看详情</a>
      <a href="#" style="background:#f8fafc;color:#374151;font-size:13px;font-weight:600;padding:8px 16px;border-radius:8px;text-decoration:none;display:inline-block;border:1px solid #e5e7eb">⚙️ 更多选项</a>
    </div>
  </div>
</div>

CodeCard — 代码展示

<div class="a2ui" style="background:#1e1e2e;border-radius:12px;overflow:hidden;max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <div style="display:flex;align-items:center;justify-content:space-between;padding:10px 16px;background:#2a2a3e">
    <span style="font-size:12px;color:#a0a0b8;font-weight:600">【语言,如 bash / python / typescript】</span>
    <div style="display:flex;gap:6px">
      <div style="width:10px;height:10px;border-radius:50%;background:#ff5f56"></div>
      <div style="width:10px;height:10px;border-radius:50%;background:#ffbd2e"></div>
      <div style="width:10px;height:10px;border-radius:50%;background:#27c93f"></div>
    </div>
  </div>
  <pre style="margin:0;padding:16px;overflow-x:auto;font-size:13px;line-height:1.6;color:#cdd6f4;font-family:'Fira Code','Cascadia Code',Consolas,monospace">【代码内容】</pre>
</div>

ImageCard — 图片展示

<div class="a2ui" style="background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 2px 12px rgba(0,0,0,0.08);max-width:600px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;margin:8px 0">
  <img src="【URL】" alt="【描述】" style="width:100%;height:200px;object-fit:cover;display:block">
  <div style="padding:14px 16px">
    <div style="font-size:15px;font-weight:700;color:#1a1a2e;margin-bottom:4px">【标题】</div>
    <div style="font-size:13px;color:#6b7280;line-height:1.5">【说明】</div>
  </div>
</div>

组合使用与最佳实践

单卡片模式(推荐)

  • 所有内容放入一个 CompositeCard,用子模块划分信息块
  • 减少视觉碎片化,提升阅读体验
  • 适合:新闻汇总、报告摘要、任务清单等多元素场景
<!-- ✅ 单卡片模式:所有信息在一个 CompositeCard 中 -->
<div class="a2ui" style="...">
  <header>标题区域</header>
  <content>
    <section>模块1: 国际焦点</section>
    <section>模块2: 科技前沿</section>
    <section>模块3: 国家发展</section>
  </content>
  <footer>底部标签栏</footer>
</div>

⚠️ 多卡片模式(特殊需求时使用)

  • 仅在特殊需求时使用:如独立代码块 + 独立说明的分离场景
<!-- ⚠️ 多卡片模式 -->
<div class="a2ui">代码展示卡片</div>
<div class="a2ui">说明文字卡片</div>

规则:

  • 多卡片连续输出时,卡片之间不需要空行(margin:8px 0 已处理间距)
  • 优先使用单卡片模式:考虑合并为一个 CompositeCard

不使用卡片的场景

  • 单句回答("好的"、"明白了"、"没问题")
  • 闲聊/情感性回复
  • 用户明确要求纯文字

详细参考

  • references/html-templates.md — 带真实示例数据的完整 HTML 模板
  • references/templates.md — A2UI v0.9 JSONL 格式模板
  • references/components.md — A2UI 组件参考(布局/展示/交互)
  • references/html-card-templates.md — 简化版 HTML 模板
  • references/ui-config-schema.md — ui-config.json 字段说明

安装

所有依赖文件已随技能打包,无需克隆任何外部仓库。assets/ 目录包含:

  • skill-ui-bridge.js — 浏览器端 bootstrap 脚本(v2)
  • skill-ui-bridge-plugin.js / skill-ui-bridge-plugin.json — openclaw plugin(v2)

只读取完成当前步骤所必需的文件。遇到无法理解的内容(如编译产物、二进制文件)立即停止,不要继续探索无关文件。

安装原理(v2):plugin 在 gateway_start 时:

  1. 读取 workspace/skills/ 下所有 ui-config.json,生成 manifest JSON
  2. 将 manifest + bootstrap JS 合并写成 skill-ui-init.js,放到 control-ui 静态目录(同源,通过 CSP script-src 'self'
  3. index.html 中注入 <script src="./skill-ui-init.js"></script>
  4. gateway_stop 时还原 index.html,删除 skill-ui-init.js

浏览器加载 skill-ui-init.js 后,bootstrap 脚本通过 MutationObserver 监听 .chat-text 容器,检测到包含 <div class="a2ui"> 的消息时,用自有白名单净化并渲染为富卡片。

安装前,先探测所有必要路径,再执行安装脚本。不得假设或写死任何路径

第一步:探测路径

依次从常见配置目录向外搜索,记录每项的实际输出结果:

# 1. 找本技能目录
find /etc "$HOME" /usr/local /opt -path "*/skills/openclaw-a2ui" -type d 2>/dev/null | head -5

# 2. 找所有 openclaw.json,列出全部路径
find /etc "$HOME" /usr/local /opt -name "openclaw.json" 2>/dev/null | head -10

根据输出结果判断:

  • 若存在多个 openclaw.json,读取每个文件的内容,选择正在被 gateway 实际使用的那个(判断依据:文件可写、且 plugins 字段中的修改重启后不会消失)。通常是 $HOME/.openclaw/openclaw.json 而非 /etc/ 下的只读镜像层副本。
  • extensions 目录默认为 $HOME/.openclaw/extensions,也可从选定的 openclaw.jsonplugins.load.paths 中读取。
  • workspace 目录默认为 $HOME/.openclaw/workspace
  • 确认 scripts/install.ts 存在后再继续。

第二步:运行安装脚本

用第一步探测到的实际路径执行:

node --experimental-strip-types <技能目录>/scripts/install.ts \
  --openclaw-config <openclaw.json 路径> \
  --extensions-dir <extensions 目录路径> \
  --workspace-dir <workspace 目录路径>

参数均可省略,脚本会自动探测默认路径。

安装脚本会完成:

  • Plugin 文件复制到 extensions 目录
  • Plugin 注册到 openclaw.json(allow / load.paths / entries 三处)
  • ui-config.json 复制到 workspace/skills/openclaw-a2ui/(若不存在)

第三步:通知用户重启

⚠️ Agent 无法自行完成此步骤:重启 gateway 意味着重启当前容器进程,必须由用户在宿主机执行。

告知用户执行以下操作:

容器化部署(docker compose):

docker compose restart openclaw

本机直接部署

openclaw gateway restart

重启后提示用户在浏览器强制刷新(Ctrl+Shift+R)。

安装验证

安装并重启后,依次执行以下检查(全部通过才算成功):

1. Plugin 文件已复制

ls <extensions-dir>/skill-ui-bridge/
# 预期:index.js  openclaw.plugin.json  skill-ui-bridge.js

2. Plugin 已正确注册到 openclaw.json

openclaw.json 的 plugins 字段应包含以下三处(缺任何一处都会导致插件不加载):

{
  "plugins": {
    "allow": ["skill-ui-bridge"],
    "load": { "paths": ["<extensions-dir>"] },
    "entries": { "skill-ui-bridge": { "enabled": true } }
  }
}

3. index.html 已注入(gateway 重启后)

grep "skill-ui-init" <openclaw-dist>/control-ui/index.html
# 预期:<script src="./skill-ui-init.js"></script>

4. 浏览器 Console 验证

F12 打开 Console,Ctrl+Shift+R 强制刷新,应看到:

[skill-ui-bridge] boot ok, tags: 45 attrs: 34

卸载

node --experimental-strip-types <技能目录>/scripts/uninstall.ts \
  --openclaw-config <openclaw.json 路径> \
  --extensions-dir <extensions-dir> \
  --remove-plugin-files

卸载后同样需要通知用户重启(见第三步)。

Comments

Loading comments...