返回 Skills 目录
dontbesilent2025/dbskill包含需要注意的行为

SKILL DETAIL

dbs-update

dontbesilent2025/dbskill/dbs-update

该技能用于更新官方 dbskill 仓库,并确保用户的存档、报告和决策记录不受影响。它只更新官方仓库 dontbesilent2025/dbskill,不涉及用户安装的其他 Skill,也不会创建后台任务或定时任务。 当用户明确要求更新、升级或检查 dbskill 版本,或在收到更新提醒后回复“1”时,此技能会执行更新操作。更新过程通过运行 npx 命令同步所有官方 Skill,并记录更新时间以避免重复提醒。成功后会提示用户新建对话以使用新能力;失败时会简要说明原因并指导用户处理权限或网络问题。

安装量 · 278查看来源

Installation

npx skills add https://github.com/dontbesilent2025/dbskill --skill dbs-update

技能文件

SKILL.md

最近同步 · 2026年10月18日

agents/openai.yaml›
interface:
  display_name: "dbs-update(更新 dbskill)"
  short_description: "按原安装渠道同步官方 dbskill 更新,保留用户存档与其他 Skill"
  default_prompt: "使用 $dbs-update,同步官方 dbskill 更新并保留用户本地资产。"
references/retired-skills.json›
{
  "skills": [
    {
      "name": "dbs-hook",
      "sha256": [
        "1d63c667d0c55e6565ca132cc791551dcbdf9940dc9876c84c7decc76b17f787",
        "234e52bd6c73dcc9a3e23391062c9d88124d9e912e690bfc4b428d100440e8ca",
        "6198fff3ea0fd68af4dd9af35ad1b15ed7492b98cb91225db8f8d2b3650385a1",
        "6e390d47956cdcc7e8e57529086436bb5492b73633647ad4e03e384b7041707d",
        "902dc2a10940c365cd4da07237117cf14c7ed8f2300782c4f9c333160193532b",
        "a7f9cf1ffe9f218d8fd91f7f2ed767fcd7294c9dbaadfbfce490e65d48329816",
        "a98318aa6f80dfdfa400e24946d1ee99a83f31ce79acf78d4aba99b021010a30",
        "af6352b3d597f6715ca63a10d4dae7f7f1a337a08ceed4d31ec31abcabab644a",
        "b406be716e55784080d55dacf11c2bc023a2f530b01cc80ec965357ec2ff7c08"
      ]
    },
    {
      "name": "dbs-xhs-title",
      "sha256": [
        "0034c63254b9a5dd4ec57fb7d9691e0a97acfb250e7c75508494e1a79a3af79b",
        "23fe0120c6ba53afcf6b927c4025ecc78704f2e18c758b74f78526fef8abcee8",
        "44ca91d64219b06c83884e353dbb9f1f86dccbd4d40b5a4b9d3a94f044a9d762",
        "acbe10ee171c2104227e5e5837003eac0ed5bd7b9685ce1220d6dd93c35edb5a",
        "c765d6e32a8850fadc6f7fd306763ca5b78995deb97e6377ae92bcac143be8c5",
        "ede07db0f582b416f669d45cf42f2b9547d135b8edf9fa17d437d5f944765a0e",
        "f4ebeff529c0526a476708b15b7c88b00791a5bc2914d4a0d15957b2187e7919"
      ]
    }
  ]
}
scripts/cleanup_retired_skills.py›
#!/usr/bin/env python3
"""清理本机残留的已下线 dbskill Skill。

只处理 references/retired-skills.json 中登记的名称,并且只处理能确认来自官方的副本:
- 失效链接(目标已不存在):移除链接;
- 指向官方历史版本的链接或目录联接:只移除链接本身,不碰目标;
- 内容与官方历史版本完全一致的目录:移到 ~/.dbs/retired-skills/<时间>/ 备份,不直接删除;
- 本工具生成、且真源已不存在的 Grok 适配层:同样移到备份目录。
内容被改过、指向其他来源或无法识别的同名项一律保留,并在结果中列出。
"""

from __future__ import annotations

import argparse
import hashlib
import json
import os
import shutil
import sys
import time
from pathlib import Path


SCRIPT_DIR = Path(__file__).resolve().parent
RETIRED_PATH = SCRIPT_DIR.parent / "references" / "retired-skills.json"

