一键导入
setup-ts-deep-modules
为 TypeScript 仓库接入 dependency-cruiser,让每个包成为深层模块(deep module):实现隐藏在子目录中,只能通过入口文件访问。仅用户调用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
为 TypeScript 仓库接入 dependency-cruiser,让每个包成为深层模块(deep module):实现隐藏在子目录中,只能通过入口文件访问。仅用户调用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
提供使用 CameraX 进行 Android 相机开发的技术指导。当实现相机功能、处理异步录制生命周期、使用 CameraX 进行底层硬件互操作,或集成 ML Kit 或 Media3 特效时使用。
提供基于 Android Credential Manager API 实现已验证邮箱获取的完整工作流。使用此 skill 向 Android 应用集成安全、免 OTP 的邮箱验证流程。该 skill 利用来自 Google 等可信提供商的加密验证凭证,解决注册流程摩擦过大的问题。
提供让应用 UI 适配不同 Android 设备(手机、平板、折叠屏、笔记本、桌面、TV、Auto 和 XR)的说明。涵盖使用 Compose MediaQuery API 处理不同窗口尺寸、指针设备(如鼠标)和文本输入设备(如键盘);使用 Navigation3 Scenes 实现多窗格布局;使用 Compose Grid 和 FlexBox API 实现随目标尺寸变化的自适应 UI 组件(如按钮)和自适应布局(含导航区——nav rails 和 nav bars)。
提供将 Android XML View 迁移到 Jetpack Compose 的结构化工作流。该 skill 详述从规划和依赖设置,到主题和布局迁移、验证及 XML 清理的分步流程。当需要在 Android 项目中把 XML View 迁移到 Jetpack Compose 时使用。它解决将旧版 XML View 的 UI 转换为现代声明式 Compose 组件、同时保持互操作性的问题。
使用此 skill 将 Jetpack Compose Styles API 集成到 Android 项目。引导你升级依赖、设置组件主题、让自定义组件可样式化,以及将现有布局属性迁移到统一样式。迁移自定义设计系统组件、用 Style 属性替换硬编码参数、使用 Modifier.styleable 处理交互状态。
学习如何安装并迁移到 Jetpack Navigation 3,以及如何实现 deep links、多个 backstack、scenes(对话框、底部表、list-detail、two-pane、supporting pane)、条件导航(如已登录导航 vs 匿名导航)、从流程返回结果、与 Hilt/ViewModel/Kotlin/View 互操作集成等功能和模式。
| name | setup-ts-deep-modules |
| description | 为 TypeScript 仓库接入 dependency-cruiser,让每个包成为深层模块(deep module):实现隐藏在子目录中,只能通过入口文件访问。仅用户调用。 |
| disable-model-invocation | true |
Make every package in this repo a deep module: a lot of behaviour behind a small interface. A package's public surface is its entry points — the files at the package root — and everything in its subfolders is hidden. This skill installs dependency-cruiser and the rules that make the entry points the only way in, then proves the rules bite.
For the vocabulary (deep module, interface, seam, depth), run the /codebase-design skill — use its language throughout.
src/packages/
<name>/
index.ts ← an entry point (public). Import this from outside.
client.ts ← another entry point. Packages may expose SEVERAL.
lib/ ← implementation: hidden from outside, free to import each other.
tests/ ← co-located tests + fixtures (a subfolder, so private).
The public surface is the package's root files — not one designated index.ts. By convention implementation lives in lib/ and tests in tests/, giving every package the same two-folder shape. The rule itself is general, though: anything in any subfolder is private, so you never extend the config to add a folder.
Four rules, all error:
<pkg>/tests/ may import any package's entry points and their own tests/ fixtures, but never any package's subfolder internals (not even their own). Integration tests across packages are fine; deep imports are not.Entry points, not a barrel. Because the public surface is every root file, a package can expose several small entry points (index.ts, client.ts, server.ts) instead of funnelling everything through one giant index.ts. Barrel files that re-export a whole subtree are discouraged — keep entry points small and hide implementation in subfolders.
Layering (which packages may depend on which) is a different concern and is left as a commented stub in the config for this repo to fill in.
pnpm-lock.yaml → pnpm, yarn.lock → yarn, bun.lockb → bun, else npm. Use it for every command below (pnpm/yarn/npm run/bunx).src/ exists use src/packages, else packages. Confirm the choice with the user if the repo already has a different obvious convention..dependency-cruiser.* file. If one exists, do not overwrite it: merge the four rules and the options in, and tell the user what you added.Done when: package manager, packages root, and existing-config status are all known.
Install dependency-cruiser as a devDependency with the detected package manager.
Done when: dependency-cruiser is in devDependencies.
Copy dependency-cruiser.config.cjs to the repo root as .dependency-cruiser.cjs. Set PACKAGES_ROOT to the root detected in step 1. The rules are path-depth based and extension-agnostic, so nothing else needs adapting.
Done when: .dependency-cruiser.cjs exists with the correct PACKAGES_ROOT, and the four forbidden rules are present.
lint:boundaries script: depcruise <packages-root> (or depcruise src).check / ci / validate script). Do not touch tsconfig or add path aliases.lint:boundaries and tell the user to include it in CI.Done when: lint:boundaries exists and runs as part of the same command as typecheck.
Create a committed <packages-root>/example/ as a copy-me template:
index.ts — an entry point. Export one function that delegates to an internal file (so the package is visibly deep, not a pass-through).lib/impl.ts — an internal file in a subfolder, imported by index.ts, not reachable from outside.tests/example.test.ts — imports only ../index (an entry point), and asserts against the public function.Tell the user this is a starter template to copy or delete.
Done when: the example package exists, exposes its behaviour through a root entry point, and hides impl in a subfolder.
This is the completion criterion for the whole skill — a config that doesn't fail on a violation is worthless.
lint:boundaries. It must pass on the clean example.tests/example.test.ts (e.g. import { thing } from "../lib/impl"). Run lint:boundaries again — it must fail with tests-through-entrypoints.Done when: you have observed a pass, then a fail on the deep import, then a pass again. If step 2 does not fail, the rules are not wired correctly — fix before finishing.
Write a README.md in the packages folder (<packages-root>/README.md) — next to the packages it governs — covering: the src/packages/<name>/ layout (entry points at the root, lib/ for implementation, tests/ for tests), "import only through a package's entry points (its root files)", and how to run lint:boundaries. Discourage barrel files explicitly — expose several small entry points instead of re-exporting a whole subtree through one index. Keep it to the copy-me snippet plus the four rules in one paragraph each.
Then add a context pointer to it from the repo's agent-instructions file — CLAUDE.md if present, else AGENTS.md (create AGENTS.md if neither exists). One line is enough, e.g. Packages are deep modules — see [src/packages/README.md](./src/packages/README.md) before adding or importing one. This is what makes an agent discover the boundary rule instead of tripping over it.
Done when: <packages-root>/README.md exists and discourages barrels, and the repo's CLAUDE.md/AGENTS.md links to it.
$1 back-references (dependency-cruiser's group matching) are what let a package reach its own internals while outsiders can't — don't flatten them into separate per-package rules.lib/ (implementation) and tests/, but the rule doesn't hardcode them — any subfolder is private, so a new folder never needs a config change. Adding an entry point is just adding a root file — no barrel..cjs (not .js) so the config's module.exports works even in "type": "module" repos.