本文へ移動
cccskills

TypeScriptの循環依存を防ぐ setup-ts-deep-modules

cccskills 編集部読了 約 11 分

この記事の結論

こんな人に
TypeScriptでパッケージ内部への直接importや循環依存が増え、構成の崩れを仕組みで止めたい開発者
入れると
  • 内部ファイルへの直接参照と循環依存が、型チェックと同じコマンドでエラーとして見つかる
  • コピー用のexampleパッケージがあり、新しいパッケージを同じ形で始められる
  • 規約のREADMEがCLAUDE.mdなどから案内され、エージェントも境界の規約を見つけられる
向かない人
パッケージを入れ子にする構成の人や、パッケージ間の依存方向の制限まで自動で整えたい人

setup-ts-deep-modulesは、TypeScriptのパッケージで外から使える入口を、直下の公開ファイルだけに限るためのスキルです。入れると、その構成を設定から検証、文書化まで一度に整えられます。この記事では、導入される4つのルール、ルールが働いているかの確かめ方、Claude CodeやCodexへのインストール方法、依頼文の例、導入前に確かめておく前提を順に説明します。

目次

使うとこうなる

setup-ts-deep-modulesを呼び出すと、エージェントがリポジトリに境界チェックを入れ、ルールが実際に違反を止めるかまで確かめます。対象は、パッケージ内部への直接参照と循環依存です。配布元はGitHubのmattpocock/skills(スター297,465)で、ライセンスはMIT。

setup-ts-deep-modulesを使って、このリポジトリのパッケージに境界チェックを入れてください。

エージェントはまず、ロックファイルを見てパッケージマネージャーを判別します。パッケージの置き場所は、src/があればsrc/packages、なければpackages。続いてdependency-cruiserを開発用依存関係に追加し、設定ファイル.dependency-cruiser.cjsをリポジトリ直下に置きます。

dependency-cruiserは、ファイル同士のimportを調べてルール違反を報告するツール。作業が終わると、各パッケージは次の形にそろいます。

src/packages/
  <name>/
    index.ts   ← 公開ファイル(外からimportしてよい)
    client.ts  ← 公開ファイルは複数置ける
    lib/       ← 実装。外からは参照できない
    tests/     ← テスト。サブフォルダなので非公開

あわせてlint:boundariesというスクリプトが追加され、型チェックを実行している既存のまとめコマンドに組み込まれます。ほかに作られるのは、サンプルのexampleパッケージと、規約を書いたREADME.md。CLAUDE.mdまたはAGENTS.mdに、そのREADMEへの案内を1行加えるところまでが作業の範囲です。

setup-ts-deep-modulesでできること

このスキルの中心は、パッケージの公開範囲を「直下のファイルだけ」と決め、それ以外への参照をエラーにすることです。サブフォルダにあるものは、名前に関係なくすべて非公開として扱われます。フォルダを増やしても、設定を書き換える必要はありません。

内部への直接参照と循環依存を検出する

導入されるルールは4つで、どれも違反するとエラーになります。

  1. パッケージの外(アプリのコードや別のパッケージ)からは、そのパッケージ直下の公開ファイルだけをimportできる
  2. パッケージ内のファイル同士は自由にimportできる
  3. tests/のテストは、各パッケージの公開ファイルと自分のtests/内のフィクスチャ(テスト用データ)だけを参照できる。自分のパッケージのlib/も参照できない
  4. 依存関係の循環を禁止する

3番目のルールがあるので、テストも利用者と同じ入口から動作を確かめる形になります。複数パッケージをまたぐ統合テストは書けますが、内部を直接読むテストは書けません。

型チェックと同じコマンドで境界を確かめる

境界チェックはlint:boundariesとして追加され、型チェックを実行しているcheckやciなどのまとめコマンドに組み込まれます。tsconfigやパスエイリアスには手を加えないため、既存のビルド設定は変わりません。まとめコマンドがないリポジトリでは、lint:boundariesだけを追加し、CIに含めるよう利用者に伝える流れです。

コピーして使える雛形を作る

exampleパッケージは、新しいパッケージを作るときにコピーする見本です。index.tsが公開する関数は処理をlib/impl.tsに任せ、テストは../indexだけをimportする構成。不要になれば削除してよい雛形として作られます。

雛形を作ったあと、エージェントはルールが機能しているかを3回の実行で確かめます。1回目は、違反のない状態で合格すること。2回目は、テストにlib/implへの直接importを一時的に足して失敗すること。3回目は、元に戻して再び合格することです。

2回目で失敗しなければ設定の誤りとみなし、作業を終える前に直します。

規約を文書にし、エージェントに共有する

パッケージフォルダのREADME.mdにまとめるのは、構成と4つのルール、lint:boundariesの実行方法。1つのindex.tsで下位の全体を再エクスポートする「バレルファイル」は避け、小さな公開ファイルを複数置くよう明記されます。

さらにCLAUDE.md(なければAGENTS.md、どちらもなければAGENTS.mdを新規作成)に、このREADMEへの案内を1行加えます。後から作業するエージェントが、この1行から境界の規約にたどり着ける仕組み。

インストール方法

インストールは、コマンドで入れる方法とエージェントに頼む方法の2通りです。コマンドの場合は、実行時にClaude CodeやCodexなど、入れる先のエージェントを選べます。

npx skills add https://github.com/mattpocock/skills --skill setup-ts-deep-modules

エージェントに頼む場合は、次の文面をそのまま送ってください。

次の Agent Skill をインストールしてください。
https://github.com/mattpocock/skills/tree/main/skills/in-progress/setup-ts-deep-modules

