setup-ts-deep-modules
Skill27 starsChanged 3 months agoMITView on GitHub
把 dependency-cruiser 接入一个 TypeScript 仓库,使每个包都成为深模块——实现隐藏在子文件夹里,只能通过其入口文件访问。用户触发。
Files
Setup TS Deep Modules
让本仓库中的每个包都成为一个深模块:小接口背后藏着大量行为。一个包的公共表面就是它的入口点——位于包根目录的那些文件——而它子文件夹里的一切都是隐藏的。本技能会安装 dependency-cruiser 以及一套规则,使入口点成为唯一的进入方式,然后证明这些规则确实生效。
关于相关词汇(深模块、接口、接缝、深度),运行 /codebase-design 技能——全程使用它的语言。
它所强制的形态
src/packages/
<name>/
index.ts ← 一个入口点(公共)。从外部导入这个。
client.ts ← 另一个入口点。包可以暴露多个。
lib/ ← 实现:对外隐藏,彼此之间可自由导入。
tests/ ← 就近放置的测试 + 固件(一个子文件夹,所以是私有的)。公共表面是包的根文件——而不是某个指定的 index.ts。按约定,实现放在 lib/,测试放在 tests/,让每个包都有相同的双文件夹形态。不过规则本身是通用的:任何子文件夹里的任何东西都是私有的,所以你永远不需要为了新增一个文件夹去扩展配置。
四条规则,全部为 error:
- 入口点边界 — 包外部的代码(应用代码或另一个包)只能导入该包的入口点(其根文件),绝不能导入它子文件夹里的任何东西。
- 包内自由 — 一个包自己的文件之间可自由互相导入。
- 测试经由入口点 —
<pkg>/tests/下的文件可以导入任何包的入口点以及它们自己的tests/固件,但绝不能导入任何包的子文件夹内部(即使是它们自己的也不行)。跨包的集成测试没问题;深层导入不行。 - 无环 — 不存在依赖环。
是入口点,不是 barrel。 因为公共表面是每个根文件,所以一个包可以暴露多个小入口点(index.ts、client.ts、server.ts),而不必把一切都塞进一个巨大的 index.ts。不鼓励用重新导出整个子树的 barrel 文件——保持入口点小巧,把实现藏进子文件夹。
分层(哪些包可以依赖哪些包)是一个不同的关注点,本仓库需在配置里以注释形式的占位存根自行填写。
步骤
1. 检测环境
- 包管理器 —
pnpm-lock.yaml→ pnpm,yarn.lock→ yarn,bun.lockb→ bun,否则 npm。下面每条命令都用它(pnpm/yarn/npm run/bunx)。 - 包根目录 — 若存在
src/则用src/packages,否则用packages。若仓库已有另一套明显的约定,则与用户确认该选择。 - 既有配置 — 检查是否有
.dependency-cruiser.*文件。如果已存在,不要覆盖它:把四条规则和相关选项合并进去,并告知用户你添加了什么。
完成标准: 包管理器、包根目录、既有配置状态三者都已知。
2. 安装 dependency-cruiser
用检测到的包管理器把 dependency-cruiser 安装为 devDependency。
完成标准: dependency-cruiser 出现在 devDependencies 中。
3. 写入配置
把 dependency-cruiser.config.cjs 复制到仓库根目录,命名为 .dependency-cruiser.cjs。把 PACKAGES_ROOT 设为第 1 步检测到的根目录。这些规则基于路径深度且与扩展名无关,所以无需再改动其他东西。
完成标准: .dependency-cruiser.cjs 存在且 PACKAGES_ROOT 正确,四条 forbidden 规则都在。
4. 接入检查流程
- 添加一个
lint:boundaries脚本:depcruise <packages-root>(或depcruise src)。 - 把它并入仓库的总检查命令——也就是那个已经运行 typecheck 的命令(例如
check/ci/validate脚本)。不要改动tsconfig,也不要添加路径别名。 - 如果没有总检查脚本,就添加
lint:boundaries并告知用户把它纳入 CI。
完成标准: lint:boundaries 存在,并作为与 typecheck 同一条命令的一部分运行。
5. 搭建示例包
创建一个提交进仓库的 <packages-root>/example/,作为“照我抄”的模板:
index.ts— 一个入口点。导出一个函数,它委托给一个内部文件(这样这个包才明显是深的,而不是一个直通层)。lib/impl.ts— 一个位于子文件夹中的内部文件,被index.ts导入,从外部无法访问。tests/example.test.ts— 只导入../index(一个入口点),并针对该公共函数做断言。
告诉用户这是一个起步模板,可以复制或删除。
完成标准: 示例包存在,通过一个根入口点暴露其行为,并把 impl 藏在子文件夹里。
6. 证明规则生效
这是整个技能的完成判据——一个在违规时不会失败的配置毫无价值。
- 运行
lint:boundaries。它在干净的示例上必须通过。 - 临时给
tests/example.test.ts加一个深层导入(例如import { thing } from "../lib/impl")。再次运行lint:boundaries——它必须以tests-through-entrypoints失败。 - 撤销那个深层导入。再运行一次——它必须通过。
完成标准: 你已观察到一次通过、然后在深层导入上一次失败、再一次通过。如果第 2 步没有失败,说明规则没接对——完成前先修好。
7. 记录约定
在包文件夹里(<packages-root>/README.md)写一个 README.md——就放在它所治理的那些包旁边——内容涵盖:src/packages/<name>/ 布局(入口点在根目录、lib/ 放实现、tests/ 放测试)、“只通过包的入口点(其根文件)导入”,以及如何运行 lint:boundaries。明确劝阻使用 barrel 文件——暴露多个小入口点,而不是通过一个 index 重新导出整个子树。把它控制在“照我抄”的代码片段,加上四条规则各一段。
然后从仓库的 agent 指令文件添加一个指向它的上下文指针——有 CLAUDE.md 就用它,否则用 AGENTS.md(若两者都没有则创建 AGENTS.md)。一行就够,例如 Packages are deep modules — see [src/packages/README.md](./src/packages/README.md) before adding or importing one.。正是这一点让 agent 发现边界规则,而不是撞上它。
完成标准: <packages-root>/README.md 存在且劝阻 barrel,仓库的 CLAUDE.md/AGENTS.md 链接到它。
备注
- 配置里的
$1反向引用(dependency-cruiser 的分组匹配)正是让一个包能够访问自己的内部、而外人不能的机制——不要把它们摊平成一条条按包分开的规则。 - 公共与私有由深度决定:包的根文件是入口点;子文件夹里的任何东西都是私有的。约定的子文件夹是
lib/(实现)和tests/,但规则并没有把它们写死——任何子文件夹都是私有的,所以新增文件夹永远不需要改配置。添加一个入口点只是添加一个根文件——没有 barrel。 - 包是扁平的:根下只有一层直接子级。一个包的内部可以按你喜欢的深度嵌套;一个包不能包含另一个包。
- 使用
.cjs(而非.js),这样即使在"type": "module"的仓库里,配置的module.exports也能正常工作。
Other versions49 projects use a version of this.
Word for word · 0
None found.
Edited · 1
- devcxl/mattpocock-skills-zh★ 52213% same
Wrote their own version · 48
- mattpocock/skills★ 309ksame name
- vinvcn/mattpocock-skills-zh-CN★ 5.5ksame name
- loulanyue/skills★ 231same name
- tt-a1i/matt-skills-with-to-goal★ 192same name
- VoDaiLocz/kilo-kit-mcp★ 28same name
- ivanrvpereira/.agents★ 19same name
- George-RD/design-studio★ 10same name
- caterpi11ar/giclaw★ 9same name
- getmodern-ai/graft★ 9same name
- imMamdouhaboammar/matts-skills-into-chatgpt★ 8same name
38 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Used alongsideProjects with it also use batch-grill-me, chief-of-staff and 4 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
boyingliu01Skillbatch-grill-me
A relentless interview that asks every frontier question at once, round by round. Thin alias of `grilling` (#540) — upstream mattpocock/skills absorbed this protocol into grilling; XP-Gate keeps this name as the sprint-flow Phase 2 entry point so orchestration docs stay stable.
Also in 5 projects that use this
getnaoSkillchief-of-staff
Also in 9 projects that use this
AWSSkillimplement-spec
Implement the result of /to-spec and /to-tickets in code.
Also in 19 projects that use this
GitHubSkillsetup-skills
Configures shared sources and drafts context with independent writers. Plain/fresh setup offers installation of user-named packages and reuses built-in browser capabilities, adding browser tooling only for an evidenced required-check gap. Use for setup, source repair, writing context or refreshing drafts. Configure-only skips tooling and authoring; installations and activation require separate approval.
Also in 3 projects that use this
AWSSkillretro
Conduct a retrospective on a coding session.
Also in 21 projects that use this
VercelSkillfind-skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
Also in 3 projects that use this
In this repository36 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- ask-mattSkill
- codebase-designSkill
- code-reviewSkill
- diagnosing-bugsSkill
- domain-modelingSkill
- grill-with-docsSkill
- implementSkill
- improve-codebase-architectureSkill
- prototypeSkill
- researchSkill
- resolving-merge-conflictsSkill
- setup-matt-pocock-skillsSkill
- tddSkill
- to-specSkill
- to-ticketsSkill
- triageSkill
- wayfinderSkill
- wizardSkill
- claude-handoffSkill
- loop-meSkill
- writing-beatsSkill
- writing-fragmentsSkill
- writing-shapeSkill
- git-guardrails-claude-codeSkill
- migrate-to-shoehornSkill
- scaffold-exercisesSkill
- setup-pre-commitSkill
- grillingSkill
- grill-meSkill
- handoffSkill
- teachSkill
- to-questionnaireSkill
- wait-whatSkill
- writing-for-agentsSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

