
text-to-cad 仓库工程实战Agent Skill 开发的分支布局、发布管线与 CAD Viewer 调试全解【免费下载链接】text-to-cadA library of agent skills for CAD, CAE and CAM项目地址: https://gitcode.com/GitHub_Trending/tex/text-to-cadtext-to-cad 是一个面向 CAD、CAE、CAM 的 Agent Skill 库当前规范版本见 VERSION仓库根目录本身即 Agent 插件包。本文以仓库工程约定文件 AGENTS.md由 CLAUDE.md 以AGENTS.md指令引入为骨架系统拆解其分支与目录布局、以 GitHub Actions 为中心的单次发布工作流、Skill 自包含的边界规则、检查体系以及 CAD Viewer 的本地调试方法所有结论均以仓库内脚本、配置与测试为证据读者可据此直接开展分支开发、跑通发布流水线并在本地把 CAD Viewer 跑起来。仓库定位一个“以 Skill 为产品”的 Workbench仓库把skills/视为产品本体每个目录是一份可独立安装的 Agent Skill把models/视为共享的 fixture/artifact 区域STEP、STL、GLB、DXF、URDF、SRDF、SDF 等样本与生成产物统一落在这里。围绕这两块核心仓库还维护了viewer/可编辑的 CAD Viewer 应用源码作为本地文件系统应用被逐字镜像到独立的 cad-viewer 仓库packages/cadjs与 UI 框架无关的共享 JS CAD / 渲染 / 运行时代码packages/implicitjs独立的自包含 implicit CAD 模型、着色器渲染、快照、网格采样与导出运行时packages/cadgen共享的 Python STEP/GLB/topology 工件生成代码docs/、tests/、scripts/文档站、根级测试套件与长期有效的仓库命令。从文件组织可以看出两条硬约束共享运行时一律放packages/作为唯一事实源再由打包流程 vendor 进各 Skill 的运行时目录models/是唯一允许写 CAD/机器人描述产物的地方禁止在仓库其他位置随手创建产物目录。分支与布局策略develop 用 symlink 开发main 只做发布分支纪律所有开发从develop分支切出PR 一律打回develop禁止从main起步开发main是纯发布分支只接受Release工作流的发布提交禁止向其开 PR 或直接 pushdevelop分支刻意使用 symlink 布局跨生成的运行时路径与 viewer 本地包路径遇到 symlink 时要沿链接追踪并编辑真正的源目标。两种布局的本质区别develop开发布局把生产打包产物路径以 symlink 指回规范源码贡献者只需编辑skills/、viewer/、packages/下的一份源码。建立与校验布局使用 scripts/dev/setup-symlinks.shscripts/dev/setup-symlinks.sh # 建立开发 symlink 布局 scripts/dev/setup-symlinks.sh --check # 校验布局无损不改动文件该脚本内部委托 scripts/dev/setup-skill-symlink.sh 与各 Skill 的setup-*-skill-symlink.sh逐个建立链接。main发布布局必须能被“裸 checkout”直接安装因此里面是真实的生成产物副本而非 symlink。把 symlink 替换成真实副本在main上是正确性要求而非惯例。为什么 symlink 不能进入发布树不同 Agent 安装器对 symlink 的处理方式互不相同且其中一种会静默丢文件。这一点在 scripts/github-workflows/check-builds.sh 中有明确注释佐证Skills CLInpx skills把 symlink 解引用为真实文件Claude Code 插件安装原样保留 symlinkCodexplugin add静默丢弃 symlink 且无任何报错——其copy_dir_recursive只按is_dir()/is_file()分支判断symlink 条目两个分支都不命中于是该文件直接缺失Skill 装上后运行时缺文件。因此发布树中一旦出现 symlinkcheck-builds.sh会直接失败Production bundle paths must not contain symlinks这是 CI 红线不可放宽。main 的“裁剪”语义仓库根即插件包main上任何源码路径都会被复制进每次安装所以发布任务在打包、全部检查通过之后会裁剪发布树移除models/、viewer/、tests/、docs/、packages/、requirements-dev.txt让main尽量只保留插件包本身。这些内容并不丢失因为各自都有“读源码而非读发布树”的消费方viewer/的运行时是解引用后的skills/cad-viewer/scripts/viewer副本镜像仓库同步自发布源提交docs/与packages/由Deploy Docs工作流从发布源提交构建部署models/、tests/、requirements-dev.txt只在源码检出时使用。单次发布的完整管线Release / Deploy Docs / Sync CAD Viewer规范版本号的唯一事实源VERSIONVERSION当前为0.4.10是规范发布版本号普通开发 PR 一律不碰它。所有衍生版本元数据各package.json/package-lock.json的version字段、.claude-plugin/与.codex-plugin/插件清单版本、packages/cadgen/pyproject.toml等 TOML 的version行由 scripts/release/sync-version.mjs 从VERSION统一盖章。值得注意的工程细节由于 develop 布局下镜像路径与规范路径是 symlink多个目标可能指向同一个真实文件sync-version.mjs用mergeTargetsByRealPath按realpath合并目标后再统一写回避免“后写的镜像目标覆盖掉规范目标独有字段”这类问题——这正是 0.4.10 发布门禁曾因packages/cadjs/package-lock.json被 symlink 覆盖而自锁的教训修复。因此永远不要手工编辑这些重复的版本字段scripts/release/bump-version.sh与 scripts/bundle/bundle.sh 会负责盖章。Release 工作流一次运行完成整个发布发布只通过单一的ReleaseGitHub Actions 工作流完成默认参数即真实发布配置gh workflow run release.yml --ref develop -f bumppatch一次运行依次完成在release/version分支上 bumpVERSION与衍生元数据 → 打开发布 PR 并立即合入develop→ 执行发布生产打包、校验、写main→ 部署文档 → 打 semver tag 与 GitHub Release。关键约束不要自行选择 semver请求未指明 patch / minor / major 或精确版本时必须先确认再派发发布 PR 不等自身 CI发布任务会对“最终要发布的东西”重新跑完整打包与测试门禁只有源版本新于main与最新 semver tag、且源包含上一次发布源提交时才允许发布写main时以“生成的生产合并提交”叠加在上一发布目标之上、以发布源为第二父提交既保证main可 fast-forward又保留源码提交用于 release notes 与贡献者归属GitHub Release 默认立即发布publishfalse可先以草稿审阅。PyPI 发布 cadgen发布任务同时把packages/cadgen上传到 PyPI先校验生产 bundle再 pushmain之前上传——发布树用 scripts/release/pin-cadgen-requirements.sh 把 editable 依赖行改写为固定的cadgenversion来自 PyPI因此 PyPI 上传失败必须阻塞发布否则会发布一个依赖无法解析的main。PyPI 版本恒等于VERSION上传使用skip-existing失败重跑幂等可续。首次发布需在 PyPI 为cadgen配置 trusted publisherGitHub OIDC无需存储 API token。bumpnone不是发布设置bumpnone表示“把base_branch原样发布”不改版本、不开发布 PR、直接进入发布任务。它用于续跑失败发布和对build-test做管线彩排。set_version只用于指定新版本不是“保持版本不动”的说法。即使bumpnonesync-version.mjs仍会运行若衍生元数据与VERSION漂移会被拦截走发布 PR 流程。彩排与续跑CI/CD 或构建变更测试只有用户明确要求测试时才用target_branchbuild-test并必须搭配bumpnone避免彩排消耗版本号gh workflow run release.yml --ref branch \ -f bumpnone -f base_branchbranch -f target_branchbuild-testdry_runtrue只预览版本变化auto_mergefalse停在“准备发布 PR”这一步。续跑失败发布任何环节失败包括main已前进但 tag 未打后用bumpnone重跑即可——版本已到base_branch无需再 bump直接进发布任务发布门禁同时处理“main 未动”与“main 已动但缺 tag”两种形态。Deploy Docs独立重部署文档站独立的Deploy Docs工作流不触发发布只把文档站重新部署到 Vercel 生产gh workflow run deploy-docs.yml -f refdevelop它只能部署源码 ref默认develop不能部署main——发布树已删掉docs/与packages/而 docs 应用是依赖根目录packages/构建的docs/tsconfig.json把cadjs/*映射到../packages/cadjs/src/*。工作流前置检查这两者并给出明确报错。要重放某次历史发布的站点用该发布源提交每次发布提交的第二父提交即发布源例如git rev-parse tag^2。镜像 CAD Viewer 仓库viewer/会被发布为独立的 cad-viewer 仓库Release在发布main之后调用Sync CAD Viewer Repo从发布源提交而非不含viewer/的main镜像。可单独派发gh workflow run sync-cad-viewer.yml -f refdevelop gh workflow run sync-cad-viewer.yml -f refdevelop -f dry_runtrue该镜像是一次直拷贝不重写任何路径/命令/文本唯一结构性变化是把viewer/packages/*解引用为真实目录脚本拒绝发布仍含 symlink 的树。推送前会在镜像内跑npm ci、npm run test、npm run build、pip install -r requirements.txt与server_py测试镜像站不住脚则发布失败。它需要CAD_VIEWER_SYNC_TOKEN对镜像仓库有contents:write。本地同步/查漂移可用 scripts/viewer/sync-cad-viewer-repo.sh。本地手动兜底与工作流同款脚本的本地发布准备git fetch origin develop git fetch --tags origin scripts/release/bump-version.sh patch --no-commit node scripts/release/sync-version.mjs scripts/release/check-version.sh --incremented-from origin/main node scripts/release/sync-version.mjs --checkscripts/release/publish-github-release.sh 是 tag 与 GitHub Release 步骤的手动兜底与工作流不同它默认创建草稿除非传--publish。同时建议配置仓库规则集main拒绝 PR 与直接 push只留Release发布任务这个唯一写入口、为[0-9]*.[0-9]*.[0-9]*开启 tag 规则集。仓库硬规则Skill 自包含、包边界与产物纪律Skill 运行时自包含每条 Skill 在运行时必须自包含且独立不得引用、导入或依赖另一条 Skill、skills/根目录或仓库根模块的代码。禁止把skills/、仓库根或兄弟 Skill 目录加入sys.path、PYTHONPATH、NODE_PATH等运行时查找路径。共享运行时助手必须放在packages/作为唯一事实源再通过打包/生成流程 vendor 进各消费 Skill 的运行时packages/cadgen这类共享 Python 工件也应走捆绑包路径而非兄弟 Skill 导入。开发 symlink 只是 checkout 布局便利不改变这条运行时约束。包间依赖方向packages/cadjs必须保持可复用、非 ReactApp 的 UI 与工作流状态属于viewer/packages/implicitjs必须保持可复用、非 React且绝不 importcadjs。依赖单向流动cadjs依赖implicitjs并在cadjs/implicit/*下再导出其共享渲染/导出 API因此消费方CAD Viewer、快照工具只装cadjs即可viewer/必须完全自包含其下任何内容不得引用上层路径/命令/文档因为它是被逐字镜像进独立 cad-viewer 仓库的无重写步骤。viewer/scripts/selfContained.test.mjs 在每次测试运行中强制这一点。产物与脚本纪律所有测试、样本、永久与生成的 CAD/机器人描述产物STEP/STP、STL、GLB、DXF、URDF、SRDF、SDF一律写入models/禁止另建临时产物目录scripts/只放长期有效的仓库命令临时一次性脚本放tmp/或/tmp源码变更影响生成运行时后用主打包包装器 scripts/bundle/bundle.sh 刷新或校验scripts/bundle/bundle.sh # 同步版本元数据并打包所有生产输出 scripts/bundle/bundle.sh --check # 打包到 tmp/若已提交输出过期则失败 scripts/bundle/bundle.sh --clean # 先清理临时打包目录bundle.sh先调用sync-version.mjs同步版本元数据再委托 scripts/bundle/bundle-skill.sh 按scripts/bundle/skills/bundle-skill-id.sh逐个 Skill 打包--all遍历全部、--print-outputs输出生成路径供检查脚本使用。低层 bundle 脚本只在调试包装器本身时使用。Git 卫生不提交.venv/、node_modules/、缓存、tmp/、本地凭据与打印机配置生成运行时的变更应来自生产输出流程而非手工编辑生成目录。开发环境与轻量 worktreeCAD Python 工作优先使用./.venv/bin/pythonCONTRIBUTING.md 建议python3.12 -m venv .venv后安装requirements-dev.txt默认保持新分支 checkout 与 git worktree 轻量化不通过.worktreeinclude复制.venv/或models/仅当工作流需要 Python 依赖时才在 worktree 内重建.venv/worktree 中若明确需要开发 symlink 布局先scripts/dev/setup-symlinks.sh --check再有意执行scripts/dev/setup-symlinks.sh不要在 Codex / Claude Code 的启动 hook 里自动修复布局models/只在用户要求或任务明确针对其下文件时才水合优先用本地 Git LFS 缓存git lfs checkout path或git lfs checkout models仅在明确需要且本地缓存缺失时下载 LFS 对象只为正在改动的工作流安装依赖。检查体系先小范围后全量原则是“跑覆盖本次改动的最小路径定向检查”触碰共享面或交接前再跑全量包装器scripts/test/test.sh # 代码测试总入口 scripts/test/test-js.sh # 聚焦 JS 测试 scripts/test/test-docs.sh # 聚焦文档测试 scripts/test/test-python.sh # 聚焦 Python 测试 scripts/test/test-global.sh # 聚焦全局测试 scripts/dev/setup-symlinks.sh --check # 开发 symlink 布局 scripts/release/check-version.sh # 规范版本号 scripts/bundle/bundle.sh --check # 生成运行时新鲜度包级与站点检查npm --prefix packages/cadjs test、npm --prefix packages/implicitjs test、npm --prefix viewer run test、npm --prefix viewer run build、npm --prefix docs run check定向 Python 测试用./.venv/bin/python -m unittest changed test paths测试按tests/python/下skills/skill、packages/package、viewer/service、global分组。CI 中test.yml在独立 job 校验规范版本号版本元数据错了代码测试仍能跑并在测试 job 里校验 develop symlink 布局、对比生成输出与源码、临时打包生产输出、再对产物跑文档与代码测试。CAD Viewer 调试实战URL 语义PATH 即绝对目录Viewer 的 URL PATH 就是它打开的绝对目录与file://URL 一致?file在该目录内选择一个工件http://127.0.0.1:3245/absolute/model/root?filepath/relative/to/that/rootWindows 下盘符是路径的一部分前导斜杠之后、使用正斜杠D:\project\models对应.../3245/D:/project/models。Viewer不是针对某个目录启动的——它打开 URL 命名的任何内容因此一个实例可服务其服务根下的任意文件夹。worktree 场景下这很关键从另一个 checkout 启动的实例按它自己的根解析路径指向别的 clone 的绝对路径会直接“not found”面板报告该文件在此 viewer 根之外。如果其他 checkout 的 Viewer 已占用默认端口请为本工作区另起一个空闲端口实例--port n而不是把运行中的实例指向你的路径。查看仓库 fixture 时一律用models/目录作为路径并保持永久/生成文件放此处且必须用绝对路径——Viewer 从任意工作目录启动相对路径会解析错位置。除非用户要求不要停掉别人的 Viewer。改了源码不生效先怀疑 Vite 缓存编辑viewer/或packages/cadjs源码却看不到变化很可能是 Vite 的服务端 transform 缓存比 HMR 和硬刷新都“长寿”——磁盘文件已正确浏览器却一直服务旧模块。重启 dev server 并删除viewer/node_modules/.vite即可。Dev 默认、Prod 只用于 e2e迭代用devserver——Vite 从源码直接服务客户端并带 HMRviewer/、packages/cadjs、packages/implicitjs的改动即时可见npm --prefix viewer run dev -- --host 127.0.0.1 --port n # 然后打开 http://127.0.0.1:portrepo/models?filepathprod路径只用于对发布 bundle 的端到端测试或用户明确要求测 prod。它由 Python 后端cad-viewer Skill 的start命令服务构建好的dist/所以先构建npm --prefix viewer run build npm --prefix viewer run start -- --host 127.0.0.1 --port n端口行为dev与start都监听--port默认3245两者都不会滚动到其他端口——端口被占则直接报错退出所以 Viewer 总在你要求的端口上。传--port n可同时跑多个实例。打包版 Viewer 的运行时与交接细节见 skills/cad-viewer/SKILL.md其检查属于生成输出检查走主打包包装器。轻量 worktree 里启动 Viewer 的四个坑cad-viewer Skill 文档描述的是 PRODUCTION 运行时假设是已水合的 checkout而轻量 worktree 刻意不带node_modules和构建产物其“一行命令”会连续失败四次且每次报错都不指向真正原因npm --prefix skills/cad-viewer/scripts/viewer run start报Cannot find package cadjs——skills/cad-viewer/scripts/viewer是指向viewer/的 symlink打包运行时仍需要 worktree 自己的模块链接好模块后服务能起、CAD API 有响应但/返回 404——start服务的是预构建 bundle而 worktree 还没有viewer/dist。活着的后端配缺失的前端看起来像坏链接而非缺构建npm --prefix viewer run build再逐个裸 specifier 失败——implicitjs、three、meshoptimizer都来自packages/cadjs/src/...meshoptimizer在packages/cadjs/node_modules下任何位置都不存在仓库里唯一副本在docs/node_modules/meshoptimizer。从 worktree 根目录main为主 checkout正确补救ln -s main/viewer/node_modules viewer/node_modules mkdir -p packages/cadjs/node_modules ln -s ../../implicitjs packages/cadjs/node_modules/implicitjs ln -s main/packages/cadjs/node_modules/three packages/cadjs/node_modules/three ln -s main/docs/node_modules/meshoptimizer packages/cadjs/node_modules/meshoptimizer npm --prefix viewer run build npm --prefix skills/cad-viewer/scripts/viewer run start -- --host 127.0.0.1 --port n务必用显式的空闲--port从别的 checkout 启动的 Viewer 会按它自己的根解析路径永远找不到这个 worktree 里的模型。两个容易误判“模型坏了”的行为目录扫描跳过点目录.review/或其他点开头路径下的可构建条目用直接?dir查询能解析但永远不会出现在项目根扫描结果里Viewer 会报告“文件不存在”。可构建条目不要放进点目录验证 Viewer 链接要“开页面”不要 curl/__cad/asset该路由只服务原始文件生成条目的渲染包由另一条路由服务所以探测它无论有无问题都返回 404。Git 与 LFS 纪律CAD 交换文件、生成渲染/topology 资源与assets/**可能由 Git LFS 跟踪。绝不为git add、提交或其他写对象操作禁用 LFS 过滤器。本地 hooks 位于.githooks通过 scripts/git-hooks/pre-commit 委托构建检查。assets/**存放重型演示 GIF被排除在默认 LFS 拉取之外仅在本地需要演示素材时执行git lfs pull --includeassets/**水合。上手路径小结开发环境从develop切分支 → 建.venv→scripts/dev/setup-symlinks.sh建立 symlink 布局 → 编辑skills/skill/与packages/源码本地联调 Skill用 scripts/install/install-skills.sh--agent codex|claude|gemini|universal|project--all全装把 checkout 的 Skill symlink 进 Agent改完立即生效卸载用 scripts/install/uninstall-skills.sh只移除指向本 checkout 的链接验证先跑最小定向检查再scripts/test/test.sh、scripts/bundle/bundle.sh --check发布只通过Release工作流由develop构建、main发布VERSION是唯一版本事实源绝不手工改衍生版本。生产用户从main克隆安装贡献者则把develop加Release工作流当作通往main的唯一路径——这条“分支开发、symlink 迭代、单管线发布、检查前置”的工程闭环正是 text-to-cad 能同时服务多种 Agent 安装器而又不丢文件的关键所在。【免费下载链接】text-to-cadA library of agent skills for CAD, CAE and CAM项目地址: https://gitcode.com/GitHub_Trending/tex/text-to-cad创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考