claude-notification-plugin 1.0.88 → 1.0.92
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 +13 -13
- package/README.md +11 -10
- package/bin/cli.js +37 -0
- package/bin/install.js +14 -26
- package/bin/listener-cli.js +2 -2
- package/bin/uninstall.js +39 -11
- package/listener/LISTENER-DETAILED.md +7 -7
- package/package.json +57 -60
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claude-notification-plugin",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "Viacheslav Makarov",
|
|
7
|
-
"email": "npmjs@bazilio.ru"
|
|
8
|
-
},
|
|
9
|
-
"homepage": "https://github.com/Bazilio-san/claude-notification-plugin#readme",
|
|
10
|
-
"repository": "https://github.com/Bazilio-san/claude-notification-plugin",
|
|
11
|
-
"license": "MIT",
|
|
12
|
-
"keywords": ["notification", "telegram", "windows", "sound", "voice", "hooks"]
|
|
13
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-notification-plugin",
|
|
3
|
+
"version": "1.0.92",
|
|
4
|
+
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Viacheslav Makarov",
|
|
7
|
+
"email": "npmjs@bazilio.ru"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/Bazilio-san/claude-notification-plugin#readme",
|
|
10
|
+
"repository": "https://github.com/Bazilio-san/claude-notification-plugin",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": ["notification", "telegram", "windows", "sound", "voice", "hooks"]
|
|
13
|
+
}
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ npm install -g claude-notification-plugin
|
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
The installer prompts for Telegram bot credentials and sets everything up.
|
|
28
|
-
Re-run `claude-notify
|
|
28
|
+
Re-run `claude-notify install` anytime to reconfigure.
|
|
29
29
|
|
|
30
30
|
## Uninstall
|
|
31
31
|
|
|
@@ -186,7 +186,7 @@ The `"default"` alias receives messages without a `@project` prefix.
|
|
|
186
186
|
### 2. Start the listener
|
|
187
187
|
|
|
188
188
|
```bash
|
|
189
|
-
claude-notify
|
|
189
|
+
claude-notify listener start
|
|
190
190
|
```
|
|
191
191
|
|
|
192
192
|
### 3. Send tasks from Telegram
|
|
@@ -209,10 +209,10 @@ The bot replies with status and results:
|
|
|
209
209
|
### 4. Manage the daemon
|
|
210
210
|
|
|
211
211
|
```bash
|
|
212
|
-
claude-notify
|
|
213
|
-
claude-notify
|
|
214
|
-
claude-notify
|
|
215
|
-
claude-notify
|
|
212
|
+
claude-notify listener status # Check if running
|
|
213
|
+
claude-notify listener stop # Stop
|
|
214
|
+
claude-notify listener restart # Restart
|
|
215
|
+
claude-notify listener logs # View last 50 log lines
|
|
216
216
|
```
|
|
217
217
|
|
|
218
218
|
### 5. Bot commands
|
|
@@ -266,10 +266,11 @@ Worktrees are auto-created when you use `@project/branch` syntax (controlled by
|
|
|
266
266
|
|
|
267
267
|
## CLI Commands
|
|
268
268
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
269
|
+
```
|
|
270
|
+
claude-notify install Reinstall plugin registration, Telegram config, hooks
|
|
271
|
+
claude-notify listener <action> Manage the Telegram Listener daemon
|
|
272
|
+
Actions: start, stop, status, logs, restart
|
|
273
|
+
```
|
|
273
274
|
|
|
274
275
|
## License
|
|
275
276
|
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
const command = process.argv[2];
|
|
9
|
+
|
|
10
|
+
switch (command) {
|
|
11
|
+
case 'install':
|
|
12
|
+
await import(path.join(__dirname, 'install.js'));
|
|
13
|
+
break;
|
|
14
|
+
case 'uninstall':
|
|
15
|
+
await import(path.join(__dirname, 'uninstall.js'));
|
|
16
|
+
break;
|
|
17
|
+
case 'listener': {
|
|
18
|
+
// Shift argv so listener-cli.js sees subcommand as argv[2]
|
|
19
|
+
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
20
|
+
await import(path.join(__dirname, 'listener-cli.js'));
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
default:
|
|
24
|
+
// Hook mode: Claude Code pipes JSON to stdin with no args
|
|
25
|
+
if (!process.stdin.isTTY) {
|
|
26
|
+
await import(path.join(__dirname, '..', 'notifier', 'notifier.js'));
|
|
27
|
+
} else {
|
|
28
|
+
console.log('Usage: claude-notify <command> [options]');
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log('Commands:');
|
|
31
|
+
console.log(' install Setup plugin registration, Telegram config, hooks');
|
|
32
|
+
console.log(' uninstall Remove plugin, hooks, config, CLI wrappers');
|
|
33
|
+
console.log(' listener <action> Manage the Telegram Listener daemon');
|
|
34
|
+
console.log(' Actions: start, stop, status, logs, restart');
|
|
35
|
+
process.exit(command ? 1 : 0);
|
|
36
|
+
}
|
|
37
|
+
}
|
package/bin/install.js
CHANGED
|
@@ -20,17 +20,14 @@ const knownMarketplacesPath = path.join(pluginsDir, 'known_marketplaces.json');
|
|
|
20
20
|
const marketplacesDir = path.join(pluginsDir, 'marketplaces');
|
|
21
21
|
const RESOLVER_PATH = path.join(claudeDir, 'claude-notify-resolve.js');
|
|
22
22
|
|
|
23
|
-
const HOOK_COMMAND = 'claude-
|
|
23
|
+
const HOOK_COMMAND = 'claude-notify';
|
|
24
24
|
const MARKETPLACE_KEY = 'bazilio-plugins';
|
|
25
25
|
const PLUGIN_KEY = 'claude-notification-plugin@bazilio-plugins';
|
|
26
26
|
const MARKETPLACE_REPO = 'https://github.com/Bazilio-san/claude-plugins.git';
|
|
27
27
|
const MARKETPLACE_GITHUB = 'Bazilio-san/claude-plugins';
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
'claude-notify-install': 'bin/install.js',
|
|
32
|
-
'claude-notify-uninstall': 'bin/uninstall.js',
|
|
33
|
-
};
|
|
29
|
+
const CLI_BIN_NAME = 'claude-notify';
|
|
30
|
+
const CLI_BIN_TARGET = 'bin/cli.js';
|
|
34
31
|
|
|
35
32
|
// ──────────────────────────────────────
|
|
36
33
|
// Plugin registration
|
|
@@ -217,28 +214,19 @@ function registerCli () {
|
|
|
217
214
|
|
|
218
215
|
const isWindows = process.platform === 'win32';
|
|
219
216
|
const resolverNative = RESOLVER_PATH.replace(/\//g, path.sep);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
for (const [name, relPath] of Object.entries(CLI_BINS)) {
|
|
223
|
-
if (isWindows) {
|
|
224
|
-
const cmdFile = path.join(binDir, `${name}.cmd`);
|
|
225
|
-
const content = `@echo off\r\nnode "${resolverNative}" ${relPath} %*\r\n`;
|
|
226
|
-
fs.writeFileSync(cmdFile, content);
|
|
227
|
-
created.push(cmdFile);
|
|
228
|
-
} else {
|
|
229
|
-
const shFile = path.join(binDir, name);
|
|
230
|
-
const content = `#!/bin/sh\nexec node "${RESOLVER_PATH}" "${relPath}" "$@"\n`;
|
|
231
|
-
fs.writeFileSync(shFile, content, { mode: 0o755 });
|
|
232
|
-
created.push(shFile);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
217
|
+
let wrapperPath;
|
|
235
218
|
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
219
|
+
if (isWindows) {
|
|
220
|
+
wrapperPath = path.join(binDir, `${CLI_BIN_NAME}.cmd`);
|
|
221
|
+
const content = `@echo off\r\nnode "${resolverNative}" ${CLI_BIN_TARGET} %*\r\n`;
|
|
222
|
+
fs.writeFileSync(wrapperPath, content);
|
|
223
|
+
} else {
|
|
224
|
+
wrapperPath = path.join(binDir, CLI_BIN_NAME);
|
|
225
|
+
const content = `#!/bin/sh\nexec node "${RESOLVER_PATH}" "${CLI_BIN_TARGET}" "$@"\n`;
|
|
226
|
+
fs.writeFileSync(wrapperPath, content, { mode: 0o755 });
|
|
241
227
|
}
|
|
228
|
+
|
|
229
|
+
console.log(` CLI wrapper registered: ${wrapperPath}`);
|
|
242
230
|
}
|
|
243
231
|
|
|
244
232
|
// ──────────────────────────────────────
|
package/bin/listener-cli.js
CHANGED
|
@@ -44,7 +44,7 @@ switch (command) {
|
|
|
44
44
|
setTimeout(() => startDaemon(), 1000);
|
|
45
45
|
break;
|
|
46
46
|
default:
|
|
47
|
-
console.log('Usage: claude-notify
|
|
47
|
+
console.log('Usage: claude-notify listener <start|stop|status|logs|restart>');
|
|
48
48
|
console.log('');
|
|
49
49
|
console.log('Commands:');
|
|
50
50
|
console.log(' start Start the listener daemon');
|
|
@@ -75,7 +75,7 @@ function startDaemon () {
|
|
|
75
75
|
// Validate config
|
|
76
76
|
if (!fs.existsSync(CONFIG_FILE)) {
|
|
77
77
|
console.error(`Config not found: ${CONFIG_FILE}`);
|
|
78
|
-
console.error('Run claude-notify
|
|
78
|
+
console.error('Run claude-notify install first, or create the config manually.');
|
|
79
79
|
process.exit(1);
|
|
80
80
|
}
|
|
81
81
|
|
package/bin/uninstall.js
CHANGED
|
@@ -11,7 +11,7 @@ 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
13
|
|
|
14
|
-
const HOOK_COMMAND = 'claude-
|
|
14
|
+
const HOOK_COMMAND = 'claude-notify';
|
|
15
15
|
|
|
16
16
|
// Remove hooks from settings.json
|
|
17
17
|
if (fs.existsSync(settingsPath)) {
|
|
@@ -49,26 +49,54 @@ for (const file of [configPath, statePath, resolverPath]) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// Remove CLI wrapper scripts
|
|
52
|
-
|
|
52
|
+
// Current name + legacy names from previous versions
|
|
53
|
+
const WRAPPER_NAMES = ['claude-notify', 'claude-notify-listener', 'claude-notify-install', 'claude-notify-uninstall'];
|
|
53
54
|
let cliBinsRemoved = false;
|
|
55
|
+
const ext = process.platform === 'win32' ? '.cmd' : '';
|
|
56
|
+
|
|
57
|
+
// Collect directories to check for wrapper scripts
|
|
58
|
+
const wrapperDirs = new Set();
|
|
59
|
+
|
|
60
|
+
// Directory next to claude binary
|
|
54
61
|
try {
|
|
55
62
|
const cmd = process.platform === 'win32' ? 'where claude' : 'which claude';
|
|
56
63
|
const claudeBin = execSync(cmd, { encoding: 'utf-8', windowsHide: true }).trim().split('\n')[0].trim();
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
wrapperDirs.add(path.dirname(claudeBin));
|
|
65
|
+
} catch {
|
|
66
|
+
// claude not in PATH
|
|
67
|
+
}
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
// ~/.local/bin (common on Linux/macOS, also used on Windows)
|
|
70
|
+
wrapperDirs.add(path.join(home, '.local', 'bin'));
|
|
71
|
+
|
|
72
|
+
for (const dir of wrapperDirs) {
|
|
73
|
+
for (const name of WRAPPER_NAMES) {
|
|
74
|
+
const filePath = path.join(dir, `${name}${ext}`);
|
|
62
75
|
if (fs.existsSync(filePath)) {
|
|
63
76
|
fs.unlinkSync(filePath);
|
|
64
77
|
cliBinsRemoved = true;
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
|
-
} catch {
|
|
68
|
-
// claude not in PATH — nothing to remove
|
|
69
80
|
}
|
|
70
81
|
|
|
71
|
-
// Remove
|
|
82
|
+
// Remove from installed_plugins.json
|
|
83
|
+
const PLUGIN_KEY = 'claude-notification-plugin@bazilio-plugins';
|
|
84
|
+
const installedPluginsPath = path.join(claudeDir, 'plugins', 'installed_plugins.json');
|
|
85
|
+
let pluginEntryRemoved = false;
|
|
86
|
+
if (fs.existsSync(installedPluginsPath)) {
|
|
87
|
+
try {
|
|
88
|
+
const data = JSON.parse(fs.readFileSync(installedPluginsPath, 'utf-8'));
|
|
89
|
+
if (data.plugins?.[PLUGIN_KEY]) {
|
|
90
|
+
delete data.plugins[PLUGIN_KEY];
|
|
91
|
+
fs.writeFileSync(installedPluginsPath, JSON.stringify(data, null, 2));
|
|
92
|
+
pluginEntryRemoved = true;
|
|
93
|
+
}
|
|
94
|
+
} catch {
|
|
95
|
+
// ignore
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Remove plugin cache
|
|
72
100
|
const pluginCacheDir = path.join(claudeDir, 'plugins', 'cache', 'bazilio-plugins', 'claude-notification-plugin');
|
|
73
101
|
let cacheRemoved = false;
|
|
74
102
|
if (fs.existsSync(pluginCacheDir)) {
|
|
@@ -80,8 +108,8 @@ console.log('');
|
|
|
80
108
|
console.log('Claude Notification Plugin uninstalled.');
|
|
81
109
|
console.log('Hooks removed from settings.json');
|
|
82
110
|
console.log('Config files deleted.');
|
|
83
|
-
if (cacheRemoved) {
|
|
84
|
-
console.log('Plugin
|
|
111
|
+
if (pluginEntryRemoved || cacheRemoved) {
|
|
112
|
+
console.log('Plugin registration cleaned.');
|
|
85
113
|
}
|
|
86
114
|
if (cliBinsRemoved) {
|
|
87
115
|
console.log('CLI wrapper scripts removed.');
|
|
@@ -87,7 +87,7 @@ The `offset` parameter in the request ensures each message is processed exactly
|
|
|
87
87
|
|
|
88
88
|
## Detached process: why the listener lives without a terminal
|
|
89
89
|
|
|
90
|
-
When you run `claude-notify
|
|
90
|
+
When you run `claude-notify listener start`, the following happens:
|
|
91
91
|
|
|
92
92
|
```
|
|
93
93
|
Your terminal
|
|
@@ -117,7 +117,7 @@ Your terminal
|
|
|
117
117
|
`child.unref()` — allows `listener-cli.js` to exit without waiting for the child.
|
|
118
118
|
|
|
119
119
|
Result: the listener runs as a background OS process. It is not tied to a terminal or to Claude Code — only to the operating system. It will only stop when:
|
|
120
|
-
- The `claude-notify
|
|
120
|
+
- The `claude-notify listener stop` command is issued (or `/stop` in Telegram)
|
|
121
121
|
- The computer is shut down or restarted
|
|
122
122
|
- It crashes due to an error
|
|
123
123
|
|
|
@@ -856,7 +856,7 @@ exec(`claude -p "${userText}"`)
|
|
|
856
856
|
### Listener won't start
|
|
857
857
|
|
|
858
858
|
```bash
|
|
859
|
-
claude-notify
|
|
859
|
+
claude-notify listener status
|
|
860
860
|
# → Status: not running
|
|
861
861
|
```
|
|
862
862
|
|
|
@@ -865,11 +865,11 @@ Check:
|
|
|
865
865
|
1. Does the config exist? `cat ~/.claude/notifier.config.json`
|
|
866
866
|
2. Are `telegram.token` and `telegram.chatId` present?
|
|
867
867
|
3. Is there a `listener.projects` section?
|
|
868
|
-
4. Logs: `claude-notify
|
|
868
|
+
4. Logs: `claude-notify listener logs`
|
|
869
869
|
|
|
870
870
|
### Bot doesn't respond
|
|
871
871
|
|
|
872
|
-
1. Is the listener running? `claude-notify
|
|
872
|
+
1. Is the listener running? `claude-notify listener status`
|
|
873
873
|
2. Is the chatId correct? Messages from other chats are ignored (check the log: `WARN Ignored message from chat ...`)
|
|
874
874
|
3. Is the bot added to the chat? Write `/help` to the bot — if there's no response, check the token
|
|
875
875
|
|
|
@@ -882,7 +882,7 @@ Check:
|
|
|
882
882
|
Or restart the listener:
|
|
883
883
|
|
|
884
884
|
```bash
|
|
885
|
-
claude-notify
|
|
885
|
+
claude-notify listener restart
|
|
886
886
|
```
|
|
887
887
|
|
|
888
888
|
The watchdog will automatically clear stale tasks on the next startup.
|
|
@@ -925,7 +925,7 @@ Suppose you have two projects: an API server and a web application.
|
|
|
925
925
|
```
|
|
926
926
|
=== 10:00 — Startup ===
|
|
927
927
|
|
|
928
|
-
You (terminal): claude-notify
|
|
928
|
+
You (terminal): claude-notify listener start
|
|
929
929
|
→ Listener started (PID: 12345)
|
|
930
930
|
|
|
931
931
|
=== 10:01 — First task ===
|
package/package.json
CHANGED
|
@@ -1,60 +1,57 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "claude-notification-plugin",
|
|
3
|
-
"productName": "claude-notification-plugin",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=18.0.0"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
".claude-plugin/",
|
|
12
|
-
"bin/",
|
|
13
|
-
"hooks/",
|
|
14
|
-
"listener/",
|
|
15
|
-
"notifier/",
|
|
16
|
-
"README.md",
|
|
17
|
-
"LICENSE"
|
|
18
|
-
],
|
|
19
|
-
"bin": {
|
|
20
|
-
"claude-notify
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
},
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
"eslint-plugin-import": "^2.31.0"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-notification-plugin",
|
|
3
|
+
"productName": "claude-notification-plugin",
|
|
4
|
+
"version": "1.0.92",
|
|
5
|
+
"description": "Claude Code task-completion notifications: Telegram, desktop notifications (Windows/macOS/Linux), sound, and voice",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18.0.0"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
".claude-plugin/",
|
|
12
|
+
"bin/",
|
|
13
|
+
"hooks/",
|
|
14
|
+
"listener/",
|
|
15
|
+
"notifier/",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"bin": {
|
|
20
|
+
"claude-notify": "bin/cli.js"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"preuninstall": "node bin/uninstall.js",
|
|
24
|
+
"postinstall": "node bin/install.js",
|
|
25
|
+
"lint": "eslint .",
|
|
26
|
+
"lint:fix": "eslint --fix ."
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"claude",
|
|
30
|
+
"claude-code",
|
|
31
|
+
"notifications",
|
|
32
|
+
"telegram",
|
|
33
|
+
"hooks",
|
|
34
|
+
"macos",
|
|
35
|
+
"linux",
|
|
36
|
+
"cross-platform"
|
|
37
|
+
],
|
|
38
|
+
"author": {
|
|
39
|
+
"name": "Viacheslav Makarov",
|
|
40
|
+
"email": "npmjs@bazilio.ru"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/Bazilio-san/claude-notification-plugin.git"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/Bazilio-san/claude-notification-plugin#readme",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"node-notifier": "^10.0.1"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"eslint-plugin-import": "^2.31.0"
|
|
56
|
+
}
|
|
57
|
+
}
|