Class: Coat::Hook
- Inherits:
-
Object
- Object
- Coat::Hook
- Defined in:
- lib/coat/hook.rb
Overview
One Claude Code hook payload, said in coat's own words: who made the scrap, what ran, what came out. This maps fields and decides nothing - the collector still says what a piece is.
Constant Summary collapse
- UNKNOWN_AGENT =
"claude"- UNKNOWN_LABEL =
"scrap"- KEY_LENGTH =
16
Class Method Summary collapse
Instance Method Summary collapse
-
#agent ⇒ Object
Subagents are named by the agent type they were spawned as; anything else was Claude itself.
-
#body ⇒ Object
Nil when there is nothing worth keeping, so an empty result does not become an empty patch.
- #cmd ⇒ Object
- #cwd ⇒ Object
- #event ⇒ Object
-
#exit_code ⇒ Object
Read only if the payload carries one.
-
#initialize(payload) ⇒ Hook
constructor
A new instance of Hook.
-
#key ⇒ Object
Pins have to be found again by the hook that fires after the work, and the tool input is the only thing both hooks are guaranteed to see the same.
- #label ⇒ Object
Constructor Details
#initialize(payload) ⇒ Hook
Returns a new instance of Hook.
21 22 23 |
# File 'lib/coat/hook.rb', line 21 def initialize(payload) @payload = payload end |
Class Method Details
.read(io) ⇒ Object
15 16 17 18 19 |
# File 'lib/coat/hook.rb', line 15 def self.read(io) new(JSON.parse(io.read)) rescue JSON::ParserError => e raise Error, "hook payload is not valid JSON: #{e.}" end |
Instance Method Details
#agent ⇒ Object
Subagents are named by the agent type they were spawned as; anything else was Claude itself.
45 46 47 |
# File 'lib/coat/hook.rb', line 45 def agent input["subagent_type"] || UNKNOWN_AGENT end |
#body ⇒ Object
Nil when there is nothing worth keeping, so an empty result does not become an empty patch.
68 69 70 71 |
# File 'lib/coat/hook.rb', line 68 def body text = flatten(response) text unless text.strip.empty? end |
#cmd ⇒ Object
53 54 55 |
# File 'lib/coat/hook.rb', line 53 def cmd input["command"] end |
#cwd ⇒ Object
29 30 31 |
# File 'lib/coat/hook.rb', line 29 def cwd @payload["cwd"] || Dir.pwd end |
#event ⇒ Object
25 26 27 |
# File 'lib/coat/hook.rb', line 25 def event @payload["hook_event_name"] end |
#exit_code ⇒ Object
Read only if the payload carries one. Claude Code does not promise an exit status for every tool, and a guessed exit status is worse than none: it would mark patches torn that never tore.
60 61 62 63 64 |
# File 'lib/coat/hook.rb', line 60 def exit_code return nil unless response.is_a?(Hash) response["exit_code"] || response["exitCode"] end |
#key ⇒ Object
Pins have to be found again by the hook that fires after the work, and the tool input is the only thing both hooks are guaranteed to see the same.
ponytail: two byte-identical tool calls in flight at once share a key, so the later pin wins and one of them gets the other's claims. Pin by hand with --key if that ever shows up.
39 40 41 |
# File 'lib/coat/hook.rb', line 39 def key Digest::SHA256.hexdigest(JSON.generate(input))[0, KEY_LENGTH] end |
#label ⇒ Object
49 50 51 |
# File 'lib/coat/hook.rb', line 49 def label input["description"] || input["command"] || @payload["tool_name"] || UNKNOWN_LABEL end |