claude_hooks 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05073a7e1f50d4391f4afddff10e781bf70c1c1a5ec15b4d8c5cf7959827ca53
4
- data.tar.gz: a477cb849efb154ac3452150030bde9a4219c82887afae7b3fded7d9d01b482c
3
+ metadata.gz: 518b315ef2a184008b91029cdb9735b77ceee67490618d9581be16ff0c42cdb2
4
+ data.tar.gz: c469281a8f36dce611c1aad3f60611d5951219d1718846739d711fc310219c6f
5
5
  SHA512:
6
- metadata.gz: ca053e3783d088baebefa2ffed240a63f624e053dfbaa10e1513191b20428f152414d281a782e2a76ba24490b9d25033271c75c47f85e89785aec7570bcc92ff
7
- data.tar.gz: 54baf322b8031460dfcf92998c86950dd84f25b67d6b3e78270f5951dce81d169b7d355a1e6498c31fd33442572943c93795bce1fbbcb359b32ceecb145af2d6
6
+ metadata.gz: c500ced26412c6666d19cbef211afe43b89dcaa1b6282f6fdeb5ec24874981621d3ef7b742a1c3fc45d9f68c91e838d0c16a6e90fb63c81a6f90facfb0f23e11
7
+ data.tar.gz: db4d7cc2ca66d8d6cb7c3582cda5433f2b6882998f600a43cda170f58951246fd5394704b4ce6136c461138160c509d0e5bbec3390530329b754b11aa62911dc
data/CHANGELOG.md CHANGED
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] - 2025-08-21
9
+
10
+ ### Added
11
+ - **Dual Configuration System**: Support for both home-level (`$HOME/.claude`) and project-level (`$CLAUDE_PROJECT_DIR/.claude`) configurations
12
+ - **Configuration Merging**: Intelligent merging of home and project configs with configurable precedence
13
+ - New environment variable `CLAUDE_HOOKS_CONFIG_MERGE_STRATEGY` to control merge behavior ("project" or "home")
14
+ - New directory access methods: `home_claude_dir`, `project_claude_dir`
15
+ - New path utility methods: `home_path_for(path)`, `project_path_for(path)`
16
+ - Enhanced `path_for(path, base_dir=nil)` method with optional base directory parameter
17
+ - Comprehensive test suite for configuration functionality (`test/` directory)
18
+ - Configuration validation and edge case handling for missing `CLAUDE_PROJECT_DIR`
19
+
20
+ ### Changed
21
+ - **Logs Location**: Logs now always go to `$HOME/.claude/{logDirectory}` regardless of active configuration
22
+ - Configuration loading now supports dual config file locations with intelligent merging
23
+ - Enhanced documentation with comprehensive dual configuration examples
24
+ - Updated API reference with new directory and path methods
25
+
26
+ ### Deprecated
27
+ - `base_dir` method (still functional for backward compatibility)
28
+ - `RUBY_CLAUDE_HOOKS_BASE_DIR` environment variable (still supported as fallback)
29
+
30
+ ### Fixed
31
+ - Graceful handling of undefined `CLAUDE_PROJECT_DIR` environment variable
32
+ - Proper path resolution when project directory is not available
33
+ - Backward compatibility maintained for all existing hook scripts
34
+
35
+ ### Migration Notes
36
+ - Existing configurations continue to work without changes
37
+ - New projects can leverage dual configuration system
38
+ - `base_dir` and legacy `path_for` methods remain functional
39
+ - Environment variables maintain same precedence over config files
40
+
8
41
  ## [0.1.0] - 2025-08-17
9
42
 
10
43
  ### Added
data/README.md CHANGED
@@ -4,6 +4,8 @@ A Ruby DSL (Domain Specific Language) for creating Claude Code hooks. This will
4
4
 
5
5
  [**Why use this instead of writing bash, or simple ruby scripts?**](WHY.md)
6
6
 
