@trendai-crem/claude-skills 0.5.3 → 0.6.0
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/cli.js +99 -8
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -65,10 +65,12 @@ function setupAutoUpdate() {
|
|
|
65
65
|
readFileSync(join(__dir, 'package.json'), 'utf8')
|
|
66
66
|
);
|
|
67
67
|
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const
|
|
68
|
+
const homeDir = homedir();
|
|
69
|
+
const claudeDir = join(homeDir, '.claude');
|
|
70
|
+
const hooksDir = join(claudeDir, 'hooks');
|
|
71
|
+
const cacheDir = join(homeDir, '.cache');
|
|
72
|
+
const hookScript = join(hooksDir, 'auto-update-claude-skills.sh');
|
|
73
|
+
const stampFile = join(cacheDir, 'claude-skills-update.json');
|
|
72
74
|
const settingsPath = join(claudeDir, 'settings.json');
|
|
73
75
|
|
|
74
76
|
// Write the auto-update hook script
|
|
@@ -104,7 +106,45 @@ function setupAutoUpdate() {
|
|
|
104
106
|
writeFileSync(tmpPath, JSON.stringify(settings, null, 2) + '\n');
|
|
105
107
|
renameSync(tmpPath, settingsPath);
|
|
106
108
|
|
|
107
|
-
|
|
109
|
+
if (process.platform === 'darwin') {
|
|
110
|
+
const launchAgentsDir = join(homeDir, 'Library', 'LaunchAgents');
|
|
111
|
+
const launchdPlistPath = join(
|
|
112
|
+
launchAgentsDir,
|
|
113
|
+
'com.trendai.claude-skills-updater.plist'
|
|
114
|
+
);
|
|
115
|
+
const launchdLogPath = join(cacheDir, 'claude-skills-launchd.log');
|
|
116
|
+
const plistTmpPath = join(tmpdir(), `claude-skills-launchd-${process.pid}.plist`);
|
|
117
|
+
|
|
118
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
119
|
+
mkdirSync(launchAgentsDir, { recursive: true });
|
|
120
|
+
|
|
121
|
+
// Unload existing agent before writing new plist — ensures reinstall applies updated config
|
|
122
|
+
try {
|
|
123
|
+
execFileSync('launchctl', ['unload', launchdPlistPath], { stdio: 'pipe' });
|
|
124
|
+
} catch (_) {
|
|
125
|
+
// Not yet loaded — expected on first install
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Bake current PATH into plist so npm/npx are findable in launchd's stripped environment
|
|
129
|
+
const launchdPath = process.env.PATH ?? '/usr/local/bin:/usr/bin:/bin';
|
|
130
|
+
writeFileSync(
|
|
131
|
+
plistTmpPath,
|
|
132
|
+
buildLaunchAgentPlist(hookScript, launchdLogPath, launchdPath)
|
|
133
|
+
);
|
|
134
|
+
renameSync(plistTmpPath, launchdPlistPath);
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
execFileSync('launchctl', ['load', '-w', launchdPlistPath], { stdio: 'pipe' });
|
|
138
|
+
} catch (error) {
|
|
139
|
+
const details = error.stderr?.toString().trim() || error.stdout?.toString().trim();
|
|
140
|
+
console.warn(`\nWARN: launchctl load failed — agent may need manual activation.${details ? ` ${details}` : ''}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const schedule = process.platform === 'darwin'
|
|
145
|
+
? 'every 24h via launchd and at session start'
|
|
146
|
+
: 'daily at session start';
|
|
147
|
+
console.log(`\n✓ Auto-update configured (runs ${schedule})`);
|
|
108
148
|
}
|
|
109
149
|
|
|
110
150
|
function buildHookScript(stampFile, installedVersion) {
|
|
@@ -113,17 +153,26 @@ function buildHookScript(stampFile, installedVersion) {
|
|
|
113
153
|
throw new Error(`Invalid version format in package.json: ${installedVersion}`);
|
|
114
154
|
}
|
|
115
155
|
|
|
156
|
+
const notifyFile = stampFile.replace('.json', '-pending-notification.txt');
|
|
157
|
+
|
|
116
158
|
return `#!/usr/bin/env bash
|
|
117
|
-
# Auto-update @trendai-crem/claude-skills
|
|
159
|
+
# Auto-update @trendai-crem/claude-skills — runs at session start and via launchd (macOS).
|
|
118
160
|
set -euo pipefail
|
|
119
161
|
|
|
120
162
|
STAMP="${stampFile}"
|
|
163
|
+
NOTIFY="${notifyFile}"
|
|
121
164
|
PACKAGE="@trendai-crem/claude-skills"
|
|
122
165
|
MIN_INTERVAL=$((60 * 60 * 24))
|
|
123
166
|
LOG="$(dirname "$STAMP")/claude-skills-update.log"
|
|
124
167
|
|
|
125
168
|
mkdir -p "$(dirname "$STAMP")"
|
|
126
169
|
|
|
170
|
+
# Show pending update notification from previous background update
|
|
171
|
+
if [ -f "$NOTIFY" ]; then
|
|
172
|
+
cat "$NOTIFY"
|
|
173
|
+
rm -f "$NOTIFY"
|
|
174
|
+
fi
|
|
175
|
+
|
|
127
176
|
# Read stamp using sys.argv to avoid shell injection
|
|
128
177
|
LAST_TS=0
|
|
129
178
|
CURRENT_VER="${installedVersion}"
|
|
@@ -147,16 +196,58 @@ LATEST=$(npm view "$PACKAGE" version 2>/dev/null || echo "")
|
|
|
147
196
|
# Validate LATEST is semver before executing
|
|
148
197
|
[[ "$LATEST" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]] || { echo "[$(date -Iseconds)] Invalid version from npm: $LATEST" >> "$LOG"; exit 1; }
|
|
149
198
|
|
|
150
|
-
# Update in background — stamp written only on success
|
|
151
|
-
echo "🔄
|
|
199
|
+
# Update in background — notification and stamp written only on success
|
|
200
|
+
echo "🔄 Updating claude-skills: $CURRENT_VER → $LATEST (background)"
|
|
152
201
|
(
|
|
153
202
|
echo "[$(date -Iseconds)] Updating $CURRENT_VER → $LATEST" >> "$LOG"
|
|
154
203
|
if npx --yes "\${PACKAGE}@\${LATEST}" >> "$LOG" 2>&1; then
|
|
155
204
|
python3 -c "import json,sys; json.dump({'ts': int(sys.argv[1]), 'version': sys.argv[2]}, open(sys.argv[3],'w'))" "$NOW" "\${LATEST}" "$STAMP"
|
|
156
205
|
echo "[$(date -Iseconds)] Update successful" >> "$LOG"
|
|
206
|
+
# Write pending notification for next session start
|
|
207
|
+
echo "✓ claude-skills updated: $CURRENT_VER → \${LATEST}" > "$NOTIFY"
|
|
208
|
+
# macOS system notification (via launchd or background)
|
|
209
|
+
osascript -e "display notification \"Updated to \${LATEST}\" with title \"claude-skills\"" 2>/dev/null || true
|
|
157
210
|
else
|
|
158
211
|
echo "[$(date -Iseconds)] Update failed — will retry next session" >> "$LOG"
|
|
159
212
|
fi
|
|
160
213
|
) &
|
|
161
214
|
`;
|
|
162
215
|
}
|
|
216
|
+
|
|
217
|
+
function escapeXml(value) {
|
|
218
|
+
return value
|
|
219
|
+
.replaceAll('&', '&')
|
|
220
|
+
.replaceAll('<', '<')
|
|
221
|
+
.replaceAll('>', '>')
|
|
222
|
+
.replaceAll('"', '"')
|
|
223
|
+
.replaceAll("'", ''');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function buildLaunchAgentPlist(hookScript, logPath, envPath) {
|
|
227
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
228
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
229
|
+
<plist version="1.0">
|
|
230
|
+
<dict>
|
|
231
|
+
<key>Label</key>
|
|
232
|
+
<string>com.trendai.claude-skills-updater</string>
|
|
233
|
+
<key>ProgramArguments</key>
|
|
234
|
+
<array>
|
|
235
|
+
<string>${escapeXml(hookScript)}</string>
|
|
236
|
+
</array>
|
|
237
|
+
<key>EnvironmentVariables</key>
|
|
238
|
+
<dict>
|
|
239
|
+
<key>PATH</key>
|
|
240
|
+
<string>${escapeXml(envPath)}</string>
|
|
241
|
+
</dict>
|
|
242
|
+
<key>RunAtLoad</key>
|
|
243
|
+
<false/>
|
|
244
|
+
<key>StartInterval</key>
|
|
245
|
+
<integer>86400</integer>
|
|
246
|
+
<key>StandardOutPath</key>
|
|
247
|
+
<string>${escapeXml(logPath)}</string>
|
|
248
|
+
<key>StandardErrorPath</key>
|
|
249
|
+
<string>${escapeXml(logPath)}</string>
|
|
250
|
+
</dict>
|
|
251
|
+
</plist>
|
|
252
|
+
`;
|
|
253
|
+
}
|