next のプロパティ
| プロパティ | 説明 |
|---|---|
next(e) | 後続のフック、Claude Code 本体の順に実行し、その結果を返す。呼び出すたびに後続の処理がもう一度実行される。 |
next.signal | この dispatch(イベント1回分の処理)が中止されたときに abort される AbortSignal。ユーザーが中断した、先行するフックが結果を返した、自分の制限時間を超えた、のいずれかで abort される。フックが開始した処理はこのシグナルで停止させる。 |
next.budget | 制限時間 { ms, remainingMs }。参照するたびに最新の値が返る。if (next.budget.remainingMs < 2_000) return next(e) のように使う。 |
next.origin | この dispatch の発生元({ plugin, tier })。Claude Code 本体が発生させた場合は { plugin: "engine", tier: "core" } になる。値はホストが設定するため、プラグインが偽装することはできない。 |
next.event | このイベントの名前。glob で登録したフックがイベントごとに処理を分けるときに使う。 |
next.is(pattern, e) | e が指定したパターンのイベントかどうかを判定する型述語。 |
next.to(e, tier) | 途中のティアを飛ばし、指定したティアから処理を続ける。ティアとは、チェーンの順序を決める層のことで、自作の mod は user ティアに入る(権限を含む詳細は後述のティア表を参照)。組織が配布する managed プラグイン向けの機能で、user ティアのフックが組織のフックを飛ばすことはできない。 |
next.trace | 直近の next() 呼び出しで、後続の各フックがどのように処理されたかの記録。近い順に並び、最後が Claude Code 本体になる。 |
next.called / next.error | .catch ハンドラの中で使う。called はフックが next を呼んだかどうか、error.kind は失敗の種類(throw / timeout / re-entry)を表す。 |
マッチャー
on(event, matcher, hook) の matcher には、e の一部の形を指定します。
| 書き方 | 意味 | 例 |
|---|---|---|
| スカラー値 | === で比較する | { tool: 'Bash' } |
| 正規表現 | 値を文字列として照合する | { command: /^p4 / } |
| 配列 | いずれか1つに一致すればよい | { tool: ['Edit', 'Write'] } |
| オブジェクト | 入れ子のオブジェクトに部分一致する | { props: { origin: { kind: 'task-notification' } } } |
{ startsWith: 'p4' } のような演算子はなく、このように書いても文字列には一致しません(型が付いている箇所では型エラーになります)。telemetry.* のイベントは名前で指定する必要があり、* や否定のパターンでは選択されません。
ティア(チェーンの順序)
ティアは、プラグインを誰が入れたかによってフックを分けた層です。同じイベントのフックは、表の上から順に、外側から内側へ入れ子になって実行されます。外側のティアほど権限が強くなります。
| ティア | 内容 | 権限 |
|---|---|---|
prepend | 管理者が配布する managed プラグイン(外側) | 最も強い |
user | ユーザーがインストールしたプラグイン。自作の mod はこのティアに入る | 2番目に強い |
append | 管理者が配布する managed プラグイン(内側) | 3番目に強い |
builtin | バイナリに同梱されたプラグイン | 4番目に強い |
core | Claude Code 本体(最も内側) | 最も弱い |
next.to(e, tier) は、組織が配布する managed プラグイン(prepend と append)のフックのための機能です。prepend のフックは append、builtin、core のいずれかを、append のフックは core を指定できます。user ティアのフックが組織のフックを飛ばすことはできません。
制限時間
| 名前 | 値 | 説明 |
|---|---|---|
ms | 10,000 ms | 1回の dispatch でフックが使える時間。next や $ の呼び出しの完了を待っている間は計測が止まるため、1分かかる $.model.complete を待っても消費されない。ただし $.clock.sleep の待ち時間は消費される。 |
catchMs | 1,000 ms | .catch ハンドラに与えられる時間。ハンドラが呼ばれた時点から改めて計測する。 |
lingerMs | 5,000 ms | next.signal が abort された後もフックが実行を続けてよい時間。超えると、終了していないフックとして報告される。 |
ストリーミングのフック(async generator)は、フック自身のコードが実行されている時間だけを計測します。turn.step では応答全体の合計、process.spawn ではチャンクごとに計測します。session.end ではチェーン全体で1つの短い制限時間を共有し、engine.create には制限時間がありません。
失敗と .catch(ガード)
失敗したフック(例外を投げた、制限時間を超えた、そのイベントで受け付けない形の値を返した)はスキップされ、チェーンはそのフックを除いて続行されます。そのため、拒否のためのガードが失敗すると、拒否は行われずに処理が通ってしまいます。拒否によって保護したいフックには、必ず .catch を付けてください。
on('tool.call', { tool: 'Edit' }, ($, e, next) =>
/(^|\/)\.env(\.|$)/.test(e.file_path)
? { deny: `${$.plugin.name}: ${e.file_path} は保護されています` }
: next(e),
).catch(($, e, next) =>
next.called ? next(e) : { deny: `${$.plugin.name}: ガードの処理に失敗しました` },
)
next.calledが true のとき、next(e)は先に実行した呼び出しの結果を返すだけで、処理が二重に実行されることはない。そのため、ガードはnextを呼ぶ前に判定する。tool.checkではnext(e)は判定結果を読み出すだけで何も実行しないため、ハンドラは常に{ decision: 'deny' }を返してよい。- ハンドラは再入(re-entry)のときにも呼ばれる。再入とは、フック自身の
$呼び出しから同じイベントが発生した場合のことで、このときフック本体は実行されない。next.error.kindは're-entry'、next.calledは false になる。呼び出した名前空間の処理から発生した場合はnext.error.causeが'lent'になる。再入時のハンドラ内で$を呼ぶと reject される。 claude plugin validateは、戻り値で拒否できるイベントのフックをgating hook with .catch:またはgating hook without .catch:として列挙する。これは警告ではなく、事実の報告である。
拒否を表す戻り値はイベントごとに異なります。tool.call、agent.spawn、config.set、prompt.mention は { deny }、prompt.submit は { drop }、command.run は { text }、agent.offer は { isOffered: false }、plugin.register は { refuse } です。
絞り込みの条件に一致する行がありません。