# 与 dbs-install-skill 支持的 Agent 目录保持一致,含已停止维护的旧目录。
AGENT_SKILL_DIRS = (
    ".agents", ".claude", ".codex", ".workbuddy", ".hermes", ".kiro", ".qwen", ".cline",
    ".aider-desk", ".augment", ".codeartsdoer", ".codebuddy", ".codemaker", ".codestudio",
    ".continue", ".copilot", ".cursor", ".factory", ".forge", ".gemini", ".junie",
    ".kilocode", ".openclaw", ".openhands", ".qoder", ".roo", ".trae", ".trae-cn",
    ".vibe", ".zencoder",
)


def normalized_sha256(path: Path) -> str | None:
    try:
        return hashlib.sha256(path.read_bytes().replace(b"\r\n", b"\n")).hexdigest()
    except OSError:
        return None


def is_link(path: Path) -> bool:
    return path.is_symlink() or (hasattr(os.path, "isjunction") and os.path.isjunction(path))


def remove_link(path: Path) -> None:
    if path.is_symlink():
        path.unlink()
    else:
        os.rmdir(path)  # Windows 目录联接:只移除联接本身


def grok_bridge_source(skill_file: Path) -> str | None:
    try:
        text = skill_file.read_text(encoding="utf-8")
    except OSError:
        return None
    if "## Grok Bridge" not in text:
        return None
    for line in text.splitlines():
        if line.startswith("- Source of truth: "):
            return line.removeprefix("- Source of truth: ").strip()
    return None


def plan_for(path: Path, name: str, known: set[str]) -> tuple[str, str]:
    """返回 (动作, 说明)。动作为 unlink、backup 或 keep。"""
    if is_link(path):
        target = Path(os.path.realpath(path))
        if not target.exists():
            return "unlink", "失效链接"
        if normalized_sha256(target / "SKILL.md") in known:
            return "unlink", f"指向官方旧版本的链接({target})"
        return "keep", f"链接指向其他内容({target})"
    if path.is_dir():
        skill_file = path / "SKILL.md"
        if normalized_sha256(skill_file) in known:
            return "backup", "与官方旧版本一致的副本"
        source = grok_bridge_source(skill_file)
        if source and source.replace("\\", "/").endswith(f"/skills/{name}/SKILL.md") and not Path(source).exists():
            return "backup", "真源已不存在的 Grok 适配层"
        return "keep", "内容与官方版本不一致,可能是你自己的同名 Skill"
    return "keep", "同名文件,不是 Skill 目录"


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--dry-run", action="store_true", help="只列出计划,不改动文件")
    parser.add_argument("--home", default=os.environ.get("DBS_INSTALL_HOME") or str(Path.home()))
    args = parser.parse_args()

    home = Path(args.home)
    retired = json.loads(RETIRED_PATH.read_text(encoding="utf-8")).get("skills", [])
    backup_root = home / ".dbs" / "retired-skills" / time.strftime("%Y%m%d-%H%M%S")
    result = {"dry_run": args.dry_run, "removed": [], "backed_up": [], "kept": [], "backup_dir": None}

    for entry in retired:
        name = entry["name"]
        known = set(entry.get("sha256", []))
        for agent in (*AGENT_SKILL_DIRS, ".grok"):
            path = home / agent / "skills" / name
            if not (path.exists() or is_link(path)):
                continue
            action, reason = plan_for(path, name, known)
            record = {"path": str(path), "reason": reason}
            if action == "keep":
                result["kept"].append(record)
                continue
            if action == "unlink":
                if not args.dry_run:
                    remove_link(path)
                result["removed"].append(record)
            else:
                destination = backup_root / agent.lstrip(".") / name
                if not args.dry_run:
                    destination.parent.mkdir(parents=True, exist_ok=True)
                    shutil.move(str(path), str(destination))
                    result["backup_dir"] = str(backup_root)
                record["backup"] = str(destination)
                result["backed_up"].append(record)

    print(json.dumps(result, ensure_ascii=False, indent=2))
    return 0


if __name__ == "__main__":
    sys.exit(main())
SKILL.md›
---
name: dbs-update
description: 更新官方 dbskill,并保留其他 Skill 与用户存档。用户要求更新、升级、检查 dbskill 版本,或在更新提醒后回复 1 时使用。
---

# dbs-update:更新 dbskill

用户已经明确要求更新 dbskill,或在上一条 dbskill 更新提醒后回复了 `1`。两种情况都直接执行更新,不再做第二次文字确认;宿主若要求 Shell 权限,由用户在宿主的权限窗口中决定。

只有上一条助手回复明确包含 dbskill 更新提醒时,单独回复的 `1` 才代表更新。缺少这段上下文时,不要自行解释数字含义。

