Class: ClaudeHooks::Output::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/claude_hooks/output/base.rb

Overview

Base class for all Claude Code hook output handlers Handles common functionality like continue/stop logic, output streams, and exit codes

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Base

Returns a new instance of Base.



12
13
14
# File 'lib/claude_hooks/output/base.rb', line 12

def initialize(data)
  @data = data || {}
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



10
11
12
# File 'lib/claude_hooks/output/base.rb', line 10

def data
  @data
end

Class Method Details

.for_hook_type(hook_type, data) ⇒ Object

Factory method to create the correct output class for a given hook type



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/claude_hooks/output/base.rb', line 121

def self.for_hook_type(hook_type, data)
  case hook_type
  when 'UserPromptSubmit'
    UserPromptSubmit.new(data)
  when 'PreToolUse'
    PreToolUse.new(data)
  when 'PermissionRequest'
    PermissionRequest.new(data)
  when 'PostToolUse'
    PostToolUse.new(data)
  when 'Stop'
    Stop.new(data)
  when 'SubagentStop'
    SubagentStop.new(data)
  when 'Notification'
    Notification.new(data)
  when 'MessageDisplay'
    MessageDisplay.new(data)
  when 'SessionStart'
    SessionStart.new(data)
  when 'SessionEnd'
    SessionEnd.new(data)
  when 'PreCompact'
    PreCompact.new(data)
  when 'Setup'
    Setup.new(data)
  when 'SubagentStart'
    SubagentStart.new(data)
  when 'UserPromptExpansion'
    UserPromptExpansion.new(data)
  when 'PostToolBatch'
    PostToolBatch.new(data)
  when 'ConfigChange'
    ConfigChange.new(data)
  when 'TaskCreated'
    TaskCreated.new(data)
  when 'TaskCompleted'
    TaskCompleted.new(data)
  when 'TeammateIdle'
    TeammateIdle.new(data)
  when 'PostToolUseFailure'
    PostToolUseFailure.new(data)
  when 'StopFailure'
    StopFailure.new(data)
  when 'PostCompact'
    PostCompact.new(data)
  when 'CwdChanged'
    CwdChanged.new(data)
  when 'FileChanged'
    FileChanged.new(data)
  when 'InstructionsLoaded'
    InstructionsLoaded.new(data)
  when 'WorktreeRemove'
    WorktreeRemove.new(data)
  when 'PermissionDenied'
    PermissionDenied.new(data)
  when 'Elicitation'
    Elicitation.new(data)
  when 'ElicitationResult'
    ElicitationResult.new(data)
  when 'WorktreeCreate'
    WorktreeCreate.new(data)
  else
    raise ArgumentError, "Unknown hook type: #{hook_type}"
  end
end

.merge(*outputs) ⇒ Object

Base merge method - handles common fields like continue, stopReason, suppressOutput Subclasses should call super and add their specific logic



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/claude_hooks/output/base.rb', line 91

def self.merge(*outputs)
  compacted_outputs = outputs.compact

  merged_data = {
    'continue' => true,
    'stopReason' => '',
    'suppressOutput' => false,
    'systemMessage' => ''
  }

  return compacted_outputs.first if compacted_outputs.length == 1
  return self.new(merged_data) if compacted_outputs.empty?

  # Apply base merge logic
  compacted_outputs.each do |output|
    output_data = output.respond_to?(:data) ? output.data : output

    merged_data['continue'] = false if output_data['continue'] == false
    merged_data['suppressOutput'] = true if output_data['suppressOutput'] == true
    merged_data['stopReason'] = [merged_data['stopReason'], output_data['stopReason']].compact.reject(&:empty?).join('; ')
    merged_data['systemMessage'] = [merged_data['systemMessage'], output_data['systemMessage']].compact.reject(&:empty?).join('; ')
    merged_data['terminalSequence'] = output_data['terminalSequence'] unless output_data['terminalSequence'].nil?
  end

  self.new(merged_data)
end

Instance Method Details

#continue?Boolean

Check if Claude should continue processing

Returns:

  • (Boolean)


19
20
21
# File 'lib/claude_hooks/output/base.rb', line 19

def continue?
  @data['continue'] != false
end

#exit_codeObject

Determine the exit code based on hook-specific logic

Raises:

  • (NotImplementedError)


78
79
80
# File 'lib/claude_hooks/output/base.rb', line 78

def exit_code
  raise NotImplementedError, "Subclasses must implement exit_code"
end

#hook_specific_outputObject

Get the hook-specific output data



39
40
41
# File 'lib/claude_hooks/output/base.rb', line 39

def hook_specific_output
  @data['hookSpecificOutput'] || {}
end

#output_and_exitObject

Main execution method - handles output and exits with correct code



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/claude_hooks/output/base.rb', line 58

def output_and_exit
  stream = output_stream
  code = exit_code

  case stream
  when :stdout
    $stdout.puts to_json
  when :stderr
    $stderr.puts to_json
  else
    raise "Unknown output stream: #{stream}"
  end

  exit code
end

#output_streamObject

Determine the output stream (:stdout or :stderr)



83
84
85
# File 'lib/claude_hooks/output/base.rb', line 83

def output_stream
  default_output_stream
end

#stop_reasonObject

Get the stop reason if continue is false



24
25
26
# File 'lib/claude_hooks/output/base.rb', line 24

def stop_reason
  @data['stopReason'] || ''
end

#suppress_output?Boolean

Check if output should be suppressed from transcript

Returns:

  • (Boolean)


29
30
31
# File 'lib/claude_hooks/output/base.rb', line 29

def suppress_output?
  @data['suppressOutput'] == true
end

#system_messageObject

Get the system message (if any)



34
35
36
# File 'lib/claude_hooks/output/base.rb', line 34

def system_message
  @data['systemMessage'] || ''
end

#terminal_sequenceObject



43
44
45
# File 'lib/claude_hooks/output/base.rb', line 43

def terminal_sequence
  @data['terminalSequence']
end

#to_json(*args) ⇒ Object Also known as: stringify

Convert to JSON string (same as existing stringify_output)



50
51
52
# File 'lib/claude_hooks/output/base.rb', line 50

def to_json(*args)
  JSON.generate(@data, *args)
end