claude-code-notify-lite 1.0.4 → 1.0.6

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.
package/bin/cli.js CHANGED
@@ -31,6 +31,7 @@ Examples:
31
31
  $ ccnotify install Install hooks
32
32
  $ ccnotify test Test notification
33
33
  $ ccnotify status Check status
34
+ $ ccnotify repair Fix conflicting hooks
34
35
  $ ccnotify logs View debug logs
35
36
 
36
37
  Version: ${pkg.version}
@@ -118,6 +119,11 @@ program
118
119
  console.log(` Hook configured: ${status.hasHook ? chalk.green('Yes') : chalk.red('No')}`);
119
120
  console.log(` Config exists: ${status.hasConfig ? chalk.green('Yes') : chalk.red('No')}`);
120
121
 
122
+ if (status.hasConflicting) {
123
+ console.log(chalk.yellow('\n [WARN] Conflicting notification hooks detected'));
124
+ console.log(chalk.yellow(' Run "ccnotify repair" to fix'));
125
+ }
126
+
121
127
  console.log(chalk.gray(`\n Log file: ${logger.getLogPath()}`));
122
128
 
123
129
  if (!status.installed) {
@@ -125,6 +131,14 @@ program
125
131
  }
126
132
  });
127
133
 
134
+ program
135
+ .command('repair')
136
+ .description('Clean up conflicting hooks and reinstall')
137
+ .action(() => {
138
+ const { repair } = require('../src/installer');
139
+ repair();
140
+ });
141
+
128
142
  program
129
143
  .command('config')
130
144
  .description('Configure settings interactively')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-notify-lite",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Task completion notifications for Claude Code - Cross-platform, lightweight, and easy to use",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/audio.js CHANGED
