hairy について
TypeScript と JavaScript のツールを使うプロジェクト向けに、個人の Web 開発方針をまとめたスキルです。推奨スタック、アーキテクチャ、依存関係の管理、lint と typecheck などの品質確認手順を示します。
主な機能
- 01pnpm によるパッケージ管理
- 02Strict TypeScript と ESM の方針
- 03@antfu/eslint-config による lint
- 04Vitest のテスト規約
- 05アーキテクチャと依存関係の指針
- 06lint と typecheck の完了条件
活用シーン
- 01Web プロジェクトを Hairyf のツール方針に合わせる
- 02プロジェクトや移行先のアーキテクチャ選定
- 03taze による依存関係の更新
- 04lint、テスト、ドキュメントの設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hairyf/ skills --skill hairyインストール後、Claude Code で/hairyを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/antfu-eslint-config.mdapp-development.mdcore-arch-upkeep-routing.mdcore-deps-taze.mdcore-lint-typecheck.mdcore-unjs-preferences.md詳細
Hairyf の好み
このスキルでは、Hairyf が好む Web 開発のツール、設定、ベストプラクティスを説明します。このスキルには独自の見解が含まれています。
クイックサマリー
| カテゴリー | 好み |
|---|---|
| パッケージマネージャー | pnpm |
| 言語 | TypeScript(strict モード) |
| モジュールシステム | ESM("type": "module") |
| リントとフォーマット | @antfu/eslint-config(Prettier は使用しません) |
| テスト | Vitest |
| Git フック | simple-git-hooks + lint-staged |
| ドキュメント | VitePress(docs/ 内) |
全般的な好み
可能な限り尊重すべき、分野横断的な高レベルの好みです。
「specify」キーワード
タスクに 「specify」 と記されている場合(例:「このリポジトリを hairy に合わせて specify する」):
- 現在のプロジェクトを調査し、これらの好みに可能な限り合うよう最適化する依頼として扱います。
- 具体的には、次の作業を行います。
@skills/arch-upkeepと関連するarch-*スキルを使って、アーキテクチャを特定し、アップグレード計画を立てます。- 好みを考慮して技術スタックを選択します(
@skills/unjsを使い、unjs エコシステムを優先します)。 @skills/tazeを使って依存関係の鮮度を確認し、アップグレードします。- 「specify」タスクを完了とする前に、最後に
lintとtypecheck(テストがある場合はテストも)を実行します。
unjs エコシステムのフレームワークを優先する
- フレームワークやランタイム(SSR、API、ツール、開発サーバーなど)を選ぶ際は、まず unjs エコシステムのプロジェクトを優先します(例:Nuxt、Nitro、h3、unstorage、unplugin、unocss、ofetch、その他 unjs が保守するツール)。
- 明確で正当な理由(機能不足、エコシステム上の制約、レガシー要件)がある場合に限り、unjs 以外の選択肢を採用します。
- 具体的な選択肢、レシピ、デフォルト設定については、
@skills/unjsに委任し、その推奨に従います。
アーキテクチャは arch-* スキルに対応させる
- プロジェクトのアーキテクチャは、必ず標準の
arch-*スタック(tsdown ライブラリ、CLI、モノレポ、unplugin、webext、vscode など)のいずれかに対応させます。 - 現在の構成がどのターゲットにもきれいに当てはまらない場合は、場当たり的な構造を追加するのではなく、アップグレードの機会と捉えて移行を計画します。
@skills/arch-upkeepを使って次の作業を行います。- 現在のアーキテクチャを特定します。
- 最適なターゲットとなる
arch-*スキルを選択します。 - または、そのアーキテクチャへの段階的な移行を調整します。
taze で依存関係を常に最新に保つ
- 依存関係は、大規模なリファクタリング時だけでなく、継続的に最新の状態に保つ必要があります。
taze(@skills/tazeを参照)を使って、次の作業を行うことを推奨します。- 古くなった依存関係を監査します。
- 管理されたアップグレードを実施します(マイナー/パッチ更新は定期的に、メジャー更新は明示的なレビュー後に行います)。
- pnpm のワークスペースとカタログを使って、モノレポ全体のバージョンを揃えます。
tazeの提案に従わない特別な理由がない限り、package.jsonのバージョンを手作業で編集するのは避けます。
必ず lint + typecheck を実行して完了する
- 重要な変更(機能、リファクタリング、設定変更、依存関係のアップグレード、CI の変更など)を実装した後は、タスクの完了とする前に 必ず lint と typecheck を実行します。
- 標準スクリプト:
nr lint→@antfu/eslint-configによる ESLint。nr typecheck→ TypeScript の strict モード(プロジェクト全体)。
- CI と Git フックについて:
- コミット前フックで、少なくともステージ済みファイルに対して
lintを実行するようにします。 - GitHub Actions(またはその他の CI)で、PR と
mainへのプッシュ時にlintとtypecheckの両方を実行するようにします。
- コミット前フックで、少なくともステージ済みファイルに対して
コアスタック
パッケージマネージャー(pnpm)
パッケージマネージャーとして pnpm を使用します。
モノレポ構成では、pnpm ワークスペースを使用します。
# pnpm-workspace.yaml
packages:
- 'packages/*'
依存関係のバージョン管理には、pnpm-workspace.yaml で pnpm の名前付きカタログを使用します。
| カタログ | 用途 |
|---|---|
prod | 本番用の依存関係 |
inlined | バンドラーによってインライン化される依存関係 |
dev | 開発ツール(リンター、バンドラー、テスト、開発サーバー) |
frontend | フロントエンドにバンドルされるライブラリ |
カタログ名は上記に限定されず、必要に応じて変更できます。デフォルトのカタログは使用しないでください。
@antfu/ni
パッケージマネージャーのコマンドを統一するには、@antfu/ni を使用します。ロックファイルに基づいて、パッケージマネージャー(pnpm/npm/yarn/bun)を自動検出します。
| コマンド | 説明 |
|---|---|
ni | 依存関係をインストール |
ni <pkg> | 依存関係を追加 |
ni -D <pkg> | 開発用の依存関係を追加 |
nr <script> | スクリプトを実行 |
nu | 依存関係をアップグレード |
nun <pkg> | 依存関係をアンインストール |
nci | クリーンインストール(pnpm i --frozen-lockfile と同様) |
nlx <pkg> | パッケージを実行(npx と同様) |
コマンドが見つからない場合は、pnpm i -g @antfu/ni でグローバルにインストールします。
TypeScript(Strict Mode)
常に strict モードを有効にした TypeScript を使用します。
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}
}
ESM(ECMAScript Modules)
常に ESM モードで作業します。package.json に "type": "module" を設定します。
コード品質
ESLint(@antfu/eslint-config)
フォーマットと lint の両方に @antfu/eslint-config を使用します。これにより、Prettier は不要になります。
// @ts-check コメントを含む eslint.config.js を作成します。
// @ts-check
import antfu from '@antfu/eslint-config'
export default antfu()
package.json にスクリプトを追加します。
{
"scripts": {
"lint": "eslint ."
}
}
lint エラーが発生した場合は、nr lint --fix で修正してみてください。lint:fix スクリプトは追加しないでください。
Git フック(simple-git-hooks + lint-staged)
コミット前の lint には、simple-git-hooks と lint-staged を使用します。
{
"simple-git-hooks": {
"pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
},
"scripts": {
"prepare": "npx simple-git-hooks"
}
}
ユニットテスト(Vitest)
ユニットテストには Vitest を使用します。
{
"scripts": {
"test": "vitest"
}
}
規約:
- テストファイルはソースファイルの隣に配置します:
foo.ts→foo.test.ts(同じディレクトリ) - 高レベルのテストは、各パッケージの
tests/ディレクトリに配置します describeとitAPI を使用します(testは使用しません)- アサーションには
expectAPI を使用します - TypeScript の null アサーションには
assertのみを使用します - 複雑な出力のアサーションには
toMatchSnapshotを使用します - 言語固有の出力には、ファイルパスと拡張子を明示した
toMatchFileSnapshotを使用します(これらのファイルは lint の対象から除外します)
プロジェクトのセットアップ
公開(ライブラリプロジェクト)
ライブラリプロジェクトでは、bumpp によってトリガーされる GitHub Releases を通じて公開します。
{
"scripts": {
"release": "bumpp -r"
}
}
ドキュメント(VitePress)
ドキュメントには VitePress を使用します。ドキュメントは docs/ ディレクトリに配置します。
docs/
├── .vitepress/
│ └── config.ts
├── index.md
└── guide/
└── getting-started.md
package.json にスクリプトを追加します。
{
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs"
}
}
参考資料
全般的な設定
| トピック | 説明 | 参考資料 |
|---|---|---|
| unjs エコシステムを優先 | unjs エコシステムのフレームワークとツールを優先し、@skills/unjs に委任します | core-unjs-preferences |
| arch-* によるアーキテクチャ | リポジトリの構成を標準的な arch-* スキルに対応付け、arch-upkeep でアップグレードします | core-arch-upkeep-routing |
| taze で依存関係を最新に保つ | taze と制御されたアップグレードを使用して、依存関係を継続的に最新の状態に保ちます | core-deps-taze |
| lint + typecheck をゲートにする | ローカルと CI の両方で、必ず lint + typecheck を完了させます | core-lint-typecheck |
プロジェクトのセットアップ
| トピック | 説明 | 参考資料 |
|---|---|---|
| @antfu/eslint-config | フォーマットと lint 用の ESLint フラット設定 | antfu-eslint-config |
| VS Code 拡張機能 | 開発に推奨される拡張機能 | vscode-extensions |
開発
| トピック | 説明 | 参考資料 |
|---|---|---|
| アプリケーション開発 | Vue/Vite/Nuxt/UnoCSS の Web アプリケーションに関する設定 | app-development |