validate と型チェック
claude plugin validate <mod のフォルダ> # manifest とソースを読み、Claude Code 本体が拒否する箇所を報告する
tsc -p <mod のフォルダ> # 一度読み込まれた mod には tsconfig が配置されている
claude plugin test <mod のフォルダ> # *.test.ts を実行する
claude --debug # 失敗したフックや拒否された結果をすべてログに出力する
validate は、モジュールがフックするイベント、呼び出す $ のメソッド、使用する $.state のキーと環境変数名、拒否できるイベントのフックに .catch があるかどうかを一覧にします。読み込まれた mod のフォルダには、.claude-plugin/types/ に次の型定義が配置されます: claude-code/index.d.ts(API)、claude-code-tools/index.d.ts(組み込みツール。e.tool === "Bash" と書くと e の型が絞り込まれる)、claude-code-mcp/index.d.ts(接続中の MCP ツール)、依存プラグインの型定義、tsconfig.json。これらの型定義は Claude Code 本体が生成するもので、手で編集するものではありません。
テスト(claude-code/testing)
claude plugin test は、フックと同じ実行環境(ファイルシステム、ネットワーク、プロセスは使えない)で *.test.ts と *.test.tsx を実行します。テスト対象のプラグインは、Claude Code 本体のホストによってフォルダから読み込まれます。
import { test, expect, mock } from 'claude-code/testing'
test('Edit で .env への書き込みを拒否する', async ($, on) => {
const r = await $.tool.call({ tool: 'Edit', file_path: '.env', old_string: 'a', new_string: 'b' })
expect(r.deny).toBeDefined()
})
test('どの表示環境でも帯を描画できる', async $ => {
for (const surface of ['terminal', 'desktop'] as const) {
const ui = await $.ui.mount({ plugin: 'turn-band', surface, component: 'AbovePrompt', props: { /* … */ } })
await ui.press({ key: 'hide' })
await ui.unmount()
}
})
test(name, async ($, on) => …)の$は Claude Code 本体のもので、onで登録したフックはテスト対象のプラグインより内側(Claude Code 本体の位置)に入る。test(name, { options }, body)と書くと、userConfigの値を指定できる。mockのclock、store、envはメモリ上で動作する。mock.session(on)を使うと、追加された行を読み出せる。$.ui.mountでは、表示環境を必ず指定する。find、press、input、key、postで操作し、awaitの直後に検証してよい。describe、expect、tierも使える。
読み込み方
| 方法 | 説明 |
|---|---|
claude --plugin-dir <folder> | そのセッションに限り、ディスク上のフォルダからプラグインを読み込む(複数回指定できる)。対話セッションではフォルダを監視し、ファイルを保存するとリロードする。 |
CLAUDE_CODE_PLUGIN_DIRS | コマンドラインのフラグを渡せない環境(デスクトップアプリ、SDK)で使う。パス区切り文字で区切って複数指定できる。プロセスの環境変数か、~/.claude/settings.json の env で設定する(プロジェクトの設定では指定できない)。 |
CLAUDE_CODE_PLUGIN_DIR_WATCH=1 | 長時間動作するヘッドレスセッションでも、フォルダを監視する。 |
| フォルダを marketplace にする | claude plugin marketplace add <folder> で追加し、エントリの source が相対パスの場合は、インストール時のコピーではなくフォルダそのものを読み込む。編集後は /reload-plugins を実行する。 |
リロードとは、モジュールの読み直しのことです。register と session.start がもう一度実行され、モジュール変数とタイマーは破棄されます。$.state と $.store はホスト側で管理されているため、リロード後も保持されます。ターンの実行中に保存したファイルは、ターンの終了時にまとめて1回だけリロードされます。userConfig の値は settings の pluginConfigs に、プラグイン名をキーとして保存されます。秘密情報でないフィールドは /config の項目としても表示されます(options を列挙した string 型のフィールドは選択式になります)。
配布
mod のリポジトリに .claude-plugin/marketplace.json を1つ置くと、そのリポジトリが marketplace になります。
{
"name": "<marketplace>",
"owner": { "name": "<author>" },
"plugins": [{ "name": "<mod>", "source": "./" }]
}
利用者は、ターミナルのセッションで次のコマンドを実行するだけでインストールできます。README のインストール手順にも、このコマンドを記載します。
/plugin install <mod> --marketplace <owner>/<repo>
実行すると、Add marketplace? に y で答え、スコープを選択し(先頭は user)、userConfig がある場合は設定画面で値を入力します。最後に Installed <mod>. Plugin is now active. と表示されます。フックモジュールだけで構成された mod は、リロードせずにその場で有効になります。デスクトップアプリの Code タブではこのコマンドは使えませんが、ターミナルから user スコープでインストールした mod はそこでも読み込まれ、表示環境 desktop 向けに描画されます。
絞り込みの条件に一致する行がありません。