まず SKILL.md と付属ファイルの中身を確認し、不審な処理(外部への送信、認証情報の読み取りなど)がないことを確かめてから、Claude Code なら ~/.claude/skills/setup-ts-deep-modules/、Codex なら ~/.agents/skills/setup-ts-deep-modules/ に配置してください。

置き場所は、すべてのプロジェクトで使うか、特定のプロジェクトだけで使うかで変わります。

エージェントすべてのプロジェクトで使う特定のプロジェクトだけで使う
Claude Code~/.claude/skills/プロジェクトの.claude/skills/
Codex~/.agents/skills/プロジェクトの.agents/skills/

スキルのフォルダにはSKILL.mdのほか、設定の元になるdependency-cruiser.config.cjsとagents/openai.yamlが入っています。手動で置くときは、フォルダごとコピーしてください。

使い方の例

このスキルは、利用者が明示的に呼び出す設計です。依頼文にはスキル名を書き、重視したい点を添えると伝わりやすくなります。

setup-ts-deep-modulesで、既存のリポジトリに境界チェックを入れてください。dependency-cruiserの設定がすでにあるので、上書きせずに統合してください。

既存の.dependency-cruiser.*があっても、エージェントは上書きしません。4つのルールと設定を統合し、何を足したかを報告します。統合後にlint:boundariesを実行すると、今のコードにある内部への直接参照や循環依存がエラーとして挙がります。

setup-ts-deep-modulesで、コピー用のexampleパッケージを作り、違反を検出できるか確認してください。

example/に作られるのは、index.ts、lib/impl.ts、tests/example.test.tsの3ファイル。続けて合格・失敗・合格の3回の実行結果が示されるので、ルールが働いていることをその場で確かめられます。

setup-ts-deep-modulesの手順で、パッケージの規約をREADMEにまとめ、CLAUDE.mdから参照できるようにしてください。

パッケージフォルダのREADME.mdには、構成の見本と4つのルールが、それぞれ1段落で書かれます。CLAUDE.mdに加わるのは、「パッケージを追加・importする前にこのREADMEを読む」という趣旨の1行。

注意点

最初に確かめたいのは、既存コードへの影響です。4つのルールはすべてエラー扱いで、型チェックと同じコマンドに組み込まれます。既存コードに内部への直接参照や循環依存があれば、導入した時点でまとめコマンドが失敗するので、修正の時間を見込んでおいてください。

対象にする構成にも前提があります。パッケージは置き場所の直下に1階層で並ぶ形が前提で、パッケージの中に別のパッケージを入れる構成は扱いません。

どのパッケージがどれに依存してよいかという、依存方向の制限も対象外。この部分は、設定ファイルにコメントの下書きとして残されます。

環境の面では、npm、pnpm、yarn、bunのいずれかでdependency-cruiserを開発用依存関係に追加します。設定ファイルは.cjs形式なので、"type": "module"のリポジトリでも問題ありません。

スキルの説明は、同じリポジトリのcodebase-designスキルを呼び出して用語をそろえる前提で書かれています。あわせて入れておくと、説明の言葉が一致するでしょう。

ライセンスはMITです。インストール前にSKILL.mdと付属ファイルを読み、外部への送信や認証情報の読み取りといった不審な処理がないかを確かめてください。

関連スキル

codebase-designは、呼び出し側が覚える使い方を小さく保ち、複雑な処理を内部にまとめる設計を支援するスキルです。setup-ts-deep-modulesはこのスキルの用語(deep module、interfaceなど)を使う前提なので、設計の検討と境界チェックの仕組みを同じ言葉で進められます。

code-reviewは、コミットやブランチを基準に変更を確認し、開発規約への適合と仕様の実現を分けてレビューするスキル。境界の規約を決めたあと、日々の変更が規約に沿っているかを見る段階で使えます。

まとめ

setup-ts-deep-modulesは、パッケージの入口を直下の公開ファイルに限り、内部への直接参照と循環依存をエラーにするスキルです。作業範囲は、dependency-cruiserの導入から、型チェックとの統合、雛形づくり、3回の実行による検証、規約の文書化まで。

レビューでの注意力に頼らず、仕組みでモジュールの境界を守りたいチームに向いています。導入前にSKILL.mdを読み、既存コードの違反に対応する時間を確保してから試してください。

cccskillsのページ

よくある質問

dependency-cruiserの設定は自分で書く必要がありますか
書く必要はありません。スキルに含まれる設定ファイルが.dependency-cruiser.cjsとしてリポジトリ直下にコピーされ、パッケージの置き場所だけが書き換えられます。ルールはフォルダの深さで判定するので、拡張子に合わせた調整も要りません。
公開ファイルはindex.tsの1つだけですか
1つに限りません。パッケージ直下にあるファイルはすべて公開ファイルとして扱われ、index.ts、client.ts、server.tsのように複数置けます。下位をまとめて再エクスポートするバレルファイルは、避けるよう案内されます。
パッケージ同士の依存方向も制限できますか
このスキルの対象外です。依存方向の制限は別の関心事として扱われ、設定ファイルにコメントの下書きが残されるだけです。必要であれば、リポジトリに合わせて自分で書き足してください。

このスキルを試す

setup-ts-deep-modules の入れ方とインストールコマンドは、cccskills のスキルページにまとめてあります。

この記事は、公開されている SKILL.md と cccskills の紹介文をもとに AI(Claude)が下書きし、cccskills 編集部の方針に沿って推敲・公開しています。正確な仕様はスキルのページで原文を確認してください。

他の記事