dby-update

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

dby-update:把本鸭对账到最新

dby-update: Reconcile Benya to the Latest Version

用户已明确要求更新都爆鸭(本鸭)。直接执行,不再做第二次文字确认;宿主若要 Shell 权限,由用户在宿主权限窗口里决定。
User has explicitly requested to update Doubaoya (Benya). Execute directly without a second confirmation; if the host requires shell permissions, the user will decide in the host permission window.

这个 skill 干的是「对账」,不是「更新」

This Skill Does "Reconciliation", Not "Update"

让本机这套本鸭 skill 等于上游当前全集:
  • 归档上游已经下架的(否则它们会永久停在被砍前的旧契约上,调用必然报错)
  • 装上新增的
  • 刷新内容哈希落后于上游当前版的;已经是当前版的一个都不动
所以「本机已经和上游一致」时,它的结论就是无需任何操作——一个包都不会重下。 真想把某个包重装一遍(比如文件坏了),用
--force-refresh
全量重下。
⚠️ 别用
npx skills update
:它只更新「已经装了的」,永远删不掉上游已下架的那些。 老用户机器上常见几十个早就砍掉的平台垂类 skill,
update
一辈子摸不到它们。
Make the local set of Benya skills equal to the current full upstream set:
  • Archive packages removed from upstream (otherwise they will remain on the old contract before being removed, and calls will definitely result in errors)
  • Install newly added packages
  • Refresh packages whose content hash is outdated compared to the current upstream version; leave those already on the current version untouched
So when "the local set is already consistent with upstream", the conclusion is no action required — not a single package will be re-downloaded. If you really want to reinstall a certain package (e.g., the file is corrupted), use
--force-refresh
to re-download all packages in full.
⚠️ Don't use
npx skills update
: It only updates "already installed" packages, and will never remove those already removed from upstream. It's common for long-time users to have dozens of platform-specific skills that were removed long ago, and
update
will never touch them.

怎么判断「这包是不是本鸭发的」

How to Determine "Is This Package Released by Benya?"

判据是 slug × 内容哈希这一对,不看它当初是从哪个源装的。 上游
known-hashes.json
是一份闭集, 记着本鸭发布过的每一个 slug 的每一版内容哈希;先拿目录名索到那一栏,再比内容哈希。于是有三态:
状态判据处置
当前版哈希 = 上游当前版保留,不刷新(除非
--force-refresh
我们的旧版哈希命中闭集里某个历史版可归档、可替换
你动过手slug 是本鸭的,但哈希谁都不命中🔴 跳过并列进报告,一个字都不动,连刷新都不给(刷新会盖掉你的改动)
别人家的slug 根本不在闭集里不碰
这样改名(本仓早期叫
redfox-community
)、
source
字段缺失、别家有同名包,都不会判错。
The criterion is the pair of slug × content hash, regardless of which source it was originally installed from. The upstream
known-hashes.json
is a closed set that records the content hash of each version of every slug released by Benya; first look up the entry by directory name, then compare the content hash. There are three states:
StatusCriterionDisposal
Current VersionHash = Current upstream versionKeep, do not refresh (unless
--force-refresh
is used)
Our Old VersionHash matches a historical version in the closed setCan be archived or replaced
You Modified ItSlug belongs to Benya, but hash doesn't match any in the set🔴 Skip and include in report, leave untouched, no refresh allowed (refresh will overwrite your changes)
Third-PartySlug is not in the closed setLeave untouched
This way, name changes (the repository was originally called
redfox-community
), missing
source
fields, and third-party packages with the same name will not be misjudged.

删除一律做成「归档」

Deletion is Always Done as "Archiving"

要下架的包移进
<scope>/.doubaoya/archive/<时间戳>/
,不做
rm
,同目录留一份
manifest.json
写明每个包原来在哪、怎么移回去。多一个目录的成本,换「删错了还能捞回来」。
三件配套的事,转述结果时都要带上
  • 怎么捞回来:脚本在归档后会直接打印一条可复制粘贴的复原命令(读 manifest 逐条移回原处)。 原样转给用户,别只说「见 manifest」。移回去 skill 立刻能用(宿主按目录读),只是
    npx skills list
    的安装记录已被清掉,想让 CLI 也认回来就重装一次。
  • 归档目录对 git 隐形:归档根落在用户自己的项目仓里,所以脚本会在
    .doubaoya/.gitignore
    写一个
    *
    自忽略整个目录(用户已有该文件就不动)。不改用户的
    .gitignore
  • 🔴 受 git 跟踪的包一律不归档:如果某个上游已下架的包在用户仓库里是被 git 跟踪的 (把 skill 版本化进仓库是真实存在的用法),归档就等于从人家工作区里删受跟踪文件。 脚本会跳过它们、单列一栏点名说明——这一栏必须原样转述给用户,由用户自己决定怎么处理。
Packages to be removed are moved to
<scope>/.doubaoya/archive/<timestamp>/
instead of being deleted with
rm
, and a
manifest.json
is left in the same directory stating where each package was originally located and how to move it back. The cost of an extra directory is exchanged for "being able to recover if deleted by mistake".
Three supporting tasks, must all be included when relaying results:
  • How to recover: After archiving, the script will directly print a copy-pasteable recovery command (reads the manifest to move each package back to its original location). Relay this to the user exactly as is, don't just say "see manifest". The skill will be usable immediately after moving back (the host reads by directory), but the installation record in
    npx skills list
    has been cleared; to make the CLI recognize it again, reinstall it once.
  • Archive directory is invisible to git: The archive root is located in the user's own project repository, so the script will write a
    *
    in
    .doubaoya/.gitignore
    to ignore the entire directory automatically (leave it untouched if the user already has this file). Do not modify the user's
    .gitignore
    .
  • 🔴 Packages tracked by git are never archived: If a package removed from upstream is tracked by git in the user's repository (versioning skills into the repository is a real usage), archiving would be equivalent to deleting tracked files from the user's workspace. The script will skip them and list them separately with an explanation — this section must be relayed to the user exactly as is, and the user decides how to handle them.

执行步骤

Execution Steps

1. 找到对账脚本

1. Locate the Reconciliation Script

按顺序找第一个存在的:
~/.claude/skills/dby-update/scripts/reconcile.mjs
~/.agents/skills/dby-update/scripts/reconcile.mjs
./.claude/skills/dby-update/scripts/reconcile.mjs
./.agents/skills/dby-update/scripts/reconcile.mjs
找不到说明本机装的是旧版 dby-update(还没有对账能力)。先跑一次下面这条把自己升级上来,然后重新找一遍
bash
npx -y skills add zizhanovo/doubaoya-community -g -s '*' -a claude-code universal -y
Find the first existing one in order:
~/.claude/skills/dby-update/scripts/reconcile.mjs
~/.agents/skills/dby-update/scripts/reconcile.mjs
./.claude/skills/dby-update/scripts/reconcile.mjs
./.agents/skills/dby-update/scripts/reconcile.mjs
If not found, it means the local installation is an old version of dby-update (which doesn't have reconciliation capability). First run the following command to upgrade itself, then look again:
bash
npx -y skills add zizhanovo/doubaoya-community -g -s '*' -a claude-code universal -y

2. 先看清单(🔴 显式给 scope,别靠 auto 猜)

2. First Check the List (🔴 Explicitly specify scope, don't rely on auto-guessing)

bash
node <上一步找到的路径> --dry-run --scope global              # 当初带 -g 装的(最常见)
node <上一步找到的路径> --dry-run --scope project --project-dir <项目目录>
为什么必须显式给
--scope auto
是按当前工作目录猜的。cwd 选错时,目标 scope 里 一个本鸭包都没有 ⇒ 计划静默变成「整仓新增 N 个、归档 0 个」——凭空多出一整套副本, 而真正该清的死包一个没清,而且这份计划长得完全正常。脚本现在会对这种情况打一行 ⚠️ 警告,看到就停下来先确认 scope,别直接执行。
不确定装在哪,就两个都看一眼(
--scope global
一次、
--scope project --project-dir <目录>
一次)。
它会联网取上游全集与历史闭集,然后打印要归档哪些、要装哪些、要刷新几个、以及哪些因为你动过手而不碰, 这一步一个字都不会改。把这份清单原样转述给用户——尤其是「要归档」那几个的名字, 以及「你改过的」那几个(那是在告诉用户:这些我认出来你动过,所以不动它们)。
bash
node <path found in previous step> --dry-run --scope global              # Installed with -g initially (most common)
node <path found in previous step> --dry-run --scope project --project-dir <project directory>
Why explicit specification is necessary:
--scope auto
guesses based on the current working directory. If the cwd is chosen incorrectly, there are no Benya packages in the target scope ⇒ the plan silently becomes "add N packages to the entire repository, archive 0" — an entire duplicate set is added out of nowhere, while none of the dead packages that should be cleared are touched, and this plan looks completely normal. The script now prints a ⚠️ warning for this situation; stop and confirm the scope before proceeding, don't execute directly.
If unsure where it's installed, check both (once with
--scope global
, once with
--scope project --project-dir <directory>
).
It will fetch the full upstream set and historical closed set online, then print which packages will be archived, which will be installed, how many will be refreshed, and which will be left untouched because you modified them. No changes are made in this step. Relay this list to the user exactly as is — especially the names of the packages "to be archived" and those "you modified" (this tells the user: these are recognized as your modifications, so they are left untouched).

3. 确认后执行

3. Execute After Confirmation

用户看过清单、认可了,再跑(scope 参数和上一步给的保持一致):
bash
node <路径> --yes --scope <上一步用的那个> [--project-dir <目录>]
脚本会自己完成:归档 → 拉齐全集 → 复核 → 自检(skill 有没有落盘、
DOUBAOYA_API_KEY
在不在、 doubaoya.com 连不连得通),最后打印一份结果,并告诉用户归档放在哪。
退出码
0
全通过;
3
对账做完了但自检有项没过;
1
用户取消;
2
需要确认但当前不是交互终端;
4
出错。
After the user has reviewed the list and approved it, run (keep the scope parameter consistent with the previous step):
bash
node <path> --yes --scope <the one used in previous step> [--project-dir <directory>]
The script will complete the following on its own: archive → fetch the full set → review → self-check (whether skills are saved to disk, whether
DOUBAOYA_API_KEY
exists, whether doubaoya.com is reachable), finally print a result and tell the user where the archive is located.
Exit codes:
0
= all passed;
3
= reconciliation completed but self-check failed on some items;
1
= user canceled;
2
= confirmation required but not in an interactive terminal;
4
= error occurred.

4. 转述结果

4. Relay Results

  • 全通过 → 告诉用户归档了几个、装了几个、现在共几个、归档目录在哪、怎么把归档捞回来 (把脚本打的那条复原命令原样贴给用户),并提醒新建一次对话才能读到新能力。 如果有「你改过的」「受 git 跟踪所以没动的」「git 判不出来所以跳过的」这几类,必须各单独说一句, 别让用户以为它们被漏掉了。🔴 后两类别混着说:前者是「这是你自己版本化的包,要清你自己
    git rm
    」, 后者是「这台机器上的 git 没能回答我,你先修好 git 再重跑」——用户该做的事完全不同。
  • 本机已经和上游一致 → 脚本会直接说「无需任何操作」,照实转述,别自己补一句「已刷新 N 个」。
  • 自检有 ❌ → 明确说卡在哪一步(是 skill 没落盘、还是没配钥匙、还是连不上服务),把脚本给的那句处理建议一起带上。别笼统说「失败了」。
  • All passed → Tell the user how many were archived, how many were installed, the total number now, where the archive directory is, how to recover the archive (paste the recovery command printed by the script exactly as is), and remind the user to start a new conversation to access new capabilities. If there are categories like "you modified", "not archived due to git tracking", "skipped because git couldn't determine", must mention each separately, don't let the user think they were missed. 🔴 Don't mix the latter two: the former means "this is your versioned package, use
    git rm
    to clear it yourself", while the latter means "git on this machine couldn't answer me, fix git first then re-run" — the user's required actions are completely different.
  • Local set is already consistent with upstream → The script will directly say "no action required", relay exactly as is, don't add a sentence like "refreshed N packages".
  • Self-check has ❌ → Clearly state where it got stuck (whether skills weren't saved to disk, no API key configured, or couldn't connect to the service), and include the handling suggestion provided by the script. Don't just say "failed".

常用参数

Common Parameters

参数作用
--dry-run
只看清单,绝不执行
--yes
跳过确认直接执行(只在用户已经看过清单之后用
--force-refresh
连「已经是当前版」的包也重下一遍。默认只刷新落后的;这个旗标留给「我这个包坏了想重装」
--verbose
连「别人家的」和「你改过的」一起列名字
--scope auto|global|project
🔴 每次都显式给。默认
auto
是按 cwd 猜的,猜错会静默变成「整仓重装」。当初带
-g
装的就是
global
--project-dir <目录>
项目级安装在别的目录时指定
--json
机器可读输出
--self-check
离线自检脚本自身(不联网)
ParameterFunction
--dry-run
Only check the list, never execute
--yes
Skip confirmation and execute directly (only use after the user has reviewed the list)
--force-refresh
Re-download even packages that are already on the current version. By default, only refresh outdated ones; this flag is for "my package is corrupted and I want to reinstall it"
--verbose
List names of third-party packages and modified ones as well
--scope auto|global|project
🔴 Always specify explicitly. Default
auto
guesses based on cwd, which can silently lead to "full repository reinstall" if guessed wrong. If installed with
-g
initially, use
global
--project-dir <directory>
Specify when installed at the project level in another directory
--json
Machine-readable output
--self-check
Offline self-check of the script itself (no internet connection required)

边界

Boundaries

  • 只碰本鸭发过的包,判据是上面那张三态表(内容哈希命中闭集)。 别人家的、以及你自己动过手的,一个字都不动。
  • 要下架的包是移进归档目录,不是删掉,随时能按
    manifest.json
    移回来;归档目录自带
    .gitignore
    对 git 隐形,不会污染用户仓库。
  • 🔴 受 git 跟踪的包一个都不归档;git 探测跑不通、判不出来的,同样保守跳过,宁可少归档一个。 两种情形脚本会分两栏打出来,因为处置不同(自己
    git rm
    vs 先修 git)。
  • 不动你的本地数据 / 配置
    wechat-article-pipeline
    config.json
    ip-profile
    的创作 DNA、 封面 / 草稿等产出文件都不受影响——对账只覆盖 skill 目录里受版本管理的那些文件。
  • 不创建后台任务、定时任务或 Agent Hook。
  • 用户只问「有什么更新 / 现在什么版本 / 要不要更」→ 先回答,不执行
    --dry-run
    正好用来回答这个)。 明确要实际同步时才跑第 3 步。
  • 只想更新某一个 skill:
    npx -y skills update <skill 名> -g
    ,只碰点名那个(但它不会做对账)。
  • Only touch packages released by Benya, based on the three-state table above (content hash matches the closed set). Leave third-party packages and your modified ones completely untouched.
  • Packages to be removed are moved to the archive directory instead of being deleted, and can be moved back at any time according to
    manifest.json
    ; the archive directory has its own
    .gitignore
    to be invisible to git, so it won't pollute the user's repository.
  • 🔴 Never archive packages tracked by git; if git detection fails or can't determine, skip conservatively rather than archive incorrectly. The script will print these two situations in separate sections because the handling is different (use
    git rm
    yourself vs fix git first).
  • Do not touch your local data / configuration:
    wechat-article-pipeline
    's
    config.json
    ,
    ip-profile
    's creative DNA, cover/draft output files, etc., are not affected — reconciliation only overwrites files under version management in the skill directory.
  • Do not create background tasks, scheduled tasks, or Agent Hooks.
  • If the user only asks "what updates are there / what version is it now / should I update", answer first, don't execute (
    --dry-run
    is exactly for answering this). Only run step 3 when explicit synchronization is requested.
  • To update only a single skill:
    npx -y skills update <skill name> -g
    , which only touches the specified skill (but it doesn't perform reconciliation).

语言

Language

用户用中文就用中文回复,用英文就用英文回复。
Reply in Chinese if the user uses Chinese, reply in English if the user uses English.