claude-code-notify-lite 1.0.0 → 1.0.1
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/README.md +25 -0
- package/bin/notify.js +1 -1
- package/package.json +1 -1
- package/src/audio.js +4 -6
- package/src/index.js +7 -1
- package/src/installer.js +2 -6
- package/src/notifier.js +51 -9
package/README.md
CHANGED
|
@@ -24,6 +24,18 @@ npm install -g claude-code-notify-lite
|
|
|
24
24
|
ccnotify install
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
If `ccnotify` command is not found, use npx instead:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx claude-code-notify-lite install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or add npm global bin to your PATH:
|
|
34
|
+
|
|
35
|
+
**Windows:** Add `%APPDATA%\npm` to your PATH environment variable.
|
|
36
|
+
|
|
37
|
+
**macOS/Linux:** Add `$(npm root -g)/../bin` to your PATH.
|
|
38
|
+
|
|
27
39
|
### Using install script
|
|
28
40
|
|
|
29
41
|
**macOS / Linux:**
|
|
@@ -108,6 +120,19 @@ Claude Code Notify Lite integrates with Claude Code's hook system:
|
|
|
108
120
|
|
|
109
121
|
## Troubleshooting
|
|
110
122
|
|
|
123
|
+
### Command 'ccnotify' not found
|
|
124
|
+
|
|
125
|
+
After npm global install, if `ccnotify` is not recognized:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Use npx instead
|
|
129
|
+
npx claude-code-notify-lite install
|
|
130
|
+
|
|
131
|
+
# Or find npm global bin location
|
|
132
|
+
npm root -g
|
|
133
|
+
# Then add the parent bin directory to PATH
|
|
134
|
+
```
|
|
135
|
+
|
|
111
136
|
### Notification not showing
|
|
112
137
|
|
|
113
138
|
**macOS:**
|
package/bin/notify.js
CHANGED
package/package.json
CHANGED
package/src/audio.js
CHANGED
|
@@ -55,12 +55,10 @@ function playWithPowershell(soundPath) {
|
|
|
55
55
|
'Start-Sleep -Seconds 3'
|
|
56
56
|
].join('; ');
|
|
57
57
|
|
|
58
|
-
exec(`powershell -NoProfile -Command "${psScript}"`,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
resolve();
|
|
63
|
-
});
|
|
58
|
+
exec(`powershell -NoProfile -ExecutionPolicy Bypass -Command "${psScript}"`,
|
|
59
|
+
{ encoding: 'utf8', windowsHide: true },
|
|
60
|
+
() => resolve()
|
|
61
|
+
);
|
|
64
62
|
});
|
|
65
63
|
}
|
|
66
64
|
|
package/src/index.js
CHANGED
|
@@ -2,12 +2,18 @@ const { notify } = require('./notifier');
|
|
|
2
2
|
const { playSound } = require('./audio');
|
|
3
3
|
const { loadConfig } = require('./config');
|
|
4
4
|
|
|
5
|
+
function formatTime() {
|
|
6
|
+
const now = new Date();
|
|
7
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
8
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
async function run(options = {}) {
|
|
6
12
|
try {
|
|
7
13
|
const config = loadConfig();
|
|
8
14
|
|
|
9
15
|
const workDir = process.env.CLAUDE_PWD || process.cwd();
|
|
10
|
-
const time =
|
|
16
|
+
const time = formatTime();
|
|
11
17
|
|
|
12
18
|
const title = options.title || config.notification.title || 'Claude Code';
|
|
13
19
|
const message = options.message || 'Task completed';
|
package/src/installer.js
CHANGED
|
@@ -16,13 +16,9 @@ function getHookCommand() {
|
|
|
16
16
|
const normalizedPath = notifyScript.replace(/\\/g, '/');
|
|
17
17
|
return `node "${normalizedPath}"`;
|
|
18
18
|
}
|
|
19
|
-
} catch (e) {
|
|
20
|
-
if (process.env.DEBUG) {
|
|
21
|
-
console.warn('Failed to find global npm path:', e.message);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
19
|
+
} catch (e) {}
|
|
24
20
|
|
|
25
|
-
return '
|
|
21
|
+
return 'node -e "require(\'claude-code-notify-lite\').run()"';
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
function readClaudeSettings() {
|
package/src/notifier.js
CHANGED
|
@@ -2,6 +2,7 @@ const notifier = require('node-notifier');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const os = require('os');
|
|
5
|
+
const { exec } = require('child_process');
|
|
5
6
|
const { loadConfig } = require('./config');
|
|
6
7
|
|
|
7
8
|
function getIconPath() {
|
|
@@ -9,6 +10,50 @@ function getIconPath() {
|
|
|
9
10
|
return fs.existsSync(iconPath) ? iconPath : undefined;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
function notifyWindows(title, message) {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
const escapedTitle = title.replace(/"/g, '\\"');
|
|
16
|
+
const escapedMessage = message.replace(/"/g, '\\"').replace(/\n/g, '`n');
|
|
17
|
+
|
|
18
|
+
const psScript = `
|
|
19
|
+
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
|
|
20
|
+
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
|
|
21
|
+
$template = @"
|
|
22
|
+
<toast>
|
|
23
|
+
<visual>
|
|
24
|
+
<binding template="ToastText02">
|
|
25
|
+
<text id="1">${escapedTitle}</text>
|
|
26
|
+
<text id="2">${escapedMessage}</text>
|
|
27
|
+
</binding>
|
|
28
|
+
</visual>
|
|
29
|
+
</toast>
|
|
30
|
+
"@
|
|
31
|
+
$xml = New-Object Windows.Data.Xml.Dom.XmlDocument
|
|
32
|
+
$xml.LoadXml($template)
|
|
33
|
+
$toast = [Windows.UI.Notifications.ToastNotification]::new($xml)
|
|
34
|
+
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Claude Code").Show($toast)
|
|
35
|
+
`.trim();
|
|
36
|
+
|
|
37
|
+
exec(`powershell -NoProfile -ExecutionPolicy Bypass -Command "${psScript.replace(/"/g, '\\"')}"`,
|
|
38
|
+
{ encoding: 'utf8', windowsHide: true },
|
|
39
|
+
(err) => {
|
|
40
|
+
if (err) {
|
|
41
|
+
notifier.notify({
|
|
42
|
+
title: title,
|
|
43
|
+
message: message,
|
|
44
|
+
sound: false,
|
|
45
|
+
wait: false,
|
|
46
|
+
timeout: 5,
|
|
47
|
+
appID: 'Claude Code'
|
|
48
|
+
}, () => resolve());
|
|
49
|
+
} else {
|
|
50
|
+
resolve();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
12
57
|
function notify(options = {}) {
|
|
13
58
|
const config = loadConfig();
|
|
14
59
|
|
|
@@ -27,9 +72,14 @@ function notify(options = {}) {
|
|
|
27
72
|
message += `\n${options.time}`;
|
|
28
73
|
}
|
|
29
74
|
|
|
30
|
-
const iconPath = getIconPath();
|
|
31
75
|
const platform = os.platform();
|
|
32
76
|
|
|
77
|
+
if (platform === 'win32') {
|
|
78
|
+
return notifyWindows(title, message);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const iconPath = getIconPath();
|
|
82
|
+
|
|
33
83
|
const notificationOptions = {
|
|
34
84
|
title: title,
|
|
35
85
|
message: message,
|
|
@@ -47,23 +97,15 @@ function notify(options = {}) {
|
|
|
47
97
|
notificationOptions.contentImage = iconPath;
|
|
48
98
|
}
|
|
49
99
|
notificationOptions.sound = false;
|
|
50
|
-
} else if (platform === 'win32') {
|
|
51
|
-
notificationOptions.appID = 'Claude Code Notify Lite';
|
|
52
100
|
}
|
|
53
101
|
|
|
54
102
|
return new Promise((resolve) => {
|
|
55
103
|
const timeoutId = setTimeout(() => {
|
|
56
|
-
if (process.env.DEBUG) {
|
|
57
|
-
console.warn('Notification timed out');
|
|
58
|
-
}
|
|
59
104
|
resolve();
|
|
60
105
|
}, 10000);
|
|
61
106
|
|
|
62
107
|
notifier.notify(notificationOptions, (err, response) => {
|
|
63
108
|
clearTimeout(timeoutId);
|
|
64
|
-
if (err && process.env.DEBUG) {
|
|
65
|
-
console.warn('Notification error:', err.message);
|
|
66
|
-
}
|
|
67
109
|
resolve(response);
|
|
68
110
|
});
|
|
69
111
|
});
|