---
name: share-skill
description: 列出当前用户容器中实际安装的 Skill，按 openclaw skills list 返回的 source 字段分组，引导用户选择 Skill、选择虾友后直接发送 web 格式 Skill 分享卡片。Use when the user asks to share or introduce an installed Skill to a Sophclaw friend / 虾友.
---

# 向虾友介绍 Skill

用于把当前容器里实际安装的某个 Skill 按 web 前端一致的 Skill 分享卡片格式发送给虾友。必须按顺序执行：**选择 Skill → 选择虾友 → 直接发送**。

## Processing Mode

**STRICT SERIAL PROCESSING ONLY** — 不并行发送；用户选定 Skill 和虾友后直接发送，不再追加确认步骤。

## Prerequisites

- Python 3.10+、uv
- 本机存在有效 JWT：`/home/node/.openclaw/jwt.json`
- 能执行 `openclaw skills list --json`；如环境命令名不同，用脚本参数 `--skills-command` 指定
- 能执行 `openclaw skills info <name> --json`；如环境命令名不同，用脚本参数 `--skill-info-command-template` 指定
- 虾友接口与 DM 发送接口可访问，默认 API base URL：`https://yagent.sophnet.com/api`
- **所有脚本调用均使用 `uv run`**，不要直接用 `python`。

## 脚本入口

`{baseDir}` 为本 Skill 根目录：

```bash
uv run {baseDir}/scripts/share_skill_to_friend.py <command> [args...]
```

常用命令：

```bash
uv run {baseDir}/scripts/share_skill_to_friend.py list-skills
uv run {baseDir}/scripts/share_skill_to_friend.py list-friends
uv run {baseDir}/scripts/share_skill_to_friend.py send --skill "<skill-name>" --friend-id <id> --friend-name "<name>"
```

脚本会优先解析 JSON；如果 OpenClaw 命令输出包含 banner/config warnings，会自动从噪声中提取 JSON；如果实际拿到的是 `openclaw skills list` 的表格输出，也会尽量解析表格中的 Skill 名称、描述、状态和 Source。展示标签直接使用返回的 `source` 字段。

## Step 1：选择 Skill

先执行：

```bash
uv run {baseDir}/scripts/share_skill_to_friend.py list-skills
```

输出 JSON：

```json
{
  "skills": [
    {
      "index": 1,
      "name": "image-classify",
      "description": "照片分类器。通过人脸识别对照片进行分类、搜索和管理。",
      "tag": "openclaw-workspace",
      "status": "可用"
    }
  ],
  "groups": [
    { "tag": "openclaw-workspace", "collapsedByDefault": false, "count": 1, "skills": [] },
    { "tag": "openclaw-managed", "collapsedByDefault": false, "count": 0, "skills": [] },
    { "tag": "openclaw-bundled", "collapsedByDefault": true, "count": 0, "skills": [] }
  ]
}
```

向用户展示时使用以下格式。若 `description` 不是中文，先改写成自然中文再展示：

```text
🧩 **请选择要介绍给虾友的 Skill**

1️⃣ **<name>**
   📝 功能：<中文 description>

2️⃣ **<name>**
   📝 功能：<中文 description>

...

📦 **其他内置 skill**（共 <count> 个，已折叠）
   包含 openclaw-bundled、agents-skills-personal 等来源的 skill

💬 请回复 **序号** 或 **Skill 名称**。
```

**展示规则：**

1. `openclaw-workspace` 和 `openclaw-managed` 的 skill 直接列出，**不显示分组标题**
2. `openclaw-bundled` 和 `agents-skills-personal` 归入"其他内置 skill"分组，默认折叠
3. 其它 source 如出现，也归入"其他内置 skill"分组
4. 标签（如 `[openclaw-workspace]`）**不显示**，保持界面简洁
5. 排序：openclaw-workspace → openclaw-managed → 其他内置 skill

## Step 2：选择虾友

用户选定 Skill 后执行：

```bash
uv run {baseDir}/scripts/share_skill_to_friend.py list-friends
```

输出 JSON：

```json
{
  "friends": [
    {
      "index": 1,
      "friendId": 23725,
      "displayName": "小李",
      "levelName": "Sophclaw 虾友"
    }
  ]
}
```

只展示非官方客服的虾友，使用以下格式：

```text
🦞 **请选择要发送给哪位虾友**

1️⃣ **<displayName>**
   🌟 <levelIcon> <levelName>

2️⃣ **<displayName>**
   🌟 <levelIcon> <levelName>

💬 请回复 **序号** 或 **虾友昵称/备注**。
```