@@ -50,17 +50,20 @@ function playWithAfplay(soundPath, volume) {
50
50
  function playWithPowershell(soundPath) {
51
51
  return new Promise((resolve) => {
52
52
  logger.info('Playing sound with PowerShell', { soundPath });
53
- const escapedPath = soundPath.replace(/\\/g, '\\\\');
54
- const psScript = [
55
- 'Add-Type -AssemblyName PresentationCore',
56
- '$player = New-Object System.Windows.Media.MediaPlayer',
57
- `$player.Open([System.Uri]"${escapedPath}")`,
58
- 'Start-Sleep -Milliseconds 300',
59
- '$player.Play()',
60
- 'Start-Sleep -Seconds 3'
61
- ].join('; ');
62
-
63
- exec(`powershell -NoProfile -ExecutionPolicy Bypass -Command "${psScript}"`,
53
+
54
+ const psScript = `
55
+ Add-Type -AssemblyName PresentationCore
56
+ $player = New-Object System.Windows.Media.MediaPlayer
57
+ $player.Open([System.Uri]'${soundPath.replace(/'/g, "''")}')
58
+ Start-Sleep -Milliseconds 300
59
+ $player.Play()
60
+ Start-Sleep -Seconds 3
61
+ $player.Close()
62
+ `;
63
+
64
+ const base64Command = Buffer.from(psScript, 'utf16le').toString('base64');
65
+
66
+ exec(`powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand ${base64Command}`,
64
67
  { encoding: 'utf8', windowsHide: true },
65
68
  (err) => {
66
69
  if (err) {
package/src/installer.js CHANGED
@@ -151,6 +151,22 @@ function isOurHook(command) {
151
151
  command.includes('notify.js');
152
152
  }
153
153
 
154
+ function isNotificationHook(command) {
155
+ if (!command) return false;
156
+ const patterns = [
157
+ 'claude-code-notify-lite',
158
+ 'ccnotify',
159
+ 'notify.js',
160
+ 'notify.bat',
161
+ 'notify.ps1',
162
+ 'task-complete-notify',
163
+ 'notification',
164
+ 'notifier'
165
+ ];
166
+ const lowerCommand = command.toLowerCase();
167
+ return patterns.some(p => lowerCommand.includes(p.toLowerCase()));
168
+ }
169
+
154
170
  function install(options = {}) {
155
171
  console.log('Installing claude-code-notify-lite...\n');
156
172
  logger.info('Install started', { options });
@@ -195,18 +211,31 @@ function install(options = {}) {
195
211
  settings.hooks.Stop = [stopHook];
196
212
  logger.info('Created new Stop hook');
197
213
  } else {
198
- const existingIndex = settings.hooks.Stop.findIndex(h =>
199
- h.hooks && h.hooks.some(hh => isOurHook(hh.command))
214
+ const conflictingHooks = settings.hooks.Stop.filter(h =>
215
+ h.hooks && h.hooks.some(hh => isNotificationHook(hh.command) && !isOurHook(hh.command))
200
216
  );
201
217
 
202
- if (existingIndex === -1) {
203
- settings.hooks.Stop.push(stopHook);
204
- logger.info('Added Stop hook');
205
- } else {
206
- settings.hooks.Stop[existingIndex] = stopHook;
207
- console.log(' [OK] Updated existing hook');
208
- logger.info('Updated existing Stop hook');
218
+ if (conflictingHooks.length > 0) {
219
+ console.log(' [WARN] Found existing notification hooks:');
220
+ conflictingHooks.forEach(h => {
221
+ h.hooks.forEach(hh => {
222
+ if (isNotificationHook(hh.command)) {
223
+ console.log(` - ${hh.command}`);
224
+ }
225
+ });
226
+ });
227
+ console.log(' [INFO] Replacing with claude-code-notify-lite...');
228
+ logger.info('Found conflicting hooks, replacing them');
209
229
  }
230
+
231
+ settings.hooks.Stop = settings.hooks.Stop.filter(h => {
232
+ if (!h.hooks) return true;
233
+ h.hooks = h.hooks.filter(hh => !isNotificationHook(hh.command));
234
+ return h.hooks.length > 0;
235
+ });
236
+
237
+ settings.hooks.Stop.push(stopHook);
238
+ logger.info('Replaced notification hooks with our hook');
210
239
  }
211
240
 
212
241
  writeClaudeSettings(settings);
@@ -284,16 +313,84 @@ function checkInstallation() {
284
313
  h.hooks && h.hooks.some(hh => isOurHook(hh.command))
285
314
  );
286
315
 
316
+ const hasConflicting = settings.hooks &&
317
+ settings.hooks.Stop &&
318
+ settings.hooks.Stop.some(h =>
319
+ h.hooks && h.hooks.some(hh => isNotificationHook(hh.command) && !isOurHook(hh.command))
320
+ );
321
+
287
322
  const configDir = getConfigDir();
288
323
  const hasConfig = fs.existsSync(path.join(configDir, 'config.json'));
289
324
 
290
- logger.debug('Installation check', { hasHook, hasConfig });
325
+ logger.debug('Installation check', { hasHook, hasConfig, hasConflicting });
291
326
 
292
327
  return {
293
328
  installed: hasHook && hasConfig,
294
329
  hasHook,
295
- hasConfig
330
+ hasConfig,
331
+ hasConflicting
296
332
  };
297
333
  }
298
334
 
299
- module.exports = { install, uninstall, checkInstallation };
335
+ function repair() {
336
+ console.log('Repairing claude-code-notify-lite...\n');
337
+ logger.info('Repair started');
338
+
339
+ try {
340
+ const settings = readClaudeSettings();
341
+
342
+ if (!settings.hooks || !settings.hooks.Stop) {
343
+ console.log(' [INFO] No Stop hooks found');
344
+ console.log(' [INFO] Running fresh install...\n');
345
+ return install();
346
+ }
347
+
348
+ let removedCount = 0;
349
+ const removedHooks = [];
350
+
351
+ settings.hooks.Stop.forEach(h => {
352
+ if (h.hooks) {
353
+ h.hooks.forEach(hh => {
354
+ if (isNotificationHook(hh.command)) {
355
+ removedHooks.push(hh.command);
356
+ removedCount++;
357
+ }
358
+ });
359
+ }
360
+ });
361
+
362
+ if (removedCount > 0) {
363
+ console.log(' [INFO] Found notification hooks to clean:');
364
+ removedHooks.forEach(cmd => console.log(` - ${cmd}`));
365
+
366
+ settings.hooks.Stop = settings.hooks.Stop.filter(h => {
367
+ if (!h.hooks) return true;
368
+ h.hooks = h.hooks.filter(hh => !isNotificationHook(hh.command));
369
+ return h.hooks.length > 0;
370
+ });
371
+
372
+ if (settings.hooks.Stop.length === 0) {
373
+ delete settings.hooks.Stop;
374
+ }
375
+
376
+ if (Object.keys(settings.hooks).length === 0) {
377
+ delete settings.hooks;
378
+ }
379
+
380
+ writeClaudeSettings(settings);
381
+ console.log(` [OK] Removed ${removedCount} notification hook(s)`);
382
+ logger.info('Cleaned notification hooks', { removedCount, removedHooks });
383
+ } else {
384
+ console.log(' [INFO] No conflicting hooks found');
385
+ }
386
+
387
+ console.log(' [INFO] Reinstalling...\n');
388
+ return install();
389
+ } catch (err) {
390
+ logger.error('Repair failed', err);
391
+ console.error(` [ERROR] ${err.message}`);
392
+ return { success: false, error: err.message };
393
+ }
394
+ }
395
+
396
+ module.exports = { install, uninstall, checkInstallation, repair };