claude-notification-plugin 1.0.99 → 1.0.102
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/.claude-plugin/plugin.json +1 -1
- package/bin/uninstall.js +91 -10
- package/commit-sha +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-notification-plugin",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.102",
|
|
4
4
|
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Viacheslav Makarov",
|
package/bin/uninstall.js
CHANGED
|
@@ -10,20 +10,81 @@ const claudeDir = path.join(home, '.claude');
|
|
|
10
10
|
const configPath = path.join(claudeDir, 'notifier.config.json');
|
|
11
11
|
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
12
12
|
const statePath = path.join(claudeDir, '.notifier_state.json');
|
|
13
|
+
const pidFile = path.join(claudeDir, '.listener.pid');
|
|
13
14
|
|
|
14
15
|
const HOOK_COMMAND = 'claude-notify';
|
|
15
16
|
const PLUGIN_KEY = 'claude-notification-plugin@bazilio-plugins';
|
|
16
17
|
const MARKETPLACE_KEY = 'bazilio-plugins';
|
|
17
18
|
|
|
19
|
+
function isPluginHookCommand (command) {
|
|
20
|
+
if (typeof command !== 'string') {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const normalized = command.trim().toLowerCase();
|
|
25
|
+
if (!normalized) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return normalized === HOOK_COMMAND || normalized.startsWith(`${HOOK_COMMAND} `);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Stop listener daemon if running
|
|
33
|
+
let listenerStopped = false;
|
|
34
|
+
try {
|
|
35
|
+
if (fs.existsSync(pidFile)) {
|
|
36
|
+
const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
37
|
+
if (!isNaN(pid)) {
|
|
38
|
+
try {
|
|
39
|
+
if (process.platform === 'win32') {
|
|
40
|
+
execSync(`taskkill /PID ${pid} /T /F`, { stdio: 'ignore', windowsHide: true });
|
|
41
|
+
} else {
|
|
42
|
+
process.kill(pid, 'SIGTERM');
|
|
43
|
+
let tries = 10;
|
|
44
|
+
const isAlive = (p) => {
|
|
45
|
+
try {
|
|
46
|
+
process.kill(p, 0);
|
|
47
|
+
return true;
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
while (tries-- > 0 && isAlive(pid)) {
|
|
53
|
+
execSync('sleep 0.5', { stdio: 'ignore' });
|
|
54
|
+
}
|
|
55
|
+
if (isAlive(pid)) {
|
|
56
|
+
process.kill(pid, 'SIGKILL');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
listenerStopped = true;
|
|
60
|
+
} catch {
|
|
61
|
+
// process may already be dead
|
|
62
|
+
}
|
|
63
|
+
fs.unlinkSync(pidFile);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
// ignore
|
|
68
|
+
}
|
|
69
|
+
|
|
18
70
|
// Remove hooks from settings.json
|
|
71
|
+
let hooksRemoved = false;
|
|
72
|
+
let hooksRemoveError = '';
|
|
19
73
|
if (fs.existsSync(settingsPath)) {
|
|
20
74
|
try {
|
|
21
75
|
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
76
|
+
let hadPluginHooks = false;
|
|
22
77
|
|
|
23
78
|
if (settings.hooks) {
|
|
24
79
|
for (const event of Object.keys(settings.hooks)) {
|
|
80
|
+
const eventHooks = Array.isArray(settings.hooks[event]) ? settings.hooks[event] : [];
|
|
81
|
+
const hadInEvent = eventHooks.some((matcher) =>
|
|
82
|
+
matcher.hooks?.some((h) => isPluginHookCommand(h.command)),
|
|
83
|
+
);
|
|
84
|
+
hadPluginHooks = hadPluginHooks || hadInEvent;
|
|
85
|
+
|
|
25
86
|
settings.hooks[event] = settings.hooks[event].filter((matcher) =>
|
|
26
|
-
!matcher.hooks?.some((h) => h.command
|
|
87
|
+
!matcher.hooks?.some((h) => isPluginHookCommand(h.command)),
|
|
27
88
|
);
|
|
28
89
|
|
|
29
90
|
if (settings.hooks[event].length === 0) {
|
|
@@ -53,22 +114,35 @@ if (fs.existsSync(settingsPath)) {
|
|
|
53
114
|
}
|
|
54
115
|
|
|
55
116
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
56
|
-
|
|
57
|
-
//
|
|
117
|
+
|
|
118
|
+
// Verify hooks were actually removed
|
|
119
|
+
const verify = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
120
|
+
const remainingPluginHooks = verify.hooks
|
|
121
|
+
? Object.values(verify.hooks).some((matchers) =>
|
|
122
|
+
Array.isArray(matchers) &&
|
|
123
|
+
matchers.some((m) => m.hooks?.some((h) => isPluginHookCommand(h.command))),
|
|
124
|
+
)
|
|
125
|
+
: false;
|
|
126
|
+
hooksRemoved = hadPluginHooks && !remainingPluginHooks;
|
|
127
|
+
if (hadPluginHooks && remainingPluginHooks) {
|
|
128
|
+
hooksRemoveError = 'Hooks still present in settings.json after removal attempt';
|
|
129
|
+
}
|
|
130
|
+
} catch (err) {
|
|
131
|
+
hooksRemoveError = `Failed to update settings.json: ${err.message}`;
|
|
58
132
|
}
|
|
59
133
|
}
|
|
60
134
|
|
|
61
|
-
// Remove config, state, and
|
|
135
|
+
// Remove config, state, resolver, and listener files
|
|
62
136
|
const resolverPath = path.join(claudeDir, 'claude-notify-resolve.js');
|
|
63
|
-
|
|
137
|
+
const listenerLogFile = path.join(claudeDir, '.cc-n-listener.log');
|
|
138
|
+
for (const file of [configPath, statePath, resolverPath, pidFile, listenerLogFile]) {
|
|
64
139
|
if (fs.existsSync(file)) {
|
|
65
140
|
fs.unlinkSync(file);
|
|
66
141
|
}
|
|
67
142
|
}
|
|
68
143
|
|
|
69
|
-
// Remove CLI wrapper
|
|
70
|
-
|
|
71
|
-
const WRAPPER_NAMES = ['claude-notify', 'claude-notify-listener', 'claude-notify-install', 'claude-notify-uninstall'];
|
|
144
|
+
// Remove CLI wrapper script
|
|
145
|
+
const WRAPPER_NAMES = ['claude-notify'];
|
|
72
146
|
let cliBinsRemoved = false;
|
|
73
147
|
const ext = process.platform === 'win32' ? '.cmd' : '';
|
|
74
148
|
|
|
@@ -121,7 +195,14 @@ if (fs.existsSync(pluginCacheDir)) {
|
|
|
121
195
|
cacheRemoved = !fs.existsSync(pluginCacheDir);
|
|
122
196
|
}
|
|
123
197
|
|
|
198
|
+
const hooksStatus = hooksRemoved
|
|
199
|
+
? 'Hooks removed from settings.json'
|
|
200
|
+
: hooksRemoveError
|
|
201
|
+
? `Warning: ${hooksRemoveError}`
|
|
202
|
+
: 'No hooks found in settings.json';
|
|
203
|
+
|
|
124
204
|
const extras = [
|
|
205
|
+
listenerStopped ? 'Listener daemon stopped.' : '',
|
|
125
206
|
pluginEntryRemoved || cacheRemoved ? 'Plugin registration cleaned.' : '',
|
|
126
207
|
cliBinsRemoved ? 'CLI wrapper scripts removed.' : '',
|
|
127
208
|
].filter(Boolean).join('\n');
|
|
@@ -132,13 +213,13 @@ if (cacheStillExists) {
|
|
|
132
213
|
Warning: Could not fully remove plugin cache directory:
|
|
133
214
|
${pluginCacheDir}
|
|
134
215
|
Please remove it manually.
|
|
135
|
-
|
|
216
|
+
${hooksStatus}
|
|
136
217
|
Config files deleted.${extras ? `\n${extras}` : ''}
|
|
137
218
|
`);
|
|
138
219
|
} else {
|
|
139
220
|
console.log(`
|
|
140
221
|
Claude Notification Plugin uninstalled.
|
|
141
|
-
|
|
222
|
+
${hooksStatus}
|
|
142
223
|
Config files deleted.${extras ? `\n${extras}` : ''}
|
|
143
224
|
`);
|
|
144
225
|
}
|
package/commit-sha
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
8cd1016fa338ed33fd68b1c9350ca62df5b00bf4
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-notification-plugin",
|
|
3
3
|
"productName": "claude-notification-plugin",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.102",
|
|
5
5
|
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|