Skip to content

refactor: overhaul hook system with dynamic types and convention-based registration#75

Merged
htcarr3 merged 1 commit intomainfrom
hooks-improvements-032126
Mar 21, 2026
Merged

refactor: overhaul hook system with dynamic types and convention-based registration#75
htcarr3 merged 1 commit intomainfrom
hooks-improvements-032126

Conversation

@htcarr3
Copy link
Copy Markdown
Contributor

@htcarr3 htcarr3 commented Mar 21, 2026

What

Replaces the rigid per-event hook system with a dynamic, convention-based architecture. Adding a new CLI hook event is now one string in an array instead of changes to three separate files.

Why

Every new hook event required updating HOOK_EVENTS, EVENT_MAP, and a define_input declaration — 23 events × 3 locations. The typed input classes (PreToolUseInput, etc.) weren't even used in the dispatch path. This refactor eliminates that maintenance burden and gives each type a clear reason to exist.

How

Hook base class — replaces HookMatcher. Owns matching (matches?), CLI serialization (to_config), and callback dispatch (dispatch). event_name is derived from the class name by convention (PreToolUseHook"PreToolUse"). Subclasses are generated per event by HookRegistry.register.

HookInput — single dynamic class replacing 23 static *Input classes. Base fields (session_id, cwd, etc.) are first-class readers; event-specific fields use method_missing. Frozen at construction.

HookRegistryEnumerable collection that persists as the data structure in Options#hooks (no more compile-to-hash step). register("PreToolUse") generates both a PreToolUseHook class and a before_tool_use DSL method. wrap normalizes any input type. from_hash builds from raw hashes.

Hook#dispatch — wires HookInput and HookContext into the actual callback dispatch path (previously callbacks received raw hashes).

Key changes

  • -648 lines net (23 files, 780 additions, 1428 deletions)
  • Hook, HookInput, HookContext, HookRegistry in hooks/ directory
  • Hook::CallbackEntry replaces plain hash in callback registry
  • build_hooks_config reduced from 20 lines to 7
  • All docs, CHANGELOG, SPEC, and architecture guide updated

…d registration

- Replace HookMatcher with Hook base class; HookRegistry.register generates
  typed subclasses (e.g., PreToolUseHook) and DSL methods by convention
- Replace 23 static *Input classes with a single dynamic HookInput
- Move Hook responsibilities: dispatch (wraps input/context), to_config
  (builds CLI payload), matches? (tool name filtering), event_name
  (derived from class name)
- Make HookRegistry Enumerable — it persists as the data structure in
  Options#hooks instead of compiling to a hash and being discarded
- Add HookRegistry.wrap for uniform input normalization
- Restructure into hooks/ directory
- Update docs, CHANGELOG, SPEC, and architecture guide
@htcarr3 htcarr3 force-pushed the hooks-improvements-032126 branch from b0b8fa7 to fb32434 Compare March 21, 2026 21:24
@htcarr3 htcarr3 merged commit 9da886b into main Mar 21, 2026
1 check passed
@htcarr3 htcarr3 deleted the hooks-improvements-032126 branch March 21, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant