feat: extract clash_hooks library and unify agent protocol path#411
Open
feat: extract clash_hooks library and unify agent protocol path#411
Conversation
…ent architecture Extract clash_hooks as a standalone crate with two-phase deserialization, per-event field structs (CommonFields + XxxFields), OnceLock-cached typed tool input accessors, and opaque Response builders. - 22+ hook event types with typed response constructors - No RawInput god-object — each event holds only its own fields - parse_payload() macro for concise event dispatch - debug_assert on Response builders to catch silent no-ops - Re-export CommonFields from lib.rs - Migrate clash crate to use clash_hooks types
- Unify Claude output through HookProtocol trait: all agents (including Claude) go through format_decision/format_session_start/etc. with no AgentKind::Claude branches in cmd/hooks.rs - Introduce PolicyDecision enum as the boundary type between policy engine and protocol output, replacing HookOutput-based returns from check_permission - Delete ToolUseHookInput, SessionStartHookInput, StopHookInput, and check_permission_legacy — all input handling uses clash_hooks typed events via recv_from_value - Add recv_from_value to clash_hooks for non-Claude agent protocol normalization - Rename Decision → MatchVerdict, ir::PolicyDecision → PolicyEvaluation, trace::PolicyDecision → TraceDecision to eliminate naming collisions - Eliminate duplicated display/ui formatting: delete print_tool_header, print_decision, print_sandbox_summary from ui.rs; cmd/explain.rs now uses display:: formatters like all other callers - Thread agent through handle_permission_request for consistent check_permission calls - Restore dropped edge-case tests for tool_response: None path
eliothedeman
approved these changes
Apr 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
clash_hooksas a standalone crate (serde,serde_json,thiserror— zero heavy deps) providing typed deserialization of all 22+ Claude Code hook events, cached tool-input accessors, and opaque response constructionHookProtocoltrait methods (format_decision,format_session_start,format_post_tool_use,format_permission_response), eliminatingif agent == Claudebranches incmd/hooks.rsPolicyDecision(Allow/Deny/Ask/Pass) as the single boundary type between the policy engine and protocol output, replacing the oldToolUseHookInput+check_permission_legacypathmatch_tree::Decision→MatchVerdict,ir::PolicyDecision→PolicyEvaluation,trace::PolicyDecision→TraceDecisionToolUseHookInput,check_permission_legacy, duplicated display/ui formatting functionsTest plan
cargo test --workspace— 1,113 tests pass (0 failures)cargo clippy --workspace— cleanToolUseHookInput,check_permission_legacy, orAgentKind::Claudebranches incmd/hooks.rsclash_hookshas 16 unit tests + 23 integration tests + 1 doctest covering all hook event typestool_response: Nonein network_hints and sandbox_hints