关于 sb-hub
sb-hub 是用于 Storybook 应用审计流程的只读导航与编排技能。它检查项目状态、推荐一个后续技能,或按产物门槛协调完整审计流程。
主要功能
- 01只读诊断项目就绪情况
- 02推荐一个后续工作步骤
- 03按门槛编排审计阶段
- 04依据状态和产物恢复流程
- 05转交技能异常报告
适用场景
- 01审计前检查代码仓库状态
- 02根据现有产物确定下一技能
- 03按序执行审计并创建 Storybook 内容
- 04恢复中断的审计流程
MCP 相关
它会检查 Storybook 的 addon-mcp 是否已接入,并据此选择 sb-stories 的执行路径。README 未说明它提供 MCP 服务端接口。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ strongeron/ storybook-workbench --skill sb-hub安装后在 Claude Code 中输入/sb-hub确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CONTEXT.mdagents/openai.yamlreferences/end-to-end-flow.mdrunbook.mdscripts/report-issue.sh详细介绍
sb-hub — 入门检查 · 编排 · 导航
Hub。你不会在这里编写内容——你要检查状态并进行路由。有三种只读模式;按意图选择。阅读一次 CONTEXT.md,了解共享词汇、存储映射和恢复协议。
按模式加载(不要一开始就加载两个参考文件):
references/runbook.md—— 导航引擎(状态检测 → 下一步)。在 模式 0 / 模式 2(诊断 /“接下来做什么”)时加载。references/end-to-end-flow.md(约 220 行)——“杂乱应用 → 设计系统”的完整流水线示例。仅在模式 1(编排完整审计)时加载。 对于模式 0 入门检查或模式 2 下一步查询,不要加载它——这些模式只需runbook.md。
规范上下文(单一来源)。 此软件包中恰好有一个 CONTEXT.md(共享词汇 · STORAGE MAP · 恢复)。它不会被手动重复创建:在软件包/插件安装中,每项技能都会读取同一个文件(CONTEXT.md / ${CLAUDE_PLUGIN_ROOT}/CONTEXT.md);独立运行 npx skills add <skill> 时,会附带构建过程打包的逐字节相同副本,并在更新时刷新。sb-hub 是编排器——如果技能是单独安装的,请通过 sb-hub 进行路由,以确保流水线和共享词汇保持权威。
解析软件包位置
脚本位于 scripts/。在此仓库中:${CLAUDE_PLUGIN_ROOT}/scripts/。
作为插件安装时,使用 ${CLAUDE_PLUGIN_ROOT}/scripts/。
CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}} # shared scripts: "$CORE/scripts/<name>"
选择模式
| 用户意图 | 模式 |
|---|---|
| “准备好了吗”“我该从哪里开始”,全新/未知仓库 | 0 · 入门检查 |
| “审计这个应用”“把整个流程跑完”“为这个应用构建 Storybook” | 1 · 编排 |
| “接下来做什么”,或任意动词已追加到台账之后 | 2 · 导航(默认) |
| “这不对”“行为异常”“报告 bug”,某项技能运行出错 | 3 · 报告 |
模式 0 — 入门检查(阶段 0 诊断,只读)
对于全新的杂乱应用:在运行任何动词之前,探查技术栈和就绪状态,输出报告并推荐第一步。无提示、无写入——可重复运行。
echo "━━ Phase 0 — readiness ━━"
grep -q '"react"' package.json 2>/dev/null && echo " [ok] React" || echo " [warn] no React in package.json"
grep -qE '"vite"|"@vitejs' package.json 2>/dev/null && echo " [ok] Vite" || echo " [info] not Vite (skill targets React+Vite)"
test -d .storybook && grep -q '"storybook"' package.json 2>/dev/null && echo " [ok] Storybook present" || echo " [warn] NO_STORYBOOK → start with sb-setup"
test -d node_modules && echo " [ok] node_modules present" || echo " [warn] deps not installed — run your package-manager install"
lock=$(ls package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null | head -1); echo " [info] lockfile: ${lock:-none}"
grep -q '@storybook/addon-mcp' package.json 2>/dev/null && test -f .mcp.json && echo " [info] MCP wired → sb-stories uses with-mcp" || echo " [info] no addon-mcp → without-mcp path"
if find .storybook -maxdepth 1 -name '*.json' 2>/dev/null | grep -q .; then
find .storybook -maxdepth 1 -name '*.json' | sed 's/^/ [ok] discovery: /'
else echo " [info] no discovery JSON yet → sb-inventory not run"; fi
grep -q 'storiesLocation:' .storybook/audit/status.md 2>/dev/null && echo " [ok] stories location decided" || echo " [warn] stories location undecided → sb-setup must ASK (isolated .storybook/stories/ vs co-located) before sb-stories"
操作示例——迁移到一半的应用(已安装 Storybook,尚未进行任何审计):
━━ Phase 0 — readiness ━━
[ok] React
[ok] Vite
[ok] Storybook present
[ok] node_modules present
[info] lockfile: pnpm-lock.yaml
[info] no addon-mcp → without-mcp path
[info] no discovery JSON yet → sb-inventory not run
[warn] stories location undecided → sb-setup must ASK …
→ 已存在 Storybook,但没有发现 JSON,且 stories 的位置尚未确定,因此不要直接跳到 sb-stories。先指定 sb-setup(以记录 stories 的位置),然后再指定 sb-inventory。这个顺序——先 setup,再 inventory,最后 stories——正是这道关卡的意义:[info]/[warn] 行是路由信号,不是噪声。
软件包写入的所有内容都位于 .storybook/ 下(参见 CONTEXT.md STORAGE MAP)——如果发现其他位置有输出,请标记。唯一需要做的决定是 stories 的存放位置;如果尚未确定,请指定 sb-setup(它会询问)。
发现数据是预先计算的。 发现层数据是
.storybook/下的 JSON:project-inventory(+tokens.map、storyCoverage)·component-usage·flows·design-system-health·component-states·prop-shapes·page-patterns·runtime。 前四项会在 Storybook 中渲染(嵌入的 autodocs + 封装器),并由refresh-usage.sh一起刷新;其余是编写输入(按需重新生成)。不要通过 shell 扫描重新推导脚本已经写入.storybook/*.json的内容——请读取字段。
然后输出 → Start: <first verb>——如果是 NO_STORYBOOK,则为 sb-setup,否则为 sb-inventory。不要运行该动词;只需指定它,然后停止。对于完整的新项目流程,交由模式 1 处理。
模式 1 — 编排(运行完整审计 → stories)
“端到端审计这个应用。”按顺序运行流水线,在各阶段之间设置关卡——只有在前一个产物存在后才能继续(发现脚本会原子写入,因此已存在的 JSON 就是完整的)。不要直接运行同级脚本;请调用各项专用技能并验证其输出。
sb-setup——如果 Mode 0 报告了NO_STORYBOOK,或故事文件的位置尚未确定。门槛:.storybook/和 package.json 中的"storybook"都已就位,且.storybook/audit/status.md中已记录storiesLocation(sb-setup会询问用户:使用独立的.storybook/stories/,还是与组件放在一起),并且.storybook/runtime.json已存在(discover-runtime.py——共享预览需要提供的 provider 树/根 CSS/portal/MSW),然后才能进入步骤 2。sb-inventory——识别真实组件与占位组件,以及占主导地位的设计系统。门槛:.storybook/project-inventory.json已存在。sb-health——检查设计系统健康状况。门槛:.storybook/design-system-health.json已存在;如果designSystem.mixed为真或大量使用原始十六进制颜色值,则在编写故事前提示转交/ds-runbook。sb-flows——路由图和导航边。门槛:.storybook/flows.json已存在。sb-stories <Component>——为每个需要故事的组件编写故事:按components.storyCoverage.needsStory[]的顺序处理(先处理自身没有故事且被导入最多的组件),每个组件都由validate-stories.sh自行检查。若storyCoverage.source == "storybook-index",则以storyCoverage.withRegisteredStory/needsCount作为准确的进度指标(根据 Storybook 的index.json对照——即 Storybook 实际注册的故事);否则使用withColocatedStory/needsCount(这是启发式指标;withStory只是宽松的上限——它也会计入仅为 mock 而导入的组件)。编写完成后重新运行sb-inventory(或sb-audit),以从索引刷新覆盖率并缩减needsStory[],持续迭代直至列表为空。sb-wrappers——将每个步骤的输出渲染为视图:ProjectInventory(步骤 2 之后)、DesignSystemHealth/TokenMatrix(步骤 3 的健康检查之后)、AppFlowGraph/JourneyGraph(步骤 4 之后),以及编写故事时使用的StateGrid/StateMatrix(步骤 5)。数据包装器需要先有对应步骤的 JSON——参见 sb-wrappers 中的 “When in the flow”。sb-audit——故事落地后定期调查偏移情况并生成决策看板;运行refresh-usage.sh(见下文)。
源自 Figma 的设计系统(可选分支,在步骤 1 之后)。 上述流程以代码为先(审计现有内容)。如果已批准的 Figma 文件是事实来源,则在编写故事前插入 sb-figma,以建立基础令牌的一致性:它会将 Figma MCP 变量保存到 .storybook/figma/,写入 .storybook/figma-token-parity.json(颜色/间距/字体,OKLCH→hex),为 Foundations/Colors|Tokens|Type 故事接入 figmaVar/figmaHex,并报告偏移情况。它为 sb-health(步骤 3)提供补充,而非取而代之:健康检查会检查代码内部的令牌集;sb-figma 则补充设计与代码之间、健康检查无法看到的维度。(通过 Figma 交付已批准的组件也属于 sb-figma,并通过 sb-stories 编写;仍在迭代、尚未定稿的设计则继续使用 sb-explore。)
每个阶段完成后,在 .storybook/audit/findings.md 中追加一条发现。遇到的第一个未通过的门槛处立即停止,并告知用户该修复哪个动词。(模式:带硬性门槛的有序流程,类似 lfg。)
保持渲染数据最新(使用情况层)。 四个渲染后的 JSON(inventory · component-usage · flows · design-system-health)会提供给 autodocs 使用情况嵌入内容——UsageSection 只需在 preview.ts 的 docs.page 中接入一次,就会在每个组件的文档以及每个基础内容(Colors/Semantic/Typography/Scales = 令牌表,Health = 审计发现)中添加“此应用中的实际用法”。refresh-usage.sh --docs 会一并重新运行这四项,让重建结果反映实际情况;sb-audit 每次运行都会执行此操作,并且应在 CI 中、storybook build 之前运行。(设置过程会接入 docs.page 组合——参见 sb-setup install-wizard。)
模式 2 — 导航(默认 — 指定唯一的下一步)
检查状态和账本,推荐一个且仅一个满足前置条件的下一项精确技能。
test -d .storybook && grep -q '"storybook"' package.json 2>/dev/null && echo STORYBOOK_PRESENT || echo NO_STORYBOOK
ls .storybook/*.json 2>/dev/null # which discovery JSONs exist
cat .storybook/audit/status.md 2>/dev/null # ledger / resume point
# DRIFT — source/story files changed since the last discovery (newer than the inventory JSON). Plain
# `find -newer` → cross-agent (no git, no Claude hook), works on uncommitted/untracked files. Lists the
# exact files that moved this session; if any, the discovery JSONs are stale → refresh before routing.
if [ -f .storybook/project-inventory.json ]; then
find src app components .storybook/stories \( -name '*.tsx' -o -name '*.ts' \) \
-newer .storybook/project-inventory.json 2>/dev/null | grep -v '\.storybook/.*\.json' | head -20
fi
# COVERAGE — READ the field the script already wrote (CONTEXT.md doctrine: never re-derive). Extract
# ONLY storyCoverage so the FULL object surfaces complete — never a truncated dump of the whole
# inventory. Prefer the authoritative `withRegisteredStory` (source=storybook-index, reconciled against
# index.json); fall back to the heuristic `withColocatedStory`. needsStory[] is the iterate list.
if [ -f .storybook/project-inventory.json ]; then
python3 - <<'PY'
import json
try: c = json.load(open(".storybook/project-inventory.json"))["components"]["storyCoverage"]
except Exception: raise SystemExit
src = c.get("source", "heuristic")
done = c.get("withRegisteredStory") if src == "storybook-index" else c.get("withColocatedStory", 0)
print(f"coverage: {done}/{c.get('real',0)} components have a story [{src}] · {c.get('needsCount',0)} need one")
if c.get("needsStory"):
extra = " …" if c.get("needsCount", 0) > 8 else ""
print("iterate next (sb-stories): " + ", ".join(c["needsStory"][:8]) + extra)
PY
fi
如果 DRIFT 列出了文件,说明发现阶段生成的 JSON 与代码不再匹配 — 先转到 sb-inventory(或定期检查时转到 sb-audit)进行刷新,再指定下一步:它的 refresh-usage.sh 会重新运行清单、使用情况和流程检查,并将故事覆盖情况与 Storybook 自身的 index.json(权威数据,而非根据基本文件名猜测)进行核对。然后转到下一步 — 准确指定一个:
| 状态 | 下一步 | 技能 |
|---|---|---|
NO_STORYBOOK | 将引导安装推迟到 npm create storybook@latest + npx storybook skills setup,然后进行协调 | sb-setup |
没有 project-inventory.json | 先发现真实项目与伪项目 | sb-inventory |
清单已完成,没有 design-system-health.json | 编写内容前先检查健康状况 | sb-health |
健康检查已完成,没有 flows.json | 记录导航 + 应用地图 | sb-flows |
| 清单无误,想要编写故事 | 编写一个组件 | sb-stories <Component> |
| 新建/重新设计的组件,尚未决定 — 正在迭代方案 | 沙盒迭代(+ Figma 节点) | sb-explore |
| 已批准的 Figma 设计 — 映射基础令牌(颜色/间距/字体),或交付已批准的组件 | Figma → 生产环境 Storybook | sb-figma |
| 检查 Figma 与代码的令牌一致性 /“设计系统是否与 Figma 同步” | 一致性 + 漂移报告 | sb-figma |
| 将组件关联回 Figma(Code Connect)/“在 Figma Dev Mode 中显示我的代码” | 代码 → 设计(反向) | sb-figma |
| 定期检查 | 漂移调查 + 决策面板 | sb-audit |
| Explore 达到毕业门槛 | 推广到生产环境 | sb-ship |
探索 vs 交付(两者都支持 Figma — 按阶段分流,而非按“是否使用 Figma”): 尚未决定 / 正在尝试方案 →
sb-explore(实验室)→sb-ship(毕业)。已在 Figma 中批准 →sb-figma(直接交付到生产环境)。sb-figma会自行编写基础令牌故事;对于已批准的组件,它会提取设计,然后按照sb-stories的规则编写故事。它会将每项 Figma MCP 输出保存到.storybook/figma/(清单 + 每个工具对应的文件),以便整个流水线可复现、可迭代,而不受 MCP 限制。
**恢复规则(CONTEXT.md):**读取 status.md + 检查哪些 JSON 文件存在;从第一个未完成的步骤继续。切勿将之前会话中写了一半的文件视为已完成 — 重新运行该步骤。
模式 3 — 报告(技能运行出错 / 行为异常)
当用户表示某个技能执行有误、结果意外或发生故障时,帮助他们提交一份有用的报告 — 不要只是道歉。使用 Agent 原生报告器起草报告,然后提供提交命令。
CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
"$CORE/scripts/report-issue.sh" --asked "<what they asked>" --observed "<what happened>" --expected "<what they wanted>"
如果问题由 sb-figma 引起,请添加 --gaps:草稿会按类型列出 .storybook/figma/gaps.json 中尚未解决的问题数量(不含名称或值)。
它会生成一份经过脱敏的草稿(仅包含版本信息 + .storybook/*.json 的结构/数量 — 不含源代码、令牌值或组件名称),并打印 gh issue create … 命令 + 空白 Issue URL。它不会发起网络请求 — 由用户提交。根据对话填写 --asked/--observed/--expected,向用户显示草稿路径 + gh 命令,并且仅在用户提出要求时,才主动帮他们运行 gh。如需指定其他仓库:SB_ISSUE_REPO=owner/name。一份好的报告会成为复现案例 → 新的评估用例 → 修复 → field-learnings.md 条目 — 这个循环能避免下一次运行再次遇到相同问题。
绝不(编排失败模式及其原因)
- 绝不要在关卡失败或结果为空时继续推进 Mode 1 中的流程——每个阶段的
.storybook/*.json都是下一阶段的前置条件(先准备基础设计令牌,再处理组件;先准备流程,再生成应用映射)。跳过任一阶段,后续阶段就会基于缺失的事实依据开展工作,导致产出不足却不易察觉。 - 绝不要通过 shell 扫描来重新推导 CONTEXT——脚本已经写入
.storybook/*.json文件,这些文件就是状态本身。手动搜索会导致结果偏离脚本捕获的信息和封装器渲染的内容;引用字段,不要重新计算。 - 绝不要将上一次会话中只写了一半的产物视为完整——每个文件的写入都是原子的,但中断的运行可能会在流程执行到一半时停止。检查
status.md,并从第一个未完成的步骤重新运行。 - 绝不要在这里编写内容——中心负责检查和路由。在中心编写故事或封装器会绕过专用技能自身的检查和反模式;请调用该技能。
- 绝不要手动复制
CONTEXT.md——每个技能都读取唯一的规范文件(CONTEXT.md);复制文件迟早会产生偏差。
跨 Agent
- Claude:此技能是
/sb-hub(Mode 2 /“下一步做什么”是默认模式;/sb-hub onboard或/sb-hub audit this app会选择 Mode 0 / 1)。 - Codex:
$sb-hub what's next·$sb-hub onboard·$sb-hub audit this app。 - 工作循环:运行一个动词 → 将内容追加到
.storybook/audit/findings.md→ 再次询问sb-hub(Mode 2)→ 它会指出下一个针对性技能 → 运行该技能。