## 更新范围

- 只更新官方仓库 `dontbesilent2025/dbskill`。
- 保留用户在 `~/.dbs/` 中的存档、报告和决策记录。
- 不更新用户安装的其他 Skill。
- 清理已下线的官方旧入口时,只处理能确认来自官方的副本;用户改过的或同名的自有 Skill 一律保留。
- 不创建后台任务、定时任务或 Agent Hook。

## 执行步骤

1. 判断 dbskill 的安装渠道。两种渠道可能同时存在,只更新实际检测到的渠道:

   - **Claude Code 插件**:本 Skill 所在路径包含 `/.claude/plugins/`,或 `claude plugin list` 的输出中有以 `@dontbesilent-skills` 结尾的插件。
   - **Skills CLI**:`~/.agents/skills/`、`~/.claude/skills/` 或其他 Agent 的 Skill 目录中存在 `dbs` 等官方 Skill,且它们不在 `/.claude/plugins/` 下。

2. 更新 Claude Code 插件渠道:先刷新 marketplace,再逐个更新 `claude plugin list` 中以 `@dontbesilent-skills` 结尾的插件。

   ```bash
   claude plugin marketplace update dontbesilent-skills
   claude plugin update dbs@dontbesilent-skills
   ```

   用户单独安装过其他插件(例如 `dbs-diagnosis@dontbesilent-skills`)时,对每个插件分别执行 `claude plugin update`。不要为插件用户再执行 Skills CLI 安装,否则会多出一套副本。

3. 更新 Skills CLI 渠道:

   ```bash
   npx -y skills add dontbesilent2025/dbskill -g --all
   ```

   两种渠道都检测不到时,按这个命令更新。

4. 清理已下线的官方旧入口。名单与官方历史版本指纹在本 Skill 的 [references/retired-skills.json](references/retired-skills.json):

   - **Claude Code 插件渠道**:`claude plugin list` 中以 `@dontbesilent-skills` 结尾、且名称在名单里的插件,逐个执行 `claude plugin uninstall <名称>@dontbesilent-skills`。
   - **本地 Skill 目录**:解析本 Skill 所在目录的绝对路径,运行其中的 `scripts/cleanup_retired_skills.py`(macOS 与 Linux 用 `python3`,Windows 用 `python` 或 `py`)。脚本只移除失效链接和指向官方旧版本的链接;与官方旧版本完全一致的目录移到 `~/.dbs/retired-skills/<时间>/` 备份;其余同名项保留并说明原因。
   - 当前环境没有 Python 时跳过脚本,在回复中列出名单里的名称,请用户自行检查各 Agent 的 Skill 目录。

5. 命令成功后记录本次更新时间,避免当前对话仍加载旧 Skill 时重复提醒:

   ```bash
   mkdir -p "$HOME/.dbs" && date +%s > "$HOME/.dbs/update_check_at"
   ```

6. 根据命令的退出状态确认是否完成。命令成功时告诉用户更新已完成:插件渠道提醒用户运行 `/reload-plugins` 或新建对话;Skills CLI 渠道提醒用户新建一次对话后再使用新能力。

7. 命令失败时,用一句话说明失败原因和下一步需要用户处理的权限或网络问题。不要把完整终端日志直接贴给用户,除非用户要求。

## 回复格式

成功:

> dbskill 已更新完成({更新的渠道})。当前对话如果还没有读取到新能力,{插件渠道:运行 `/reload-plugins`;其他渠道:新建一次对话}后即可使用。

清理了旧入口时追加一句:

> 已清理下线的旧入口:{名称与位置}。{有备份时:原文件备份在 `{备份目录}`。}{有保留项时:`{路径}` 与官方版本不一致,已保留。}

没有残留时不提清理。

失败:

> dbskill 没有更新完成:{简短原因}。处理完 {权限或网络问题} 后,再说一次「更新 dbskill」。

## 边界

- 用户只问版本、更新内容或是否需要更新时,先回答问题,不执行命令。
- 用户明确要求检查更新且希望实际同步时,按本 Skill 更新。
- 不使用 `npx skills update`,该命令可能更新用户安装的其他 Skill。

---

完成当前任务后直接结束。用户的请求超出本 Skill 的范围、任务完成后用户的材料里出现明确的后续需求,或用户询问下一步时,用一句话说明还需要哪种能力,不点名其他 Skill;当前环境已经安装 `/dbs` 时,补一句「可以输入 `/dbs`,由它匹配对应的 Skill」。