ui(shadcn/ui)贡献者开发指南:Monorepo 结构、本地 CLI 调试与 Registry 构建流水线
本文基于仓库根目录的 CONTRIBUTING.md 展开,系统讲解 shadcn/ui 这个 pnpm + Turborepo monorepo 的目录结构、本地开发启动流程、shadcn CLI 的本地调试方法、组件注册表(registry)的构建规则与提交规范。读完后,你能够独立完成:克隆仓库并跑起官网 dev server、在本地对 CLI 进行端到端调试、修改组件后正确地执行 registry 定向构建,并按仓库约定提交代码。
一、Monorepo 架构与工具链
CONTRIBUTING.md 开宗明义:这是一个 monorepo,开发依赖三套核心工具:
- pnpm workspaces:管理多包依赖与跨包脚本过滤(
--filter); - Turborepo:作为构建系统,负责任务编排、缓存与依赖感知执行;
- changesets:管理
packages/下可发布包的版本与发布。
这三点在仓库配置中都有直接对应:
-
pnpm-workspace.yaml 声明了工作区范围,
apps/*与packages/*下的包均纳入工作区,同时通过排除规则把测试夹具目录排除在外:packages: - "apps/*" - "packages/*" - "!**/test/**" - "!**/fixtures/**" - "!**/temp/**" - "!packages/tests/temp/**" -
根 package.json 的
scripts字段展示了 Turborepo 的用法:build、lint、typecheck、check等脚本都走turbo run <task>,而针对特定工作区的操作则直接用 pnpm 过滤,例如v4:dev即pnpm --filter=v4 dev(见 package.json)。同时release脚本为changeset version(package.json),印证了 changesets 在发布流程中的角色。根目录还安装了@commitlint/cli与@commitlint/config-conventional(package.json),并在仓库中配有 .commitlintrc.json 与 .changeset/ 目录,分别支撑下文第五、七节的提交规范与发布流程。 -
turbo.json 定义了各任务的缓存与依赖关系,其中与贡献者日常最相关的有:
dev任务标记为persistent: true(长期驻留,不缓存);test任务dependsOn: ["^build"]且cache: false(测试前会先构建被依赖的包);build任务的outputs中明确包含了public/r/styles/**与styles/**——这正是 registry 构建产物的缓存声明。
二、仓库目录结构
CONTRIBUTING.md 给出的结构图与职责表如下:
apps
└── v4
├── app
├── components
├── content
└── registry
└── new-york-v4
├── example
└── ui
packages
└── shadcn
| Path | Description |
|---|---|
apps/v4/app |
The Next.js application for the website. |
apps/v4/components |
The React components for the website. |
apps/v4/content |
The content for the website. |
apps/v4/registry |
The registry for the components. |
packages/shadcn |
The shadcn package. |
结合当前仓库的实际目录可以补充几点文档没有展开的事实:
apps/v4是名为v4的 Next.js 应用(见 apps/v4/package.json),content/docs目录下按主题划分为installation、components、dark-mode、forms、changelog等子目录;apps/v4/registry下除文档提到的new-york-v4外,还有bases/、styles/、__components__/等目录,它们共同构成 registry 流水线(详见第四节);- 仓库根目录还有
templates/(CLI 安装组件时的项目模板源)与packages/tests/(跨包的 CLI 集成测试)等目录,是理解 CLI 行为时值得关注的部分。
三、首次本地启动:从 Fork 到 Dev Server
CONTRIBUTING.md 给出的标准开发步骤为:
1. Fork 并克隆仓库
在仓库页面右上角点击 Fork 按钮,然后克隆到你的本机:
git clone <你 fork 后的仓库地址>
(原文档中使用 git clone https://github.com/your-username/ui.git,请替换为你自己的 fork 地址。)
2. 进入目录并创建分支
cd ui
git checkout -b my-new-branch
3. 安装依赖
pnpm install
根 package.json 通过 packageManager 字段锁定 pnpm@10.33.4,建议保持版本一致以避免依赖解析差异。此外 pnpm-workspace.yaml 配置了 minimumReleaseAge: 2880(48 小时),即默认拒绝安装发布不足 48 小时的依赖,这是对依赖供应链的一种加固策略。
4. 运行工作区
文档说明可以使用 pnpm --filter=[WORKSPACE] 来启动任意工作区,给出了两个例子:
-
运行
ui.shadcn.com官网:pnpm --filter=v4 devFresh clone 提示(原文档强调):生成的样式文件并未提交到 git。第一次启动 dev server 前,需先执行一次
pnpm --filter=v4 registry:build --style all。如果忘了执行,dev server 会快速失败并明确提示这一点。从 apps/v4/package.json 看,
dev脚本的实际实现是pnpm icons:dev & next dev --turbopack --port 4000——它会并行启动图标构建的 watch 模式(scripts/build-icons.ts --watch)与 Next.js dev server(Turbopack,端口 4000)。这个端口信息对下一节本地调试 CLI 很关键。 -
运行
shadcn包:pnpm --filter=shadcn dev对应 packages/shadcn/package.json 中的
dev: "tsup --watch",即以 tsup 的 watch 模式持续构建 CLI 包,适合在修改 CLI 源码时热更新。
四、本地调试 shadcn CLI
CONTRIBUTING.md 的 "Running the CLI Locally" 一节给出的工作流是两终端并行:
-
一个终端启动 dev server(即上一节的
pnpm --filter=v4 dev,根目录等价命令为):pnpm dev根 package.json 中
dev即turbo run dev,会拉起v4工作区的官网服务。 -
另一个终端测试 CLI:
pnpm shadcn要在指定项目中测试,可加上
-c指向目标应用:pnpm shadcn <init | add | ...> -c ~/Desktop/my-app这个命令之所以能测到"本地最新版",原因在于根 package.json 中
shadcn脚本的定义:pnpm --filter=shadcn start:dev,而 packages/shadcn/package.json 中start:dev的完整内容是:cross-env REGISTRY_URL=http://localhost:4000/r SHADCN_TEMPLATE_DIR=../../templates node dist/index.js也就是说:
REGISTRY_URL被指到本地 dev server 的/r路由(官网 4000 端口),CLI 拉取的组件 JSON 全部来自你本地刚构建的 registry,而不是线上版本;SHADCN_TEMPLATE_DIR指向仓库内的templates/目录,init命令使用的就是仓库里的模板源。
这正是文档总结的:"This workflow ensures that you are running the most recent version of the registry and testing the CLI properly in your local environment."(该工作流确保你运行的是最新版本的 registry,并在本地环境正确地测试 CLI。)
作为对照,
start:prod会把REGISTRY_URL指向线上https://ui.shadcn.com/r(packages/shadcn/package.json),用于验证线上行为;包还声明了engines.node >= 20.18.1(packages/shadcn/package.json),运行 CLI 需满足该 Node 版本要求。
五、文档(MDX)开发
CONTRIBUTING.md 指出:本项目文档位于 v4 工作区内,本地运行方式同样是 pnpm --filter=v4 dev;文档使用 MDX 编写,源文件位于 apps/v4/content/docs 目录。
仓库中可以进一步印证:
- apps/v4/content/docs 下按
installation、components、registry、changelog等模块组织,每个模块目录内含meta.json控制导航排序; - apps/v4/package.json 的
postinstall脚本是fumadocs-mdx,说明文档栈基于 Fuma Docs 的 MDX 方案,安装依赖时会自动完成 MDX 预处理。
六、组件(Registry)开发:改动、文档与构建
CONTRIBUTING.md 的 "Components" 一节说明:组件开发采用 registry 系统,组件源码位于 apps/v4/registry,按 style 组织,结构示意如下:
apps
└── v4
└── registry
└── new-york-v4
├── example
└── ui
新增或修改组件时,文档要求满足三点:
- 为每一种 style 都做相应修改;
- 更新文档;
- 执行
pnpm registry:build更新 registry。
registry 流水线的源码级细节
文档要求参阅 apps/v4/registry/README.md 了解流水线结构与更快的定向构建模式。该 README 补充了大量 CONTRIBUTING.md 未覆盖的关键事实:
- 手写源(source of truth):
bases/base/与bases/radix/是两套手写的 base registry(Base UI 与 Radix),styles/style-*.css是风格 token 文件(nova、sera、vega等),new-york-v4/是遗留的手写源 registry; - 生成产物(不可手改):
__index__.tsx、__blocks__.json、bases/__index__.tsx、styles/<style>/ui/*(以及base-nova、radix-nova的ui-rtl)与可安装的public/r/*JSON,均由scripts/build-registry.mts生成; - 风格模型(style model):所有 base(
base、radix)与所有风格 token(nova、sera…)的交叉组合(如base-nova、radix-sera)是生成的,registry/<组合>/目录内容不入库;而new-york-v4是遗留源 registry,直接手写并提交,--style new-york-v4会被拒绝,应改用--registry new-york-v4。
定向构建模式(快速本地迭代)
文档中提到的快速构建模式在 apps/v4/registry/README.md 中有完整定义:
pnpm registry:build --examples # examples/__index__.tsx
pnpm registry:build --indexes # runtime registry indexes
pnpm registry:build --style base-nova # styles/base-nova/ui (+ ui-rtl)
pnpm registry:build --style all # every generated combination
pnpm registry:build --registry base-nova # public/r/styles/base-nova
pnpm registry:build --registry all # every style, incl. new-york-v4
| Flag | Rebuilds | Run after |
|---|---|---|
--examples |
../examples/__index__.tsx |
adding, removing, or renaming a demo |
--indexes |
bases/__index__.tsx, __index__.tsx, __blocks__.json, public/r/index.json |
changing registry or block metadata |
--style <style|all> |
../styles/<style>/ui and ui-rtl |
editing authored base UI/components |
--registry <style|all> |
../public/r/styles/<style> |
changing what the CLI installs |
注意事项(来自该 README 与 CONTRIBUTING 的共同约定):
- 定向模式可组合使用,如
--style base-nova --registry base-nova; - 定向模式为了速度跳过格式化,可能留下未格式化的生成文件与较大的
git diff; - 因此提交前必须跑一次完整的
pnpm registry:build来重新规范化所有产物。根目录的registry:build脚本实际是pnpm --filter=v4 registry:build && pnpm lint:fix && pnpm format:write -- --loglevel silent(package.json),在v4工作区内则会先构建@shadcn/react、@shadcn/helpers、shadcn三个包,再执行scripts/build-registry.mts(apps/v4/package.json)。
生成产物与 git 工作树
CONTRIBUTING.md 特别强调:大部分生成产物不受 git 跟踪——apps/v4/public/r/styles 下的可安装 JSON 与 apps/v4/styles 下的编译样式均被 gitignore,并在每次部署时重建。因此执行 registry:build 不会用生成文件弄脏你的工作树——最终提交的只有手写源(如 registry/bases)的变化和被跟踪的索引文件。这一设计与 turbo.json 中 build 任务将 public/r/styles/**、styles/** 列为输出的做法一致:它们受 Turborepo 缓存管理,而非 git。
七、提交规范(Commit Convention)
CONTRIBUTING.md 要求提交前检查提交信息是否符合 category(scope or module): message 约定,可用的 category 如下:
feat / feature:引入全新代码或新功能的所有改动fix:修复 bug 的改动(若存在对应 issue 建议引用)refactor:非 fix、非 feature 的代码相关改动docs:修改或新建文档(README、库或 CLI 使用文档等)build:与软件构建相关的所有改动、依赖变更或新增依赖test:与测试相关的所有改动(新增或修改测试)ci:与持续集成配置相关的所有改动chore:不属于以上任何类别的仓库改动
示例:feat(components): add new prop to the avatar component
这一约定有工具链支撑:根 package.json 依赖了 @commitlint/cli 与 @commitlint/config-conventional,仓库根目录存在 .commitlintrc.json 配置文件。约定本身源自 Conventional Commits 规范与 Angular 提交信息指南(文档中给出了参考说明)。一个实际用例:模板同步脚本 scripts/sync-templates.sh 在提交模板变更时使用的就是 chore: update template 这类消息(scripts/sync-templates.sh)。
八、测试
CONTRIBUTING.md 说明测试使用 Vitest 编写,可以从仓库根目录运行全部测试:
pnpm test
提交 PR 前请确保测试通过;新增功能请附带测试。
源码层面可以进一步看清这条命令的完整语义——根 package.json 中:
"test:dev": "turbo run test --force",
"test": "pnpm --filter=v4 registry:build && start-server-and-test v4:dev http://localhost:4000 test:dev"
即根目录的 pnpm test 并不只是跑单元用例:它会先构建 registry,再启动 v4 dev server 并等待 http://localhost:4000 就绪后,通过 Turborepo 以 --force 方式在各工作区执行 test 任务(--force 绕过缓存)。这与 turbo.json 中 test 任务 dependsOn: ["^build"]、cache: false 的配置互相印证:测试依赖已构建的产物(shadcn CLI 的测试会通过 REGISTRY_URL=http://localhost:4000/r 打向本地 registry,见 packages/shadcn/package.json 的 test:dev)。
工作区维度的测试编排见 vitest.workspace.ts:Vitest 以 workspace 模式聚合根 vitest.config.ts 与 packages/tests/vitest.config.ts(后者承载针对 CLI 的集成测试,测试夹具位于 packages/tests/fixtures/)。针对单个包也可以直接跑,例如 pnpm --filter=shadcn test(对应根脚本 shadcn:test)。
九、其他贡献路径
CONTRIBUTING.md 还约定了两条补充路径:
- 新组件请求:如有新组件需求,应通过 GitHub Discussions 发起讨论,而非直接提 PR;
- CLI 改动:所有
shadcnCLI 的改动都在packages/shadcn目录中进行,并强烈建议为改动补充测试。CLI 的公开子命令与参数实现位于 packages/shadcn/src/commands,其对外能力(registry 拉取、schema、MCP 等子入口)在 packages/shadcn/package.json 的exports字段中有明确声明。
关于版本发布,虽然 CONTRIBUTING.md 未展开,但从仓库配置可以确认:发布基于 changesets,根脚本 release 为 changeset version(package.json),shadcn 包的发布通过 pub:beta / pub:rc / pub:release 脚本带 tag 执行(packages/shadcn/package.json);RELEASING.md 提供了更完整的发布流程说明。
十、贡献流程速查
综合 CONTRIBUTING.md 与上述源码佐证,一次完整的组件贡献流程可归纳为:
- Fork → 克隆 → 建分支 →
pnpm install; - 首次启动前执行
pnpm --filter=v4 registry:build --style all; pnpm --filter=v4 dev启动官网(端口 4000),开发时用pnpm registry:build --style/--registry/--examples/--indexes定向快速重建;- 若改动涉及 CLI,另开终端用
pnpm dev+pnpm shadcn <cmd> -c <目标项目>做本地端到端验证; - 按"所有 style 同步修改 + 更新文档"的要求检查
apps/v4/registry与apps/v4/content/docs; - 提交前运行完整
pnpm registry:build(勿只留定向模式的未格式化产物)与pnpm test; - 以
category(scope): message规范写提交信息,发起 PR。
掌握以上流程与 pnpm-workspace.yaml、turbo.json、apps/v4/registry/README.md 三份配置之间的关系,就能在只读浏览本仓库的基础上,顺畅地进入自己的 fork 进行开发。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00