claude-code-templates 1.16.1 → 1.17.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.
Files changed (101) hide show
  1. package/README.md +7 -7
  2. package/bin/create-claude-config.js +17 -8
  3. package/package.json +2 -3
  4. package/src/analytics/core/AgentAnalyzer.js +17 -3
  5. package/src/analytics/core/ProcessDetector.js +23 -7
  6. package/src/analytics/core/StateCalculator.js +102 -33
  7. package/src/analytics/data/DataCache.js +7 -7
  8. package/src/analytics-web/chats_mobile.html +2590 -0
  9. package/src/analytics-web/components/App.js +10 -10
  10. package/src/analytics-web/components/SessionTimer.js +1 -1
  11. package/src/analytics-web/components/Sidebar.js +5 -14
  12. package/src/analytics-web/index.html +932 -78
  13. package/src/analytics.js +263 -5
  14. package/src/chats-mobile.js +682 -0
  15. package/src/claude-api-proxy.js +460 -0
  16. package/src/file-operations.js +239 -36
  17. package/src/health-check.js +310 -0
  18. package/src/index.js +1245 -36
  19. package/src/tracking-service.js +31 -34
  20. package/components/agents/api-security-audit.md +0 -92
  21. package/components/agents/database-optimization.md +0 -94
  22. package/components/agents/react-performance-optimization.md +0 -64
  23. package/components/commands/check-file.md +0 -53
  24. package/components/commands/generate-tests.md +0 -68
  25. package/components/mcps/deepgraph-nextjs.json +0 -12
  26. package/components/mcps/deepgraph-react.json +0 -12
  27. package/components/mcps/deepgraph-typescript.json +0 -12
  28. package/components/mcps/deepgraph-vue.json +0 -12
  29. package/components/mcps/filesystem-access.json +0 -12
  30. package/components/mcps/github-integration.json +0 -11
  31. package/components/mcps/memory-integration.json +0 -8
  32. package/components/mcps/mysql-integration.json +0 -11
  33. package/components/mcps/postgresql-integration.json +0 -11
  34. package/components/mcps/web-fetch.json +0 -8
  35. package/src/analytics-web/components/AgentsPage.js +0 -4761
  36. package/templates/common/.claude/commands/git-workflow.md +0 -239
  37. package/templates/common/.claude/commands/project-setup.md +0 -316
  38. package/templates/common/.mcp.json +0 -41
  39. package/templates/common/CLAUDE.md +0 -109
  40. package/templates/common/README.md +0 -96
  41. package/templates/go/.mcp.json +0 -78
  42. package/templates/go/README.md +0 -25
  43. package/templates/javascript-typescript/.claude/commands/api-endpoint.md +0 -51
  44. package/templates/javascript-typescript/.claude/commands/debug.md +0 -52
  45. package/templates/javascript-typescript/.claude/commands/lint.md +0 -48
  46. package/templates/javascript-typescript/.claude/commands/npm-scripts.md +0 -48
  47. package/templates/javascript-typescript/.claude/commands/refactor.md +0 -55
  48. package/templates/javascript-typescript/.claude/commands/test.md +0 -61
  49. package/templates/javascript-typescript/.claude/commands/typescript-migrate.md +0 -51
  50. package/templates/javascript-typescript/.claude/settings.json +0 -142
  51. package/templates/javascript-typescript/.mcp.json +0 -80
  52. package/templates/javascript-typescript/CLAUDE.md +0 -185
  53. package/templates/javascript-typescript/README.md +0 -259
  54. package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +0 -63
  55. package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +0 -62
  56. package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +0 -46
  57. package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +0 -56
  58. package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +0 -61
  59. package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +0 -57
  60. package/templates/javascript-typescript/examples/node-api/CLAUDE.md +0 -102
  61. package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +0 -29
  62. package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +0 -44
  63. package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +0 -45
  64. package/templates/javascript-typescript/examples/react-app/CLAUDE.md +0 -81
  65. package/templates/javascript-typescript/examples/react-app/agents/react-performance-optimization.md +0 -530
  66. package/templates/javascript-typescript/examples/react-app/agents/react-state-management.md +0 -295
  67. package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +0 -46
  68. package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +0 -51
  69. package/templates/python/.claude/commands/lint.md +0 -111
  70. package/templates/python/.claude/commands/test.md +0 -73
  71. package/templates/python/.claude/settings.json +0 -153
  72. package/templates/python/.mcp.json +0 -78
  73. package/templates/python/CLAUDE.md +0 -276
  74. package/templates/python/examples/django-app/.claude/commands/admin.md +0 -264
  75. package/templates/python/examples/django-app/.claude/commands/django-model.md +0 -124
  76. package/templates/python/examples/django-app/.claude/commands/views.md +0 -222
  77. package/templates/python/examples/django-app/CLAUDE.md +0 -313
  78. package/templates/python/examples/django-app/agents/django-api-security.md +0 -642
  79. package/templates/python/examples/django-app/agents/django-database-optimization.md +0 -752
  80. package/templates/python/examples/fastapi-app/.claude/commands/api-endpoints.md +0 -513
  81. package/templates/python/examples/fastapi-app/.claude/commands/auth.md +0 -775
  82. package/templates/python/examples/fastapi-app/.claude/commands/database.md +0 -657
  83. package/templates/python/examples/fastapi-app/.claude/commands/deployment.md +0 -160
  84. package/templates/python/examples/fastapi-app/.claude/commands/testing.md +0 -927
  85. package/templates/python/examples/fastapi-app/CLAUDE.md +0 -229
  86. package/templates/python/examples/flask-app/.claude/commands/app-factory.md +0 -384
  87. package/templates/python/examples/flask-app/.claude/commands/blueprint.md +0 -243
  88. package/templates/python/examples/flask-app/.claude/commands/database.md +0 -410
  89. package/templates/python/examples/flask-app/.claude/commands/deployment.md +0 -620
  90. package/templates/python/examples/flask-app/.claude/commands/flask-route.md +0 -217
  91. package/templates/python/examples/flask-app/.claude/commands/testing.md +0 -559
  92. package/templates/python/examples/flask-app/CLAUDE.md +0 -391
  93. package/templates/ruby/.claude/commands/model.md +0 -360
  94. package/templates/ruby/.claude/commands/test.md +0 -480
  95. package/templates/ruby/.claude/settings.json +0 -146
  96. package/templates/ruby/.mcp.json +0 -83
  97. package/templates/ruby/CLAUDE.md +0 -284
  98. package/templates/ruby/examples/rails-app/.claude/commands/authentication.md +0 -490
  99. package/templates/ruby/examples/rails-app/CLAUDE.md +0 -376
  100. package/templates/rust/.mcp.json +0 -78
  101. package/templates/rust/README.md +0 -26
