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 +14 -0
- package/package.json +1 -1
- package/src/audio.js +14 -11
- package/src/installer.js +109 -12
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
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
|
-
|
|
54
|
-
const psScript =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
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 (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
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 };
|