`displayName` 的生成规则：优先使用虾友备注名 `remark`，没有备注时使用昵称 `nickname`，都没有时显示「未命名虾友」。内部保留 `friendId` 供脚本调用，但**不要向用户展示虾友号**。如果昵称重复，只用列表序号区分，并可提示用户按序号选择。

## Step 3：发送（含敏感信息确认）

用户选定虾友后，发送自定义 Skill 前，脚本会先扫描 Skill 目录是否包含私钥、token、`.env`、凭据文件等秘钥相关敏感信息。

### 敏感信息检测

脚本会检测以下敏感信息：
- 敏感文件名：`.env`、`.env.local`、`credentials.json`、`id_rsa` 等
- 敏感文件后缀：`.pem`、`.key`、`.p12`、`.pfx` 等
- 敏感文件名关键词：`token`、`secret`、`password`、`credential`、`private_key` 等
- 文件内容：私钥块、AWS Access Key、GitHub Token、Slack Token、JWT 等

### 发送流程

首次发送（不带 `--allow-sensitive`）：

```bash
uv run {baseDir}/scripts/share_skill_to_friend.py send \
  --skill "<skill-name>" \
  --friend-id <friendId> \
  --friend-name "<display-name>" \
  --description-zh "<中文功能介绍>"
```

如果检测到敏感信息，脚本会返回错误：

```json
{
  "error": "检测到要分享的 Skill 目录中可能包含秘钥相关敏感信息。\n命中项：\n- resources/bearer_token.txt: 文件名包含敏感关键词: token\n\n如需继续发送，请添加 --allow-sensitive 参数确认。"
}
```

**此时 Agent 应向用户展示敏感信息列表，询问是否确认发送：**

```text
━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━

🚨 **安全警告：检测到敏感信息**

该 Skill 包含以下敏感内容，分享后接收方将获得完整访问权限：

| 文件路径                          | 检测原因                     |
|----------------------------------|------------------------------|
| `resources/bearer_token.txt`     | 文件名包含敏感关键词: token  |
| `scripts/send_email.py`          | 疑似秘钥字段赋值             |

⚠️ **风险提示**
• 接收方将获得这些敏感文件的完整内容
• 可能导致凭据泄露、API 被滥用等安全风险
• 建议仅在确认接收方完全可信的情况下发送

💬 请回复 **「确认发送」** 继续发送，或回复 **「取消」** 返回。

━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━ ━
```

**注意：** 表格使用标准 Markdown 格式 `| 列1 | 列2 |`，便于阅读和对齐。

用户确认后，使用 `--allow-sensitive` 参数重新发送：

```bash
uv run {baseDir}/scripts/share_skill_to_friend.py send \
  --skill "<skill-name>" \
  --friend-id <friendId> \
  --friend-name "<display-name>" \
  --description-zh "<中文功能介绍>" \
  --allow-sensitive
```

### 发送结果

发送成功后返回：

```json
{
  "success": true,
  "skill": "operations-dashboard",
  "friend": { "friendId": 34200, "displayName": "黄志举" },
  "messageId": "<message-id>",
  "message": "📝 功能介绍：...\n[claw-skill-share]\n{\"v\":1,...}\n[/claw-skill-share]"
}
```

Agent 应向用户提示：

```text
✅已发送 `operations-dashboard` skill 给虾友「黄志举」
```

如果包含敏感信息，返回结果会额外包含 `sensitiveFindings` 和 `sensitiveWarning` 字段：

```json
{
  "success": true,
  "skill": "operations-dashboard",
  "friend": { "friendId": 34200, "displayName": "黄志举" },
  "messageId": "<message-id>",
  "sensitiveFindings": [
    { "path": "resources/bearer_token.txt", "reason": "文件名包含敏感关键词: token" }
  ],
  "sensitiveWarning": "已发送包含敏感信息的 Skill，请确认接收方可信"
}
```

如果包含敏感信息，Agent 应在成功提示中提醒用户：

```text
✅已发送 `operations-dashboard` skill 给虾友「黄志举」

━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ **安全提醒**
该 Skill 已包含敏感文件一并发送给接收方：
• `resources/bearer_token.txt`

请确认接收方可信，必要时建议轮换相关凭据。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

## Safety

- 发送消息必须使用 web 前端一致的 `[claw-skill-share]` 卡片格式。
- 用户侧输出不展示内部 JSON、`packageUrl`、本地文件路径、密钥或环境变量值。
- 分享自定义 Skill 前会扫描敏感信息；命中时必须让用户确认后才可发送。
- 敏感信息检测到的文件路径和原因可向用户展示，但**不要展示文件内容或密钥值**。
- 不要替用户猜测虾友；必须让用户从列表中选择，或在用户主动提供时内部使用 `friendId`。
- 用户侧输出中不要展示虾友号 / `friendId`。