@@ -1,480 +0,0 @@
1
- # Ruby Test Generator
2
-
3
- Create comprehensive test files with RSpec or Minitest following Ruby testing best practices.
4
-
5
- ## Purpose
6
-
7
- This command helps you quickly create test files with proper structure, examples, and testing patterns for Ruby applications.
8
-
9
- ## Usage
10
-
11
- ```
12
- /test
13
- ```
14
-
15
- ## What this command does
16
-
17
- 1. **Creates test files** with proper structure for RSpec or Minitest
18
- 2. **Includes test examples** for common scenarios
19
- 3. **Sets up test helpers** and support files
20
- 4. **Follows testing conventions** and best practices
21
- 5. **Generates factory/fixture data** when needed
22
-
23
- ## RSpec Example Output
24
-
25
- ```ruby
26
- # spec/models/user_spec.rb
27
- require 'spec_helper'
28
-
29
- RSpec.describe User do
30
- let(:user) { build(:user) }
31
- let(:valid_attributes) do
32
- {
33
- name: 'John Doe',
34
- email: 'john@example.com',
35
- age: 30
36
- }
37
- end
38
-
39
- describe 'validations' do
40
- it { should validate_presence_of(:name) }
41
- it { should validate_presence_of(:email) }
42
- it { should validate_uniqueness_of(:email) }
43
- it { should validate_numericality_of(:age).is_greater_than(0) }
44
-
45
- context 'when email format is invalid' do
46
- let(:user) { build(:user, email: 'invalid-email') }
47
-
48
- it 'is not valid' do
49
- expect(user).not_to be_valid
50
- expect(user.errors[:email]).to include('is invalid')
51
- end
52
- end
53
- end
54
-
55
- describe 'associations' do
56
- it { should have_many(:posts) }
57
- it { should have_many(:comments) }
58
- end
59
-
60
- describe 'callbacks' do
61
- describe 'before_save' do
62
- it 'normalizes email' do
63
- user = create(:user, email: 'JOHN@EXAMPLE.COM')
64
- expect(user.email).to eq('john@example.com')
65
- end
66
- end
67
- end
68
-
69
- describe 'instance methods' do
70
- describe '#full_name' do
71
- let(:user) { build(:user, first_name: 'John', last_name: 'Doe') }
72
-
73
- it 'returns the full name' do
74
- expect(user.full_name).to eq('John Doe')
75
- end
76
-
77
- context 'when last_name is missing' do
78
- let(:user) { build(:user, first_name: 'John', last_name: nil) }
79
-
80
- it 'returns only first_name' do
81
- expect(user.full_name).to eq('John')
82
- end
83
- end
84
- end
85
-
86
- describe '#active?' do
87
- context 'when user is active' do
88
- let(:user) { build(:user, status: 'active') }
89
-
90
- it 'returns true' do
91
- expect(user.active?).to be true
92
- end
93
- end
94
-
95
- context 'when user is inactive' do
96
- let(:user) { build(:user, status: 'inactive') }
97
-
98
- it 'returns false' do
99
- expect(user.active?).to be false
100
- end
101
- end
102
- end
103
- end
104
-
105
- describe 'class methods' do
106
- describe '.active' do
107
- let!(:active_user) { create(:user, status: 'active') }
108
- let!(:inactive_user) { create(:user, status: 'inactive') }
109
-
110
- it 'returns only active users' do
111
- expect(User.active).to include(active_user)
112
- expect(User.active).not_to include(inactive_user)
113
- end
114
- end
115
-
116
- describe '.find_by_email' do
117
- let!(:user) { create(:user, email: 'test@example.com') }
118
-
119
- it 'finds user by email' do
120
- found_user = User.find_by_email('test@example.com')
121
- expect(found_user).to eq(user)
122
- end
123
-
124
- it 'returns nil when user not found' do
125
- found_user = User.find_by_email('nonexistent@example.com')
126
- expect(found_user).to be_nil
127
- end
128
- end
129
- end
130
-
131
- describe 'scopes' do
132
- describe '.recent' do
133
- let!(:old_user) { create(:user, created_at: 1.year.ago) }
134
- let!(:recent_user) { create(:user, created_at: 1.day.ago) }
135
-
136
- it 'returns users created in the last 30 days' do
137
- expect(User.recent).to include(recent_user)
138
- expect(User.recent).not_to include(old_user)
139
- end
140
- end
141
- end
142
- end
143
- ```
144
-
145
- ## Minitest Example Output
146
-
147
- ```ruby
148
- # test/models/user_test.rb
149
- require 'test_helper'
150
-
151
- class UserTest < ActiveSupport::TestCase
152
- def setup
153
- @user = users(:john)
154
- @valid_attributes = {
155
- name: 'Jane Doe',
156
- email: 'jane@example.com',
157
- age: 25
158
- }
159
- end
160
-
161
- # Validation tests
162
- test 'should not save user without name' do
163
- user = User.new(@valid_attributes.except(:name))
164
- assert_not user.save
165
- assert_includes user.errors[:name], "can't be blank"
166
- end
167
-
168
- test 'should not save user without email' do
169
- user = User.new(@valid_attributes.except(:email))
170
- assert_not user.save
171
- assert_includes user.errors[:email], "can't be blank"
172
- end
173
-
174
- test 'should not save user with invalid email' do
175
- user = User.new(@valid_attributes.merge(email: 'invalid-email'))
176
- assert_not user.save
177
- assert_includes user.errors[:email], 'is invalid'
178
- end
179
-
180
- test 'should not save user with duplicate email' do
181
- user1 = User.create!(@valid_attributes)
182
- user2 = User.new(@valid_attributes)
183
- assert_not user2.save
184
- assert_includes user2.errors[:email], 'has already been taken'
185
- end
186
-
187
- test 'should save user with valid attributes' do
188
- user = User.new(@valid_attributes)
189
- assert user.save
190
- end
191
-
192
- # Association tests
193
- test 'should have many posts' do
194
- assert_respond_to @user, :posts
195
- assert_kind_of ActiveRecord::Associations::CollectionProxy, @user.posts
196
- end
197
-
198
- test 'should have many comments' do
199
- assert_respond_to @user, :comments
200
- end
201
-
202
- # Instance method tests
203
- test 'full_name should return first and last name' do
204
- @user.first_name = 'John'
205
- @user.last_name = 'Doe'
206
- assert_equal 'John Doe', @user.full_name
207
- end
208
-
209
- test 'full_name should return first name only when last name is missing' do
210
- @user.first_name = 'John'
211
- @user.last_name = nil
212
- assert_equal 'John', @user.full_name
213
- end
214
-
215
- test 'active? should return true for active users' do
216
- @user.status = 'active'
217
- assert @user.active?
218
- end
219
-
220
- test 'active? should return false for inactive users' do
221
- @user.status = 'inactive'
222
- assert_not @user.active?
223
- end
224
-
225
- # Class method tests
226
- test 'active scope should return only active users' do
227
- active_user = User.create!(@valid_attributes.merge(status: 'active'))
228
- inactive_user = User.create!(@valid_attributes.merge(
229
- email: 'inactive@example.com',
230
- status: 'inactive'
231
- ))
232
-
233
- active_users = User.active
234
- assert_includes active_users, active_user
235
- assert_not_includes active_users, inactive_user
236
- end
237
-
238
- test 'find_by_email should find user by email' do
239
- user = User.create!(@valid_attributes)
240
- found_user = User.find_by_email(@valid_attributes[:email])
241
- assert_equal user, found_user
242
- end
243
-
244
- test 'find_by_email should return nil when user not found' do
245
- found_user = User.find_by_email('nonexistent@example.com')
246
- assert_nil found_user
247
- end
248
- end
249
- ```
250
-
251
- ## Controller Test Example
252
-
253
- ```ruby
254
- # spec/controllers/users_controller_spec.rb
255
- require 'rails_helper'
256
-
257
- RSpec.describe UsersController, type: :controller do
258
- let(:user) { create(:user) }
259
- let(:valid_attributes) { attributes_for(:user) }
260
- let(:invalid_attributes) { { name: '', email: 'invalid' } }
261
-
262
- describe 'GET #index' do
263
- it 'returns a success response' do
264
- get :index
265
- expect(response).to be_successful
266
- end
267
-
268
- it 'assigns @users' do
269
- user1 = create(:user)
270
- user2 = create(:user)
271
- get :index
272
- expect(assigns(:users)).to match_array([user1, user2])
273
- end
274
- end
275
-
276
- describe 'GET #show' do
277
- it 'returns a success response' do
278
- get :show, params: { id: user.to_param }
279
- expect(response).to be_successful
280
- end
281
-
282
- it 'assigns the requested user' do
283
- get :show, params: { id: user.to_param }
284
- expect(assigns(:user)).to eq(user)
285
- end
286
- end
287
-
288
- describe 'POST #create' do
289
- context 'with valid parameters' do
290
- it 'creates a new User' do
291
- expect {
292
- post :create, params: { user: valid_attributes }
293
- }.to change(User, :count).by(1)
294
- end
295
-
296
- it 'redirects to the created user' do
297
- post :create, params: { user: valid_attributes }
298
- expect(response).to redirect_to(User.last)
299
- end
300
- end
301
-
302
- context 'with invalid parameters' do
303
- it 'does not create a new User' do
304
- expect {
305
- post :create, params: { user: invalid_attributes }
306
- }.to change(User, :count).by(0)
307
- end
308
-
309
- it 'renders the new template' do
310
- post :create, params: { user: invalid_attributes }
311
- expect(response).to render_template(:new)
312
- end
313
- end
314
- end
315
-
316
- describe 'PUT #update' do
317
- context 'with valid parameters' do
318
- let(:new_attributes) { { name: 'Updated Name' } }
319
-
320
- it 'updates the requested user' do
321
- put :update, params: { id: user.to_param, user: new_attributes }
322
- user.reload
323
- expect(user.name).to eq('Updated Name')
324
- end
325
-
326
- it 'redirects to the user' do
327
- put :update, params: { id: user.to_param, user: new_attributes }
328
- expect(response).to redirect_to(user)
329
- end
330
- end
331
-
332
- context 'with invalid parameters' do
333
- it 'renders the edit template' do
334
- put :update, params: { id: user.to_param, user: invalid_attributes }
335
- expect(response).to render_template(:edit)
336
- end
337
- end
338
- end
339
-
340
- describe 'DELETE #destroy' do
341
- it 'destroys the requested user' do
342
- user # Create user
343
- expect {
344
- delete :destroy, params: { id: user.to_param }
345
- }.to change(User, :count).by(-1)
346
- end
347
-
348
- it 'redirects to the users list' do
349
- delete :destroy, params: { id: user.to_param }
350
- expect(response).to redirect_to(users_url)
351
- end
352
- end
353
- end
354
- ```
355
-
356
- ## Factory Configuration
357
-
358
- ```ruby
359
- # spec/factories/users.rb
360
- FactoryBot.define do
361
- factory :user do
362
- sequence(:name) { |n| "User #{n}" }
363
- sequence(:email) { |n| "user#{n}@example.com" }
364
- age { rand(18..80) }
365
- status { 'active' }
366
-
367
- trait :inactive do
368
- status { 'inactive' }
369
- end
370
-
371
- trait :admin do
372
- admin { true }
373
- end
374
-
375
- trait :with_posts do
376
- after(:create) do |user|
377
- create_list(:post, 3, user: user)
378
- end
379
- end
380
-
381
- factory :admin_user, traits: [:admin]
382
- factory :inactive_user, traits: [:inactive]
383
- end
384
- end
385
- ```
386
-
387
- ## Test Helper Configuration
388
-
389
- ```ruby
390
- # spec/spec_helper.rb
391
- require 'simplecov'
392
- SimpleCov.start 'rails' do
393
- add_filter '/spec/'
394
- add_filter '/config/'
395
- add_filter '/vendor/'
396
-
397
- add_group 'Controllers', 'app/controllers'
398
- add_group 'Models', 'app/models'
399
- add_group 'Services', 'app/services'
400
- add_group 'Libraries', 'lib'
401
- end
402
-
403
- RSpec.configure do |config|
404
- config.expect_with :rspec do |expectations|
405
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
406
- end
407
-
408
- config.mock_with :rspec do |mocks|
409
- mocks.verify_partial_doubles = true
410
- end
411
-
412
- config.shared_context_metadata_behavior = :apply_to_host_groups
413
- config.filter_run_when_matching :focus
414
- config.example_status_persistence_file_path = 'spec/examples.txt'
415
- config.disable_monkey_patching!
416
- config.warnings = true
417
-
418
- if config.files_to_run.one?
419
- config.default_formatter = 'doc'
420
- end
421
-
422
- config.profile_examples = 10
423
- config.order = :random
424
- Kernel.srand config.seed
425
- end
426
- ```
427
-
428
- ## Integration Test Example
429
-
430
- ```ruby
431
- # spec/requests/api/users_spec.rb
432
- require 'rails_helper'
433
-
434
- RSpec.describe 'API::Users', type: :request do
435
- let(:user) { create(:user) }
436
- let(:valid_headers) {
437
- { 'Authorization' => "Bearer #{user.auth_token}" }
438
- }
439
-
440
- describe 'GET /api/users' do
441
- it 'returns users' do
442
- create_list(:user, 3)
443
-
444
- get '/api/users', headers: valid_headers
445
-
446
- expect(response).to have_http_status(:ok)
447
- expect(JSON.parse(response.body)['users'].size).to eq(3)
448
- end
449
- end
450
-
451
- describe 'POST /api/users' do
452
- let(:valid_params) do
453
- {
454
- user: {
455
- name: 'New User',
456
- email: 'new@example.com'
457
- }
458
- }
459
- end
460
-
461
- it 'creates a new user' do
462
- post '/api/users', params: valid_params, headers: valid_headers
463
-
464
- expect(response).to have_http_status(:created)
465
- expect(JSON.parse(response.body)['user']['name']).to eq('New User')
466
- end
467
- end
468
- end
469
- ```
470
-
471
- ## Best Practices Included
472
-
473
- - **Descriptive test names** that explain expected behavior
474
- - **Proper test organization** with contexts and describes
475
- - **Factory usage** for test data generation
476
- - **Mocking and stubbing** for external dependencies
477
- - **Coverage configuration** with SimpleCov
478
- - **Test helpers** and shared examples
479
- - **Request/Integration tests** for API endpoints
480
- - **Feature tests** for user workflows
@@ -1,146 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash",
5
- "Edit",
6
- "MultiEdit",
7
- "Write",
8
- "Bash(ruby:*)",
9
- "Bash(bundle:*)",
10
- "Bash(rails:*)",
11
- "Bash(rake:*)",
12
- "Bash(rspec:*)",
13
- "Bash(rubocop:*)",
14
- "Bash(brakeman:*)",
15
- "Bash(irb:*)",
16
- "Bash(pry:*)",
17
- "Bash(gem:*)",
18
- "Bash(rbenv:*)",
19
- "Bash(rvm:*)",
20
- "Bash(kamal:*)",
21
- "Bash(git:*)"
22
- ],
23
- "deny": [
24
- "Bash(curl:*)",
25
- "Bash(wget:*)",
26
- "Bash(rm -rf:*)"
27
- ],
28
- "defaultMode": "allowEdits"
29
- },
30
- "env": {
31
- "BASH_DEFAULT_TIMEOUT_MS": "60000",
32
- "BASH_MAX_OUTPUT_LENGTH": "20000",
33
- "CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1",
34
- "BUNDLE_PATH": "vendor/bundle",
35
- "BUNDLE_JOBS": "4"
36
- },
37
- "includeCoAuthoredBy": true,
38
- "cleanupPeriodDays": 30,
39
- "hooks": {
40
- "PreToolUse": [
41
- {
42
- "matcher": "Bash",
43
- "hooks": [
44
- {
45
- "type": "command",
46
- "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
47
- }
48
- ]
49
- },
50
- {
51
- "matcher": "Write",
52
- "hooks": [
53
- {
54
- "type": "command",
55
- "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"); CONTENT=$(echo $STDIN_JSON | jq -r '.tool_input.content // \"\"); if [[ \"$FILE\" =~ \\.rb$ ]] && echo \"$CONTENT\" | grep -q 'puts\\|p '; then echo 'Warning: puts/p statements should be replaced with proper logging' >&2; exit 2; fi"
56
- }
57
- ]
58
- },
59
- {
60
- "matcher": "Write",
61
- "hooks": [
62
- {
63
- "type": "command",
64
- "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"'); if [[ \"$FILE\" == \"Gemfile\" ]] || [[ \"$FILE\" == \"Gemfile.lock\" ]] || [[ \"$FILE\" =~ gemspec$ ]]; then echo 'Checking for vulnerable gems...'; if command -v bundle >/dev/null 2>&1 && bundle show bundler-audit >/dev/null 2>&1; then bundle audit; elif command -v bundle >/dev/null 2>&1; then echo 'Run: bundle add bundler-audit --group development to enable security audits'; else echo 'Bundler not found for security audit'; fi; fi",
65
- "timeout": 60
66
- }
67
- ]
68
- }
69
- ],
70
- "PostToolUse": [
71
- {
72
- "matcher": "Write|Edit|MultiEdit",
73
- "hooks": [
74
- {
75
- "type": "command",
76
- "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"'); if [[ \"$FILE\" =~ \\.rb$ ]]; then if command -v rubocop >/dev/null 2>&1; then rubocop -A \"$FILE\" 2>/dev/null || echo 'RuboCop auto-correction applied'; elif command -v bundle >/dev/null 2>&1 && bundle show rubocop >/dev/null 2>&1; then bundle exec rubocop -A \"$FILE\" 2>/dev/null || echo 'RuboCop auto-correction applied'; else echo 'RuboCop not available for auto-correction'; fi; fi",
77
- "timeout": 30
78
- }
79
- ]
80
- },
81
- {
82
- "matcher": "Write|Edit|MultiEdit",
83
- "hooks": [
84
- {
85
- "type": "command",
86
- "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"'); if [[ \"$FILE\" =~ \\.rb$ ]]; then RESULT=$(if command -v rubocop >/dev/null 2>&1; then rubocop \"$FILE\" 2>&1; elif command -v bundle >/dev/null 2>&1 && bundle show rubocop >/dev/null 2>&1; then bundle exec rubocop \"$FILE\" 2>&1; fi); if [ $? -ne 0 ] && [[ -n \"$RESULT\" ]]; then echo \"RuboCop linting issues found: $RESULT\" >&2; exit 2; fi; fi",
87
- "timeout": 30
88
- }
89
- ]
90
- },
91
- {
92
- "matcher": "Write|Edit|MultiEdit",
93
- "hooks": [
94
- {
95
- "type": "command",
96
- "command": "FILE=$(echo $STDIN_JSON | jq -r '.tool_input.file_path // \"\"'); if [[ \"$FILE\" =~ \\.rb$ && \"$FILE\" != *\"spec/\"* && \"$FILE\" != *\"_spec.rb\" && \"$FILE\" != *\"test/\"* && \"$FILE\" != *\"_test.rb\" ]]; then DIR=$(dirname \"$FILE\"); BASENAME=$(basename \"$FILE\" .rb); for TEST_FILE in \"spec/${BASENAME}_spec.rb\" \"test/${BASENAME}_test.rb\" \"spec/models/${BASENAME}_spec.rb\" \"spec/controllers/${BASENAME}_spec.rb\" \"spec/services/${BASENAME}_spec.rb\"; do if [ -f \"$TEST_FILE\" ]; then echo \"Running tests for $TEST_FILE...\"; if command -v rspec >/dev/null 2>&1; then rspec \"$TEST_FILE\"; elif command -v bundle >/dev/null 2>&1 && bundle show rspec >/dev/null 2>&1; then bundle exec rspec \"$TEST_FILE\"; elif command -v ruby >/dev/null 2>&1; then ruby -Itest \"$TEST_FILE\" 2>/dev/null || echo 'Test runner not available'; fi; break; fi; done; fi",
97
- "timeout": 60
98
- }
99
- ]
100
- }
101
- ],
102
- "Notification": [
103
- {
104
- "matcher": "",
105
- "hooks": [
106
- {
107
- "type": "command",
108
- "command": "echo \"Claude Code notification: $(date)\" >> ~/.claude/notifications.log"
109
- }
110
- ]
111
- }
112
- ],
113
- "Stop": [
114
- {
115
- "matcher": "",
116
- "hooks": [
117
- {
118
- "type": "command",
119
- "command": "if [[ -f Gemfile || -f Rakefile ]] && [[ $(git status --porcelain | grep '\\.rb$') ]]; then echo 'Running RuboCop on changed Ruby files...'; if command -v rubocop >/dev/null 2>&1; then rubocop $(git diff --name-only --diff-filter=ACMR | grep '\\.rb$'); elif command -v bundle >/dev/null 2>&1 && bundle show rubocop >/dev/null 2>&1; then bundle exec rubocop $(git diff --name-only --diff-filter=ACMR | grep '\\.rb$'); else echo 'RuboCop not found for linting'; fi; fi",
120
- "timeout": 60
121
- }
122
- ]
123
- },
124
- {
125
- "matcher": "",
126
- "hooks": [
127
- {
128
- "type": "command",
129
- "command": "if [[ -f Gemfile || -f Rakefile ]] && [[ $(git status --porcelain | grep '\\.rb$') ]]; then echo 'Running security scan with Brakeman...'; if command -v brakeman >/dev/null 2>&1; then brakeman --quiet --no-pager || echo 'Brakeman scan completed with findings'; elif command -v bundle >/dev/null 2>&1 && bundle show brakeman >/dev/null 2>&1; then bundle exec brakeman --quiet --no-pager || echo 'Brakeman scan completed with findings'; else echo 'Brakeman not found for security scanning'; fi; fi",
130
- "timeout": 60
131
- }
132
- ]
133
- },
134
- {
135
- "matcher": "",
136
- "hooks": [
137
- {
138
- "type": "command",
139
- "command": "if [[ -f Gemfile ]]; then echo 'Checking for gem vulnerabilities...'; if command -v bundle >/dev/null 2>&1 && bundle show bundler-audit >/dev/null 2>&1; then bundle audit || echo 'Security audit completed with findings'; else echo 'bundler-audit not found. Run: bundle add bundler-audit --group development'; fi; fi",
140
- "timeout": 30
141
- }
142
- ]
143
- }
144
- ]
145
- }
146
- }