7
+ > You might also be interested in my other project, a [Claude Code statusline](https://github.com/gabriel-dehan/claude_monitor_statusline) that shows your Claude usage in realtime ✨.
8
+
7
9
  ## 🚀 Quick Start
8
10
 
9
11
  > [!TIP]
@@ -44,10 +46,11 @@ if __FILE__ == $0
44
46
  end
45
47
  ```
46
48
 
47
- 3. ⚠️ **Make it executable (and test it)**
49
+ 3. ⚠️ **Make it executable**
48
50
  ```bash
49
51
  chmod +x add_context_after_prompt.rb
50
- echo '{"session_id":"test","prompt":"Hello!"}' | ruby add_context_after_prompt.rb
52
+ # Test it
53
+ echo '{"session_id":"test","prompt":"Hello!"}' | ./add_context_after_prompt.rb
51
54
  ```
52
55
 
53
56
  4. **Register it in your `.claude/settings.json`**
@@ -87,6 +90,7 @@ Or add it to your Gemfile (you can add a Gemfile in your `.claude` directory if
87
90
  ```ruby
88
91
  # .claude/Gemfile
89
92
  source 'https://rubygems.org'
93
+
90
94
  gem 'claude_hooks'
91
95
  ```
92
96
 
@@ -101,63 +105,91 @@ $ bundle install
101
105
 
102
106
  ### 🔧 Configuration
103
107
 
104
- This gem uses either environment variables or a global configuration file.
105
-
108
+ Claude Hooks supports both home-level (`$HOME/.claude`) and project-level (`$CLAUDE_PROJECT_DIR/.claude`) directories. Claude Hooks specific config files (`config/config.json`) found in either directory will be merged together.
106
109
 
107
- #### Required Configuration Options
110
+ | Directory | Description | Purpose |
111
+ |-----------|-------------|---------|
112
+ | `$HOME/.claude` | Home Claude directory | Global user settings and logs |
113
+ | `$CLAUDE_PROJECT_DIR/.claude` | Project Claude directory | Project-specific settings |
108
114
 
109
- | Option | Description | Default |
110
- |--------|-------------|---------|
111
- | `baseDir` | Base directory for all Claude files | `~/.claude` |
112
- | `logDirectory` | Directory for logs (relative to baseDir) | `logs` |
115
+ > [!NOTE]
116
+ > Logs always go to `$HOME/.claude/{logDirectory}`
113
117
 
114
- #### Environment Variables (Preferred)
118
+ #### Environment Variables
115
119
 
116
- The gem uses environment variables with the `RUBY_CLAUDE_HOOKS_` prefix for configuration:
120
+ You can configure Claude Hooks through environment variables with the `RUBY_CLAUDE_HOOKS_` prefix:
117
121
 
118
122
  ```bash
119
- export RUBY_CLAUDE_HOOKS_BASE_DIR="~/.claude" # Default: ~/.claude
120
- export RUBY_CLAUDE_HOOKS_LOG_DIR="logs" # Default: logs (relative to base_dir)
123
+ # Existing configuration options
124
+ export RUBY_CLAUDE_HOOKS_LOG_DIR="logs" # Default: logs (relative to HOME/.claude)
125
+ export CLAUDE_HOOKS_CONFIG_MERGE_STRATEGY="project" # Config merge strategy: "project" or "home", default: "project"
126
+ export RUBY_CLAUDE_HOOKS_BASE_DIR="~/.claude" # Deprecated: fallback base directory
121
127
 
122
- # You can add any custom configuration
128
+ # Any variable prefixed with RUBY_CLAUDE_HOOKS_ will also be available through the config object
123
129
  export RUBY_CLAUDE_HOOKS_API_KEY="your-api-key"
124
130
  export RUBY_CLAUDE_HOOKS_DEBUG_MODE="true"
125
131
  export RUBY_CLAUDE_HOOKS_USER_NAME="Gabriel"
126
132
  ```
127
133
 
128
- #### Configuration File
134
+ #### Configuration Files
129
135
 
130
- You can choose to use a global configuration file by setting it up in `~/.claude/config/config.json`.
131
- The gem will read from it as fallback for any missing environment variables.
136
+ You can also use configuration files in any of the two locations:
132
137
 
138
+ **Home config** (`$HOME/.claude/config/config.json`):
133
139
  ```json
134
140
  {
135
- "baseDir": "~/.claude",
141
+ // Existing configuration option
136
142
  "logDirectory": "logs",
137
- "apiKey": "your-api-key",
138
- "debugMode": true,
143
+ // Custom configuration options
144
+ "apiKey": "your-global-api-key",
139
145
  "userName": "Gabriel"
140
146
  }
141
147
  ```
142
148
 
143
- #### Accessing Custom Configuration
149
+ **Project config** (`$CLAUDE_PROJECT_DIR/.claude/config/config.json`):
150
+ ```json
151
+ {
152
+ // Custom configuration option
153
+ "projectSpecificConfig": "someValue",
154
+ }
155
+ ```
156
+
157
+ #### Configuration Merging
158
+
159
+ When both config files exist, they will be merged with configurable precedence:
160
+
161
+ - **Default (`project`)**: Project config values override home config values
162
+ - **Home precedence (`home`)**: Home config values override project config values
163
+
164
+ Set merge strategy: `export CLAUDE_HOOKS_CONFIG_MERGE_STRATEGY="home" | "project"` (default: "project")
165
+
166
+ > [!WARNING]
167
+ > Environment Variables > Merged Config Files
168
+
169
+ #### Accessing Configuration Variables
144
170
 
145
171
  You can access any configuration value in your handlers:
146
172
 
147
173
  ```ruby
148
174
  class MyHandler < ClaudeHooks::UserPromptSubmit
149
175
  def call
150
- # Access built-in config
151
- log "Base dir: #{config.base_dir}"
176
+ # Access directory paths
177
+ log "Home Claude dir: #{home_claude_dir}"
178
+ log "Project Claude dir: #{project_claude_dir}" # nil if CLAUDE_PROJECT_DIR not set
179
+ log "Base dir (deprecated): #{base_dir}"
152
180
  log "Logs dir: #{config.logs_directory}"
153
181
 
182
+ # Path utilities
183
+ log "Home config path: #{home_path_for('config')}"
184
+ log "Project hooks path: #{project_path_for('hooks')}" # nil if no project dir
185
+
154
186
  # Access custom config via method calls
155
187
  log "API Key: #{config.api_key}"
156
188
  log "Debug mode: #{config.debug_mode}"
157
189
  log "User: #{config.user_name}"
158
190
 
159
191
  # Or use get_config_value for more control
160
- user_name = config.get_config_value('USER_NAME', 'userName', )
192
+ user_name = config.get_config_value('USER_NAME', 'userName')
161
193
  log "Username: #{user_name}"
162
194
 
163
195
  output_data
@@ -165,18 +197,16 @@ class MyHandler < ClaudeHooks::UserPromptSubmit
165
197
  end
166
198
  ```
167
199
 
168
- **Configuration Priority:** Environment variables always take precedence over config file values.
169
-
170
200
  ## 📖 Table of Contents
171
201
 
172
202
  - [Ruby DSL for Claude Code hooks](#ruby-dsl-for-claude-code-hooks)
173
203
  - [🚀 Quick Start](#-quick-start)
174
204
  - [📦 Installation](#-installation)
175
205
  - [🔧 Configuration](#-configuration)
176
- - [Required Configuration Options](#required-configuration-options)
177
- - [Environment Variables (Preferred)](#environment-variables-preferred)
178
- - [Configuration File](#configuration-file)
179
- - [Accessing Custom Configuration](#accessing-custom-configuration)
206
+ - [Environment Variables](#environment-variables)
207
+ - [Configuration Files](#configuration-files)
208
+ - [Configuration Merging](#configuration-merging)
209
+ - [Accessing Configuration Variables](#accessing-configuration-variables)
180
210
  - [📖 Table of Contents](#-table-of-contents)
181
211
  - [🏗️ Architecture](#️-architecture)
182
212
  - [Core Components](#core-components)
@@ -184,7 +214,7 @@ end
184
214
  - [🪝 Hook Types](#-hook-types)
185
215
  - [🚀 Claude Hook Flow](#-claude-hook-flow)
186
216
  - [A very simplified view of how a hook works in Claude Code](#a-very-simplified-view-of-how-a-hook-works-in-claude-code)
187
- - [🔄 Claude Hook Execution Flow](#-claude-hook-execution-flow)
217
+ - [🔄 Proposal: a more robust Claude Hook execution flow](#-proposal-a-more-robust-claude-hook-execution-flow)
188
218
  - [Basic Hook Handler Structure](#basic-hook-handler-structure)
189
219
  - [Input Fields](#input-fields)
190
220
  - [📚 API Reference](#-api-reference)
@@ -192,7 +222,9 @@ end
192
222
  - [Input Methods](#input-methods)
193
223
  - [Output Methods](#output-methods)
194
224
  - [Class Output Methods](#class-output-methods)
225
+ - [Configuration and Utility Methods](#configuration-and-utility-methods)
195
226
  - [Utility Methods](#utility-methods)
227
+ - [Configuration Methods](#configuration-methods)
196
228
  - [UserPromptSubmit API](#userpromptsubmit-api)
197
229
  - [Input Methods](#input-methods-1)
198
230
  - [Output Methods](#output-methods-1)
@@ -218,9 +250,6 @@ end
218
250
  - [SessionStart API](#sessionstart-api)
219
251
  - [Input Methods](#input-methods-8)
220
252
  - [Output Methods](#output-methods-8)
221
- - [Configuration and Utility Methods](#configuration-and-utility-methods)
222
- - [Configuration Methods](#configuration-methods)
223
- - [Utility Methods](#utility-methods-2)
224
253
  - [📝 Logging](#-logging)
225
254
  - [Log File Location](#log-file-location)
226
255
  - [Log Output Format](#log-output-format)
@@ -298,10 +327,10 @@ The framework supports the following hook types:
298
327
 
299
328
  ```mermaid
300
329
  graph LR
301
- A[Hook triggers] --> B[JSON from STDIN] --> C[Hook does its thing] --> D[JSON to STDOUT or STDERR]
330
+ A[Hook triggers] --> B[JSON from STDIN] --> C[Hook does its thing] --> D[JSON to STDOUT or STDERR] --> E[Yields back to Claude Code] --> A
302
331
  ```
303
332
 
304
- ### 🔄 Claude Hook Execution Flow
333
+ ### 🔄 Proposal: a more robust Claude Hook execution flow
305
334
 
306
335
  1. An entrypoint for a hook is set in `~/.claude/settings.json`
307
336
  2. Claude Code calls the entrypoint script (e.g., `hooks/entrypoints/pre_tool_use.rb`)
@@ -318,8 +347,8 @@ graph TD
318
347
  C --> D[📋 Entrypoint<br />Parses JSON from STDIN]
319
348
  D --> E[📋 Entrypoint<br />Calls hook handlers]
320
349
 
321
- E --> F[📝 AppendContextRules.call<br/><em>Returns output_data</em>]
322
- E --> G[📝 PromptGuard.call<br/><em>Returns output_data</em>]
350
+ E --> F[📝 Handler<br />AppendContextRules.call<br/><em>Returns output_data</em>]
351
+ E --> G[📝 Handler<br />PromptGuard.call<br/><em>Returns output_data</em>]
323
352
 
324
353
  F --> J[📋 Entrypoint<br />Calls _ClaudeHooks::UserPromptSubmit.merge_outputs_ to 🔀 merge outputs]
325
354
  G --> J
@@ -422,11 +451,30 @@ Each hook type provides a **class method** `merge_outputs` that will try to inte
422
451
  |--------|-------------|
423
452
  | `merge_outputs(*outputs_data)` | Intelligently merge multiple outputs into a single output |
424
453
 
454
+ ### Configuration and Utility Methods
455
+
456
+ Available in all hooks via the base `ClaudeHooks::Base` class:
457
+
425
458
  #### Utility Methods
426
459
  | Method | Description |
427
460
  |--------|-------------|
428
461
  | `log(message, level: :info)` | Log to session-specific file (levels: :info, :warn, :error) |
429
462
 
463
+ #### Configuration Methods
464
+ | Method | Description |
465
+ |--------|-------------|
466
+ | `home_claude_dir` | Get the home Claude directory (`$HOME/.claude`) |
467
+ | `project_claude_dir` | Get the project Claude directory (`$CLAUDE_PROJECT_DIR/.claude`, or `nil`) |
468
+ | `home_path_for(relative_path)` | Get absolute path relative to home Claude directory |
469
+ | `project_path_for(relative_path)` | Get absolute path relative to project Claude directory (or `nil`) |
470
+ | `base_dir` | Get the base Claude directory (**deprecated**) |
471
+ | `path_for(relative_path, base_dir=nil)` | Get absolute path relative to specified or default base dir (**deprecated**) |
472
+ | `config` | Access the merged configuration object |
473
+ | `config.get_config_value(env_key, config_file_key, default)` | Get any config value with fallback |
474
+ | `config.logs_directory` | Get logs directory path (always under home directory) |
475
+ | `config.your_custom_key` | Access any custom config via method_missing |
476
+
477
+
430
478
  ### UserPromptSubmit API
431
479
 
432
480
  Available when inheriting from `ClaudeHooks::UserPromptSubmit`:
@@ -560,26 +608,6 @@ Available when inheriting from `ClaudeHooks::SessionStart`:
560
608
  | `add_context!(context)` | Alias for `add_additional_context!` |
561
609
  | `empty_additional_context!` | Clear additional context |
562
610
 
563
- ### Configuration and Utility Methods
564
-
565
- Available in all hooks via the base `ClaudeHooks::Base` class:
566
-
567
- #### Configuration Methods
568
- | Method | Description |
569
- |--------|-------------|
570
- | `base_dir` | Get the base Claude directory |
571
- | `path_for(relative_path)` | Get absolute path relative to base dir |
572
- | `config` | Access the full configuration object |
573
- | `config.get_config_value(env_key, config_key, default)` | Get any config value with fallback |
574
- | `config.logs_directory` | Get logs directory path |
575
- | `config.your_custom_key` | Access any custom config via method_missing |
576
-
577
- #### Utility Methods
578
- | Method | Description |
579
- |--------|-------------|
580
- | `log(message, level: :info)` | Log to session-specific file (levels: :info, :warn, :error) |
581
- | `log(level: :info) { block }` | Multiline logging with block support |
582
-
583
611
  ### 📝 Logging
584
612
 
585
613
  `ClaudeHooks::Base` provides a **session logger** that will write logs to session-specific files.
@@ -2,8 +2,8 @@
2
2
 
3
3
  require 'claude_hooks'
4
4
  require 'json'
5
- require_relative '../user_prompt_submit/append_rules'
6
- require_relative '../user_prompt_submit/log_user_prompt'
5
+ require_relative '../handlers/user_prompt_submit/append_rules'
6
+ require_relative '../handlers/user_prompt_submit/log_user_prompt'
7
7
 
8
8
  begin
9
9
  # Read input from stdin
@@ -111,8 +111,24 @@ module ClaudeHooks
111
111
  config.base_dir
112
112
  end
113
113
 
114
- def path_for(relative_path)
115
- config.path_for(relative_path)
114
+ def home_claude_dir
115
+ config.home_claude_dir
116
+ end
117
+
118
+ def project_claude_dir
119
+ config.project_claude_dir
120
+ end
121
+
122
+ def path_for(relative_path, base_directory = nil)
123
+ config.path_for(relative_path, base_directory)
124
+ end
125
+
126
+ def home_path_for(relative_path)
127
+ config.home_path_for(relative_path)
128
+ end
129
+
130
+ def project_path_for(relative_path)
131
+ config.project_path_for(relative_path)
116
132
  end
117
133
 
118
134
  # Supports both single messages and blocks for multiline logging
@@ -16,29 +16,75 @@ module ClaudeHooks
16
16
  def reload!
17
17
  @config = nil
18
18
  @base_dir = nil
19
+ @home_claude_dir = nil
20
+ @project_claude_dir = nil
19
21
  @config_file_path = nil
22
+ @home_config_file_path = nil
23
+ @project_config_file_path = nil
20
24
  end
21
25
 
22
- # Get the base directory from ENV or default
26
+ # Get the home Claude directory (always ~/.claude)
27
+ def home_claude_dir
28
+ @home_claude_dir ||= File.expand_path('~/.claude')
29
+ end
30
+
31
+ # Get the project Claude directory (from CLAUDE_PROJECT_DIR/.claude)
32
+ # Returns nil if CLAUDE_PROJECT_DIR environment variable is not set
33
+ def project_claude_dir
34
+ @project_claude_dir ||= begin
35
+ project_dir = ENV['CLAUDE_PROJECT_DIR']
36
+ if project_dir
37
+ File.expand_path(File.join(project_dir, '.claude'))
38
+ else
39
+ nil
40
+ end
41
+ end
42
+ end
43
+
44
+ # Get the base directory from ENV or default (backward compatibility)
45
+ # This method will determine which base directory to use based on context
23
46
  def base_dir
24
47
  @base_dir ||= begin
48
+ # Check for legacy environment variable first
25
49
  env_base_dir = ENV["#{ENV_PREFIX}BASE_DIR"]
26
- File.expand_path(env_base_dir || '~/.claude')
50
+ if env_base_dir
51
+ File.expand_path(env_base_dir)
52
+ else
53
+ # Default to home directory for backward compatibility
54
+ home_claude_dir
55
+ end
27
56
  end
28
57
  end
29
58
 
30
59
  # Get the full path for a file/directory relative to base_dir
31
- def path_for(relative_path)
32
- File.join(base_dir, relative_path)
60
+ # Can optionally specify which base directory to use
61
+ def path_for(relative_path, base_directory = nil)
62
+ base_directory ||= base_dir
63
+ File.join(base_directory, relative_path)
33
64
  end
34
65
 
35
- # Get the log directory path
66
+ # Get the full path for a file/directory relative to home_claude_dir
67
+ def home_path_for(relative_path)
68
+ File.join(home_claude_dir, relative_path)
69
+ end
70
+
71
+ # Get the full path for a file/directory relative to project_claude_dir
72
+ # Returns nil if CLAUDE_PROJECT_DIR environment variable is not set
73
+ def project_path_for(relative_path)
74
+ if project_claude_dir
75
+ File.join(project_claude_dir, relative_path)
76
+ else
77
+ nil
78
+ end
79
+ end
80
+
81
+ # Get the log directory path (always relative to home_claude_dir)
36
82
  def logs_directory
37
83
  log_dir = get_config_value('LOG_DIR', 'logDirectory') || 'logs'
38
84
  if log_dir.start_with?('/')
39
85
  log_dir # Absolute path
40
86
  else
41
- path_for(log_dir) # Relative to base_dir
87
+ File.join(home_claude_dir, log_dir) # Always relative to home_claude_dir
42
88
  end
43
89
  end
44
90
 
@@ -92,25 +138,63 @@ module ClaudeHooks
92
138
  @config_file_path ||= path_for('config/config.json')
93
139
  end
94
140
 
141
+ def home_config_file_path
142
+ @home_config_file_path ||= File.join(home_claude_dir, 'config/config.json')
143
+ end
144
+
145
+ def project_config_file_path
146
+ @project_config_file_path ||= begin
147
+ if project_claude_dir
148
+ File.join(project_claude_dir, 'config/config.json')
149
+ else
150
+ nil
151
+ end
152
+ end
153
+ end
154
+
95
155
  def load_config
96
- # Start with config file
97
- file_config = load_config_file
156
+ # Load and merge config files from both locations
157
+ merged_file_config = load_and_merge_config_files
98
158
 
99
159
  # Merge with ENV variables
100
160
  env_config = load_env_config
101
161
 
102
- # ENV variables take precedence
103
- file_config.merge(env_config)
162
+ # ENV variables take precedence over file configs
163
+ merged_file_config.merge(env_config)
164
+ end
165
+
166
+ def load_and_merge_config_files
167
+ home_config = load_config_file_from_path(home_config_file_path)
168
+ project_config = load_config_file_from_path(project_config_file_path) if project_config_file_path
169
+
170
+ # Determine merge strategy
171
+ merge_strategy = ENV['CLAUDE_HOOKS_CONFIG_MERGE_STRATEGY'] || 'project'
172
+
173
+ if project_config && merge_strategy == 'project'
174
+ # Project config takes precedence
175
+ home_config.merge(project_config)
176
+ elsif project_config && merge_strategy == 'home'
177
+ # Home config takes precedence
178
+ project_config.merge(home_config)
179
+ else
180
+ # Only home config exists or no project config
181
+ home_config
182
+ end
104
183
  end
105
184
 
106
185
  def load_config_file
107
186
  config_file = config_file_path
187
+ load_config_file_from_path(config_file)
188
+ end
189
+
190
+ def load_config_file_from_path(config_file_path)
191
+ return {} unless config_file_path
108
192
 
109
- if File.exist?(config_file)
193
+ if File.exist?(config_file_path)
110
194
  begin
111
- JSON.parse(File.read(config_file))
195
+ JSON.parse(File.read(config_file_path))
112
196
  rescue JSON::ParserError => e
113
- warn "Warning: Error parsing config file #{config_file}: #{e.message}"
197
+ warn "Warning: Error parsing config file #{config_file_path}: #{e.message}"
114
198
  {}
115
199
  end
116
200
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClaudeHooks
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: claude_hooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Dehan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-17 00:00:00.000000000 Z
11
+ date: 2025-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json