skillo 0.2.6 → 0.2.8

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.
Files changed (68) hide show
  1. package/README.md +198 -198
  2. package/dist/api-client-BF6GDR7Q.js +12 -0
  3. package/dist/{chunk-WJKZWKER.js → chunk-63FVALWX.js} +1 -1
  4. package/dist/chunk-63FVALWX.js.map +1 -0
  5. package/dist/chunk-6GOJPFZ7.js +113 -0
  6. package/dist/chunk-6GOJPFZ7.js.map +1 -0
  7. package/dist/chunk-6UGTWBUW.js +89 -0
  8. package/dist/chunk-6UGTWBUW.js.map +1 -0
  9. package/dist/{chunk-2CVEPT6U.js → chunk-73NUWYUO.js} +2 -2
  10. package/dist/chunk-73NUWYUO.js.map +1 -0
  11. package/dist/chunk-QIV4VIXA.js +221 -0
  12. package/dist/chunk-QIV4VIXA.js.map +1 -0
  13. package/dist/{chunk-CPL3P2OF.js → chunk-QUXHHRRK.js} +2 -2
  14. package/dist/chunk-QUXHHRRK.js.map +1 -0
  15. package/dist/{chunk-ODOZM4QV.js → chunk-RQ2SC5HW.js} +72 -10
  16. package/dist/chunk-RQ2SC5HW.js.map +1 -0
  17. package/dist/chunk-U53QWUOR.js +727 -0
  18. package/dist/chunk-U53QWUOR.js.map +1 -0
  19. package/dist/chunk-VAQ73XPE.js +68 -0
  20. package/dist/chunk-VAQ73XPE.js.map +1 -0
  21. package/dist/chunk-XLJGCOVT.js +975 -0
  22. package/dist/chunk-XLJGCOVT.js.map +1 -0
  23. package/dist/{claude-watcher-N6GN6WHJ.js → claude-watcher-WKGBJYKN.js} +65 -3
  24. package/dist/claude-watcher-WKGBJYKN.js.map +1 -0
  25. package/dist/cli.js +495 -1846
  26. package/dist/cli.js.map +1 -1
  27. package/dist/{config-P5EM5L7N.js → config-ZOKAP2LJ.js} +3 -3
  28. package/dist/daemon-6DTCMOJB.js +28 -0
  29. package/dist/daemon-runner.js +338 -71
  30. package/dist/daemon-runner.js.map +1 -1
  31. package/dist/database-KQY5OSCS.js +9 -0
  32. package/dist/git-OGUSYBJS.js +16 -0
  33. package/dist/git-OGUSYBJS.js.map +1 -0
  34. package/dist/git-OUAHIOY2.js +110 -0
  35. package/dist/git-OUAHIOY2.js.map +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/{paths-INOKEM66.js → paths-MPOZBOKE.js} +2 -2
  38. package/dist/paths-MPOZBOKE.js.map +1 -0
  39. package/dist/project-OFU2W6MH.js +19 -0
  40. package/dist/project-OFU2W6MH.js.map +1 -0
  41. package/dist/shell-NZABRJLA.js +16 -0
  42. package/dist/shell-NZABRJLA.js.map +1 -0
  43. package/dist/skill-installer-F67OAOQN.js +121 -0
  44. package/dist/skill-installer-F67OAOQN.js.map +1 -0
  45. package/dist/{skill-usage-detector-EO26MRYV.js → skill-usage-detector-MSW5VWQZ.js} +2 -2
  46. package/dist/skill-usage-detector-MSW5VWQZ.js.map +1 -0
  47. package/dist/tray-WKFGUUTO.js +346 -0
  48. package/dist/tray-WKFGUUTO.js.map +1 -0
  49. package/package.json +62 -63
  50. package/scripts/postinstall.mjs +415 -364
  51. package/scripts/tray-helper-darwin +0 -0
  52. package/scripts/tray-helper-darwin.swift +180 -180
  53. package/scripts/tray-helper-linux.py +322 -0
  54. package/scripts/tray-helper-windows.cs +322 -0
  55. package/dist/api-client-KUQW7FSC.js +0 -12
  56. package/dist/chunk-2CVEPT6U.js.map +0 -1
  57. package/dist/chunk-CPL3P2OF.js.map +0 -1
  58. package/dist/chunk-ODOZM4QV.js.map +0 -1
  59. package/dist/chunk-WJKZWKER.js.map +0 -1
  60. package/dist/claude-watcher-N6GN6WHJ.js.map +0 -1
  61. package/dist/database-F3BFFZKG.js +0 -9
  62. package/dist/skill-usage-detector-EO26MRYV.js.map +0 -1
  63. package/dist/tray-UCAI2U2C.js +0 -408
  64. package/dist/tray-UCAI2U2C.js.map +0 -1
  65. /package/dist/{api-client-KUQW7FSC.js.map → api-client-BF6GDR7Q.js.map} +0 -0
  66. /package/dist/{config-P5EM5L7N.js.map → config-ZOKAP2LJ.js.map} +0 -0
  67. /package/dist/{database-F3BFFZKG.js.map → daemon-6DTCMOJB.js.map} +0 -0
  68. /package/dist/{paths-INOKEM66.js.map → database-KQY5OSCS.js.map} +0 -0
@@ -0,0 +1,346 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ StatusWriter
4
+ } from "./chunk-6UGTWBUW.js";
5
+ import {
6
+ ensureDirectory,
7
+ getDataDir
8
+ } from "./chunk-63FVALWX.js";
9
+
10
+ // src/tray/tray.ts
11
+ import { readFileSync, existsSync, writeFileSync, unlinkSync, chmodSync, statSync } from "fs";
12
+ import { exec, execSync, spawn } from "child_process";
13
+ import { join, dirname } from "path";
14
+ import { platform } from "os";
15
+ import { fileURLToPath } from "url";
16
+ var SEPARATOR = { title: "<SEPARATOR>", tooltip: "", enabled: true };
17
+ var ICON_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEE0lEQVR4nM2YS4gcRRjHOz4THyEqGKIePAiKeFECJggqGvcggl68KKxiTjklB8UHCQSMIplV8KAevOjeNHoxxyyCEBCML0Qvgd2Z7urqZ1VXdVXXVr92PmlIYBh2Znu6e2f3D7/bzFc/Zqr7+6oMY4cDAHsB4NTGxsZXxm4OANxUluViURRrZVlCWZY/GrsxAHBDlmWv5Xl+Nc9zGOGCsduitT6mtf4zTVMYR2v9nbFbIqU8liTJb0opmESSJDsvLIR4Wkr5i5QSavB95wIAcLjO5xhjT8RxfCmOY5iBboUBYAEA3qnzWSnlvVEUnWCMXY6iaMgYg62Ioqi7LQEA95dl6QHA/lm/6/v+Q5TSzwghnFIKkyCEdCdcluVPRVEMAeD2pjXCMLwzCIIzYRjKMAxhE7oRLory5aIooCLP8xNt63med9DzvGXf92EUz/PaCwPArXmeD0aESZqmj7QubBiG4zgvuq6LXNeFCsdx2gtnWXZ8rBtV4DzPn+pC2rbtexBCK7ZtA0KovXCappezLINx0jQtsyz7FAAOdDFTWJb1pWVZ7VpzJaO13tisjY7ga62PV/NBW/F+v3+0VQGl1BGtNdSkartPGjsZrfWz6+vrUBel1FAptSylPLgjwkKIR6cNK1PgSqlTAHDzXIUBYE+SJH6SJNCQf6WUz89VWghxpuakNY2LjLEH5yIMAPuEEH8IIaAlSgjx3ly2iVLqvjiO/+lAGuI4/m8u24QQsp9z/jXnfDjjjAsTuDCXbcI5f4FzvsY5h7YwxjRj7ONqittWaQC4JYqik4yxuM5gzrbGYYy9Ymx3giA4RCn9hlI6jKII2kIp/RZjfNu2i1NKj1JKr0w7TdD6/F6NtHNpMoSQRUKIRwiBNoRh+JExrzDGDoRh+HkQBMWEYxDUIOWc323MM67rPub7/s9BEEATwjB8vdHf3FY8CIJXfd83x89vNTjbRPh9AHiprbRlWfsqAd/312cQ/nDmhYqiWMrzfFgUxTkAuLGtOELoAdd1lz3Pg61wXfetmRfIsmxp5Bx3qbrNMToIxnjBcZz+9dPyZti2/fDMhZVSvbFTRaSUOtnFr+37/h0Y4y8cx4FxMMZXGhWVUp7fbDCXUv6aJMnjRgexbfsNjHGGMYbrIIQWGxUTQvSmjIkbQoiLcRwf6UD6zepe4trdxF+NT+BRFPVq3jqucM4Xmi4EAHssy7qKEKqEnzOahhDSq9n/fUrp29Xrq+lalmWtmKb5g9EmQRAsTWuhQRCQMAzPVsN9m3X6/f5e0zT/Xl1dbXc94Lpub8J7knqe90H1pBsdxDTNd9fW1p5pXQhjvDT2uhGO43zS7/db36dtSxBCS9ee3AQhdM40zbuM3ZzBYHDaNM3zg8Hg0E67jOZ/1kjldsi1/g0AAAAASUVORK5CYII=";
18
+ var TRAY_PID_FILE = "tray.pid";
19
+ var STATUS_POLL_MS = 3e3;
20
+ function formatTimeAgo(isoString) {
21
+ if (!isoString) return "Never";
22
+ const diff = Date.now() - new Date(isoString).getTime();
23
+ const seconds = Math.floor(diff / 1e3);
24
+ if (seconds < 60) return "Just now";
25
+ const minutes = Math.floor(seconds / 60);
26
+ if (minutes < 60) return `${minutes} min ago`;
27
+ const hours = Math.floor(minutes / 60);
28
+ if (hours < 24) return `${hours}h ago`;
29
+ const days = Math.floor(hours / 24);
30
+ return `${days}d ago`;
31
+ }
32
+ function readStatus() {
33
+ return StatusWriter.read();
34
+ }
35
+ function buildMenu(status) {
36
+ const running = status?.running ?? false;
37
+ const statusIcon = running ? "\u25CF" : "\u25CB";
38
+ const statusText = running ? "Running" : "Stopped";
39
+ const projects = status?.trackedProjects ?? [];
40
+ const projectItems = projects.length > 0 ? projects.map((p) => ({
41
+ title: ` ${p.name}`,
42
+ tooltip: p.path,
43
+ enabled: false,
44
+ checked: false
45
+ })) : [{
46
+ title: " (none)",
47
+ tooltip: "No tracked projects",
48
+ enabled: false,
49
+ checked: false
50
+ }];
51
+ const items = [
52
+ {
53
+ title: `${statusIcon} Skillo \u2014 ${statusText}`,
54
+ tooltip: "Daemon status",
55
+ enabled: false,
56
+ checked: false
57
+ },
58
+ SEPARATOR,
59
+ {
60
+ title: status?.user ? `Logged in as: ${status.user}` : "Not logged in",
61
+ tooltip: "User info",
62
+ enabled: false,
63
+ checked: false
64
+ },
65
+ SEPARATOR,
66
+ {
67
+ title: `Tracked Projects (${projects.length})`,
68
+ tooltip: "Projects being tracked",
69
+ enabled: false,
70
+ checked: false
71
+ },
72
+ ...projectItems,
73
+ SEPARATOR,
74
+ {
75
+ title: `Last sync: ${formatTimeAgo(status?.claudeWatcher?.lastSync)}`,
76
+ tooltip: "Last Claude conversation sync",
77
+ enabled: false,
78
+ checked: false
79
+ },
80
+ {
81
+ title: `Prompts synced: ${status?.claudeWatcher?.promptsSynced ?? 0}`,
82
+ tooltip: "Total prompts synced",
83
+ enabled: false,
84
+ checked: false
85
+ },
86
+ {
87
+ title: `Skills detected: ${status?.skillDetector?.usagesDetected ?? 0}`,
88
+ tooltip: "Skill usages detected",
89
+ enabled: false,
90
+ checked: false
91
+ },
92
+ SEPARATOR,
93
+ {
94
+ title: running ? "Stop Daemon" : "Start Daemon",
95
+ tooltip: running ? "Stop the Skillo daemon" : "Start the Skillo daemon",
96
+ enabled: true,
97
+ checked: false
98
+ },
99
+ {
100
+ title: "Open Dashboard",
101
+ tooltip: "Open Skillo dashboard in browser",
102
+ enabled: true,
103
+ checked: false
104
+ },
105
+ SEPARATOR,
106
+ {
107
+ title: "Quit Tray",
108
+ tooltip: "Hide tray icon (daemon keeps running)",
109
+ enabled: true,
110
+ checked: false
111
+ }
112
+ ];
113
+ return {
114
+ icon: ICON_BASE64,
115
+ title: "",
116
+ tooltip: `Skillo \u2014 ${statusText}`,
117
+ items
118
+ };
119
+ }
120
+ function openBrowser(url) {
121
+ const os = platform();
122
+ let cmd;
123
+ if (os === "darwin") {
124
+ cmd = `open "${url}"`;
125
+ } else if (os === "win32") {
126
+ cmd = `start "" "${url}"`;
127
+ } else {
128
+ cmd = `xdg-open "${url}"`;
129
+ }
130
+ exec(cmd, () => {
131
+ });
132
+ }
133
+ function execSkillo(args) {
134
+ exec(`skillo ${args}`, () => {
135
+ });
136
+ }
137
+ function handleClick(title, cleanup) {
138
+ if (title === "Stop Daemon" || title === "Start Daemon") {
139
+ execSkillo(title === "Stop Daemon" ? "stop" : "start");
140
+ } else if (title === "Open Dashboard") {
141
+ openBrowser("https://www.skillo.one/dashboard");
142
+ } else if (title === "Quit Tray") {
143
+ cleanup();
144
+ }
145
+ }
146
+ async function runNativeHelper(command, args, pidFile) {
147
+ const helper = spawn(command, args, {
148
+ stdio: ["pipe", "pipe", "ignore"]
149
+ });
150
+ const cleanup = () => {
151
+ try {
152
+ unlinkSync(pidFile);
153
+ } catch {
154
+ }
155
+ helper.kill();
156
+ process.exit(0);
157
+ };
158
+ process.on("SIGINT", cleanup);
159
+ process.on("SIGTERM", cleanup);
160
+ helper.on("exit", () => {
161
+ try {
162
+ unlinkSync(pidFile);
163
+ } catch {
164
+ }
165
+ process.exit(0);
166
+ });
167
+ await new Promise((resolve, reject) => {
168
+ let buf = "";
169
+ const onData = (data) => {
170
+ buf += data.toString();
171
+ const lines = buf.split("\n");
172
+ buf = lines.pop() || "";
173
+ for (const line of lines) {
174
+ if (!line.trim()) continue;
175
+ try {
176
+ const msg = JSON.parse(line);
177
+ if (msg.type === "ready") {
178
+ helper.stdout.removeListener("data", onData);
179
+ resolve();
180
+ }
181
+ } catch {
182
+ }
183
+ }
184
+ };
185
+ helper.stdout.on("data", onData);
186
+ setTimeout(() => reject(new Error("Tray helper did not become ready")), 1e4);
187
+ });
188
+ const initialStatus = readStatus();
189
+ const menu = buildMenu(initialStatus);
190
+ helper.stdin.write(JSON.stringify(menu) + "\n");
191
+ let clickBuf = "";
192
+ helper.stdout.on("data", (data) => {
193
+ clickBuf += data.toString();
194
+ const lines = clickBuf.split("\n");
195
+ clickBuf = lines.pop() || "";
196
+ for (const line of lines) {
197
+ if (!line.trim()) continue;
198
+ try {
199
+ const msg = JSON.parse(line);
200
+ if (msg.type === "clicked" && msg.item) {
201
+ handleClick(msg.item.title, cleanup);
202
+ }
203
+ } catch {
204
+ }
205
+ }
206
+ });
207
+ setInterval(() => {
208
+ try {
209
+ const status = readStatus();
210
+ const updatedMenu = buildMenu(status);
211
+ const action = { type: "update-menu", menu: updatedMenu };
212
+ helper.stdin.write(JSON.stringify(action) + "\n");
213
+ } catch {
214
+ }
215
+ }, STATUS_POLL_MS);
216
+ await new Promise(() => {
217
+ });
218
+ }
219
+ function findDarwinHelper() {
220
+ const candidates = [
221
+ join(getDataDir(), "tray-helper-darwin"),
222
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-darwin"),
223
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-darwin")
224
+ ];
225
+ for (const p of candidates) {
226
+ if (existsSync(p)) return p;
227
+ }
228
+ return null;
229
+ }
230
+ function compileDarwinHelper() {
231
+ const srcCandidates = [
232
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-darwin.swift"),
233
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-darwin.swift")
234
+ ];
235
+ let src = null;
236
+ for (const p of srcCandidates) {
237
+ if (existsSync(p)) {
238
+ src = p;
239
+ break;
240
+ }
241
+ }
242
+ if (!src) return null;
243
+ const out = join(getDataDir(), "tray-helper-darwin");
244
+ try {
245
+ execSync(`swiftc "${src}" -o "${out}" -O 2>/dev/null`, { timeout: 6e4 });
246
+ chmodSync(out, 493);
247
+ return out;
248
+ } catch {
249
+ return null;
250
+ }
251
+ }
252
+ function findOrCompileWindowsHelper() {
253
+ const exePath = join(getDataDir(), "tray-helper-windows.exe");
254
+ const srcCandidates = [
255
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-windows.cs"),
256
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-windows.cs")
257
+ ];
258
+ const src = srcCandidates.find((p) => existsSync(p)) || null;
259
+ if (!src) return existsSync(exePath) ? exePath : null;
260
+ if (existsSync(exePath)) {
261
+ try {
262
+ const srcStat = statSync(src);
263
+ const exeStat = statSync(exePath);
264
+ if (srcStat.mtimeMs <= exeStat.mtimeMs) return exePath;
265
+ } catch {
266
+ }
267
+ }
268
+ const cscPaths = [
269
+ "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe",
270
+ "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe"
271
+ ];
272
+ const csc = cscPaths.find((p) => existsSync(p));
273
+ if (!csc) return existsSync(exePath) ? exePath : null;
274
+ try {
275
+ execSync(
276
+ `"${csc}" /nologo /target:winexe /r:System.Windows.Forms.dll /r:System.Drawing.dll /r:System.Web.Extensions.dll /out:"${exePath}" "${src}"`,
277
+ { timeout: 3e4, shell: "cmd.exe" }
278
+ );
279
+ return exePath;
280
+ } catch {
281
+ return existsSync(exePath) ? exePath : null;
282
+ }
283
+ }
284
+ function findLinuxHelper() {
285
+ const scriptCandidates = [
286
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-linux.py"),
287
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-linux.py")
288
+ ];
289
+ const script = scriptCandidates.find((p) => existsSync(p)) || null;
290
+ if (!script) return null;
291
+ try {
292
+ execSync("python3 --version", { stdio: "ignore" });
293
+ return { python: "python3", script };
294
+ } catch {
295
+ }
296
+ try {
297
+ const ver = execSync("python --version", { encoding: "utf-8" });
298
+ if (ver.includes("Python 3")) return { python: "python", script };
299
+ } catch {
300
+ }
301
+ return null;
302
+ }
303
+ async function startTray() {
304
+ const pidFile = join(getDataDir(), TRAY_PID_FILE);
305
+ ensureDirectory(getDataDir());
306
+ if (existsSync(pidFile)) {
307
+ try {
308
+ const pid = parseInt(readFileSync(pidFile, "utf-8").trim(), 10);
309
+ process.kill(pid, 0);
310
+ console.error("Tray icon is already running (PID: " + pid + ")");
311
+ process.exit(1);
312
+ } catch {
313
+ }
314
+ }
315
+ writeFileSync(pidFile, String(process.pid));
316
+ const os = platform();
317
+ if (os === "darwin") {
318
+ let helperPath = findDarwinHelper();
319
+ if (!helperPath) {
320
+ helperPath = compileDarwinHelper();
321
+ }
322
+ if (!helperPath) {
323
+ console.error("Could not find or compile tray helper. Install Xcode Command Line Tools: xcode-select --install");
324
+ process.exit(1);
325
+ }
326
+ await runNativeHelper(helperPath, [], pidFile);
327
+ } else if (os === "win32") {
328
+ const helperPath = findOrCompileWindowsHelper();
329
+ if (!helperPath) {
330
+ console.error("Could not find or compile tray helper. Requires .NET Framework 4.x (pre-installed on Windows 10/11).");
331
+ process.exit(1);
332
+ }
333
+ await runNativeHelper(helperPath, [], pidFile);
334
+ } else {
335
+ const result = findLinuxHelper();
336
+ if (!result) {
337
+ console.error("Could not find tray helper. Requires python3 with PyGObject (python3-gi).");
338
+ process.exit(1);
339
+ }
340
+ await runNativeHelper(result.python, [result.script], pidFile);
341
+ }
342
+ }
343
+ export {
344
+ startTray
345
+ };
346
+ //# sourceMappingURL=tray-WKFGUUTO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tray/tray.ts"],"sourcesContent":["/**\r\n * Skillo System Tray Icon\r\n *\r\n * Shows daemon status, tracked projects, sync info in the system tray.\r\n * Reads ~/.skillo/daemon-status.json (written by StatusWriter in daemon).\r\n *\r\n * macOS: native Swift helper (scripts/tray-helper-darwin.swift).\r\n * Windows: native C# helper (scripts/tray-helper-windows.cs, .NET Framework 4.x).\r\n * Linux: native Python3 helper (scripts/tray-helper-linux.py, PyGObject/GTK).\r\n */\r\n\r\nimport { readFileSync, existsSync, writeFileSync, unlinkSync, chmodSync, statSync } from \"fs\";\r\nimport { exec, execSync, spawn } from \"child_process\";\r\nimport { join, dirname } from \"path\";\r\nimport { platform } from \"os\";\r\nimport { fileURLToPath } from \"url\";\r\nimport { StatusWriter, type DaemonStatus } from \"../utils/status-writer.js\";\r\nimport { getDataDir, ensureDirectory } from \"../utils/paths.js\";\r\n\r\ntype MenuItem = {\r\n title: string;\r\n tooltip: string;\r\n checked?: boolean;\r\n enabled?: boolean;\r\n hidden?: boolean;\r\n items?: MenuItem[];\r\n};\r\n\r\ntype Menu = {\r\n icon: string;\r\n title: string;\r\n tooltip: string;\r\n items: MenuItem[];\r\n};\r\n\r\nconst SEPARATOR: MenuItem = { title: \"<SEPARATOR>\", tooltip: \"\", enabled: true };\r\n\r\n// Skillo \"S\" logo as 44x44 white-on-transparent PNG (from public/logo.svg)\r\n// macOS: isTemplate=true auto-inverts for dark/light mode\r\n// Windows/Linux: white logo on dark tray background\r\nconst ICON_BASE64 =\r\n \"iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE\" +\r\n \"E0lEQVR4nM2YS4gcRRjHOz4THyEqGKIePAiKeFECJggqGvcggl68KKxiTjklB8UHCQSMIplV\" +\r\n \"8KAevOjeNHoxxyyCEBCML0Qvgd2Z7urqZ1VXdVXXVr92PmlIYBh2Znu6e2f3D7/bzFc/Zqr7\" +\r\n \"+6oMY4cDAHsB4NTGxsZXxm4OANxUluViURRrZVlCWZY/GrsxAHBDlmWv5Xl+Nc9zGOGCsdui\" +\r\n \"tT6mtf4zTVMYR2v9nbFbIqU8liTJb0opmESSJDsvLIR4Wkr5i5QSavB95wIAcLjO5xhjT8Rx\" +\r\n \"fCmOY5iBboUBYAEA3qnzWSnlvVEUnWCMXY6iaMgYg62Ioqi7LQEA95dl6QHA/lm/6/v+Q5TS\" +\r\n \"zwghnFIKkyCEdCdcluVPRVEMAeD2pjXCMLwzCIIzYRjKMAxhE7oRLory5aIooCLP8xNt63med9\" +\r\n \"DzvGXf92EUz/PaCwPArXmeD0aESZqmj7QubBiG4zgvuq6LXNeFCsdx2gtnWXZ8rBtV4DzPn+\" +\r\n \"pC2rbtexBCK7ZtA0KovXCappezLINx0jQtsyz7FAAOdDFTWJb1pWVZ7VpzJaO13tisjY7ga62P\" +\r\n \"V/NBW/F+v3+0VQGl1BGtNdSkartPGjsZrfWz6+vrUBel1FAptSylPLgjwkKIR6cNK1PgSqlTAH\" +\r\n \"DzXIUBYE+SJH6SJNCQf6WUz89VWghxpuakNY2LjLEH5yIMAPuEEH8IIaAlSgjx3ly2iVLqvj\" +\r\n \"iO/+lAGuI4/m8u24QQsp9z/jXnfDjjjAsTuDCXbcI5f4FzvsY5h7YwxjRj7ONqittWaQC4JY\" +\r\n \"qik4yxuM5gzrbGYYy9Ymx3giA4RCn9hlI6jKII2kIp/RZjfNu2i1NKj1JKr0w7TdD6/F6NtH\" +\r\n \"NpMoSQRUKIRwiBNoRh+JExrzDGDoRh+HkQBMWEYxDUIOWc323MM67rPub7/s9BEEATwjB8vdHf\" +\r\n \"3FY8CIJXfd83x89vNTjbRPh9AHiprbRlWfsqAd/312cQ/nDmhYqiWMrzfFgUxTkAuLGtOELo\" +\r\n \"Add1lz3Pg61wXfetmRfIsmxp5Bx3qbrNMToIxnjBcZz+9dPyZti2/fDMhZVSvbFTRaSUOtnFr+\" +\r\n \"37/h0Y4y8cx4FxMMZXGhWVUp7fbDCXUv6aJMnjRgexbfsNjHGGMYbrIIQWGxUTQvSmjIkbQo\" +\r\n \"iLcRwf6UD6zepe4trdxF+NT+BRFPVq3jqucM4Xmi4EAHssy7qKEKqEnzOahhDSq9n/fUrp29\" +\r\n \"Xrq+lalmWtmKb5g9EmQRAsTWuhQRCQMAzPVsN9m3X6/f5e0zT/Xl1dbXc94Lpub8J7knqe90\" +\r\n \"H1pBsdxDTNd9fW1p5pXQhjvDT2uhGO43zS7/db36dtSxBCS9ee3AQhdM40zbuM3ZzBYHDaNM\" +\r\n \"3zg8Hg0E67jOZ/1kjldsi1/g0AAAAASUVORK5CYII=\";\r\n\r\nconst TRAY_PID_FILE = \"tray.pid\";\r\nconst STATUS_POLL_MS = 3000;\r\n\r\nfunction formatTimeAgo(isoString: string | null | undefined): string {\r\n if (!isoString) return \"Never\";\r\n const diff = Date.now() - new Date(isoString).getTime();\r\n const seconds = Math.floor(diff / 1000);\r\n if (seconds < 60) return \"Just now\";\r\n const minutes = Math.floor(seconds / 60);\r\n if (minutes < 60) return `${minutes} min ago`;\r\n const hours = Math.floor(minutes / 60);\r\n if (hours < 24) return `${hours}h ago`;\r\n const days = Math.floor(hours / 24);\r\n return `${days}d ago`;\r\n}\r\n\r\nfunction readStatus(): DaemonStatus | null {\r\n return StatusWriter.read();\r\n}\r\n\r\nfunction buildMenu(status: DaemonStatus | null): Menu {\r\n const running = status?.running ?? false;\r\n const statusIcon = running ? \"\\u25CF\" : \"\\u25CB\"; // ● or ○\r\n const statusText = running ? \"Running\" : \"Stopped\";\r\n\r\n const projects = status?.trackedProjects ?? [];\r\n const projectItems: MenuItem[] = projects.length > 0\r\n ? projects.map((p) => ({\r\n title: ` ${p.name}`,\r\n tooltip: p.path,\r\n enabled: false,\r\n checked: false,\r\n }))\r\n : [{\r\n title: \" (none)\",\r\n tooltip: \"No tracked projects\",\r\n enabled: false,\r\n checked: false,\r\n }];\r\n\r\n const items: MenuItem[] = [\r\n {\r\n title: `${statusIcon} Skillo \\u2014 ${statusText}`,\r\n tooltip: \"Daemon status\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: status?.user ? `Logged in as: ${status.user}` : \"Not logged in\",\r\n tooltip: \"User info\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: `Tracked Projects (${projects.length})`,\r\n tooltip: \"Projects being tracked\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n ...projectItems,\r\n SEPARATOR,\r\n {\r\n title: `Last sync: ${formatTimeAgo(status?.claudeWatcher?.lastSync)}`,\r\n tooltip: \"Last Claude conversation sync\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n {\r\n title: `Prompts synced: ${status?.claudeWatcher?.promptsSynced ?? 0}`,\r\n tooltip: \"Total prompts synced\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n {\r\n title: `Skills detected: ${status?.skillDetector?.usagesDetected ?? 0}`,\r\n tooltip: \"Skill usages detected\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: running ? \"Stop Daemon\" : \"Start Daemon\",\r\n tooltip: running ? \"Stop the Skillo daemon\" : \"Start the Skillo daemon\",\r\n enabled: true,\r\n checked: false,\r\n },\r\n {\r\n title: \"Open Dashboard\",\r\n tooltip: \"Open Skillo dashboard in browser\",\r\n enabled: true,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: \"Quit Tray\",\r\n tooltip: \"Hide tray icon (daemon keeps running)\",\r\n enabled: true,\r\n checked: false,\r\n },\r\n ];\r\n\r\n return {\r\n icon: ICON_BASE64,\r\n title: \"\",\r\n tooltip: `Skillo \\u2014 ${statusText}`,\r\n items,\r\n };\r\n}\r\n\r\nfunction openBrowser(url: string) {\r\n const os = platform();\r\n let cmd: string;\r\n if (os === \"darwin\") {\r\n cmd = `open \"${url}\"`;\r\n } else if (os === \"win32\") {\r\n cmd = `start \"\" \"${url}\"`;\r\n } else {\r\n cmd = `xdg-open \"${url}\"`;\r\n }\r\n exec(cmd, () => {});\r\n}\r\n\r\nfunction execSkillo(args: string) {\r\n exec(`skillo ${args}`, () => {});\r\n}\r\n\r\nfunction handleClick(title: string, cleanup: () => void) {\r\n if (title === \"Stop Daemon\" || title === \"Start Daemon\") {\r\n execSkillo(title === \"Stop Daemon\" ? \"stop\" : \"start\");\r\n } else if (title === \"Open Dashboard\") {\r\n openBrowser(\"https://www.skillo.one/dashboard\");\r\n } else if (title === \"Quit Tray\") {\r\n cleanup();\r\n }\r\n}\r\n\r\n// ── Shared native helper runner ───────────────────────────────────────────────\r\n\r\nasync function runNativeHelper(\r\n command: string,\r\n args: string[],\r\n pidFile: string,\r\n): Promise<void> {\r\n const helper = spawn(command, args, {\r\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\r\n });\r\n\r\n const cleanup = () => {\r\n try { unlinkSync(pidFile); } catch { /* ignore */ }\r\n helper.kill();\r\n process.exit(0);\r\n };\r\n process.on(\"SIGINT\", cleanup);\r\n process.on(\"SIGTERM\", cleanup);\r\n helper.on(\"exit\", () => {\r\n try { unlinkSync(pidFile); } catch { /* ignore */ }\r\n process.exit(0);\r\n });\r\n\r\n // Wait for {\"type\":\"ready\"} with 10s timeout\r\n await new Promise<void>((resolve, reject) => {\r\n let buf = \"\";\r\n const onData = (data: Buffer) => {\r\n buf += data.toString();\r\n const lines = buf.split(\"\\n\");\r\n buf = lines.pop() || \"\";\r\n for (const line of lines) {\r\n if (!line.trim()) continue;\r\n try {\r\n const msg = JSON.parse(line);\r\n if (msg.type === \"ready\") {\r\n helper.stdout!.removeListener(\"data\", onData);\r\n resolve();\r\n }\r\n } catch { /* ignore parse errors */ }\r\n }\r\n };\r\n helper.stdout!.on(\"data\", onData);\r\n setTimeout(() => reject(new Error(\"Tray helper did not become ready\")), 10000);\r\n });\r\n\r\n // Send initial menu\r\n const initialStatus = readStatus();\r\n const menu = buildMenu(initialStatus);\r\n helper.stdin!.write(JSON.stringify(menu) + \"\\n\");\r\n\r\n // Listen for clicks\r\n let clickBuf = \"\";\r\n helper.stdout!.on(\"data\", (data: Buffer) => {\r\n clickBuf += data.toString();\r\n const lines = clickBuf.split(\"\\n\");\r\n clickBuf = lines.pop() || \"\";\r\n for (const line of lines) {\r\n if (!line.trim()) continue;\r\n try {\r\n const msg = JSON.parse(line);\r\n if (msg.type === \"clicked\" && msg.item) {\r\n handleClick(msg.item.title, cleanup);\r\n }\r\n } catch { /* ignore */ }\r\n }\r\n });\r\n\r\n // Poll and update\r\n setInterval(() => {\r\n try {\r\n const status = readStatus();\r\n const updatedMenu = buildMenu(status);\r\n const action = { type: \"update-menu\", menu: updatedMenu };\r\n helper.stdin!.write(JSON.stringify(action) + \"\\n\");\r\n } catch { /* ignore */ }\r\n }, STATUS_POLL_MS);\r\n\r\n await new Promise(() => {});\r\n}\r\n\r\n// ── macOS native tray (Swift helper) ─────────────────────────────────────────\r\n\r\nfunction findDarwinHelper(): string | null {\r\n const candidates = [\r\n join(getDataDir(), \"tray-helper-darwin\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-darwin\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-darwin\"),\r\n ];\r\n for (const p of candidates) {\r\n if (existsSync(p)) return p;\r\n }\r\n return null;\r\n}\r\n\r\nfunction compileDarwinHelper(): string | null {\r\n const srcCandidates = [\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-darwin.swift\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-darwin.swift\"),\r\n ];\r\n let src: string | null = null;\r\n for (const p of srcCandidates) {\r\n if (existsSync(p)) { src = p; break; }\r\n }\r\n if (!src) return null;\r\n\r\n const out = join(getDataDir(), \"tray-helper-darwin\");\r\n try {\r\n execSync(`swiftc \"${src}\" -o \"${out}\" -O 2>/dev/null`, { timeout: 60000 });\r\n chmodSync(out, 0o755);\r\n return out;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n// ── Windows native tray (C# helper) ──────────────────────────────────────────\r\n\r\nfunction findOrCompileWindowsHelper(): string | null {\r\n const exePath = join(getDataDir(), \"tray-helper-windows.exe\");\r\n const srcCandidates = [\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-windows.cs\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-windows.cs\"),\r\n ];\r\n\r\n const src = srcCandidates.find((p) => existsSync(p)) || null;\r\n if (!src) return existsSync(exePath) ? exePath : null;\r\n\r\n // Check if recompile needed (source newer than binary)\r\n if (existsSync(exePath)) {\r\n try {\r\n const srcStat = statSync(src);\r\n const exeStat = statSync(exePath);\r\n if (srcStat.mtimeMs <= exeStat.mtimeMs) return exePath; // cached\r\n } catch { /* recompile on error */ }\r\n }\r\n\r\n // Find csc.exe\r\n const cscPaths = [\r\n \"C:\\\\Windows\\\\Microsoft.NET\\\\Framework64\\\\v4.0.30319\\\\csc.exe\",\r\n \"C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\v4.0.30319\\\\csc.exe\",\r\n ];\r\n const csc = cscPaths.find((p) => existsSync(p));\r\n if (!csc) return existsSync(exePath) ? exePath : null;\r\n\r\n try {\r\n execSync(\r\n `\"${csc}\" /nologo /target:winexe /r:System.Windows.Forms.dll /r:System.Drawing.dll /r:System.Web.Extensions.dll /out:\"${exePath}\" \"${src}\"`,\r\n { timeout: 30000, shell: \"cmd.exe\" },\r\n );\r\n return exePath;\r\n } catch {\r\n return existsSync(exePath) ? exePath : null;\r\n }\r\n}\r\n\r\n// ── Linux native tray (Python3 helper) ───────────────────────────────────────\r\n\r\nfunction findLinuxHelper(): { python: string; script: string } | null {\r\n const scriptCandidates = [\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-linux.py\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-linux.py\"),\r\n ];\r\n\r\n const script = scriptCandidates.find((p) => existsSync(p)) || null;\r\n if (!script) return null;\r\n\r\n // Find python3\r\n try {\r\n execSync(\"python3 --version\", { stdio: \"ignore\" });\r\n return { python: \"python3\", script };\r\n } catch { /* try next */ }\r\n\r\n try {\r\n const ver = execSync(\"python --version\", { encoding: \"utf-8\" });\r\n if (ver.includes(\"Python 3\")) return { python: \"python\", script };\r\n } catch { /* not available */ }\r\n\r\n return null;\r\n}\r\n\r\n// ── Entry point ──────────────────────────────────────────────────────────────\r\n\r\nexport async function startTray(): Promise<void> {\r\n const pidFile = join(getDataDir(), TRAY_PID_FILE);\r\n ensureDirectory(getDataDir());\r\n\r\n // Check if another tray is already running\r\n if (existsSync(pidFile)) {\r\n try {\r\n const pid = parseInt(readFileSync(pidFile, \"utf-8\").trim(), 10);\r\n process.kill(pid, 0);\r\n console.error(\"Tray icon is already running (PID: \" + pid + \")\");\r\n process.exit(1);\r\n } catch {\r\n // Stale PID file, continue\r\n }\r\n }\r\n\r\n writeFileSync(pidFile, String(process.pid));\r\n\r\n const os = platform();\r\n\r\n if (os === \"darwin\") {\r\n let helperPath = findDarwinHelper();\r\n if (!helperPath) {\r\n helperPath = compileDarwinHelper();\r\n }\r\n if (!helperPath) {\r\n console.error(\"Could not find or compile tray helper. Install Xcode Command Line Tools: xcode-select --install\");\r\n process.exit(1);\r\n }\r\n await runNativeHelper(helperPath, [], pidFile);\r\n } else if (os === \"win32\") {\r\n const helperPath = findOrCompileWindowsHelper();\r\n if (!helperPath) {\r\n console.error(\"Could not find or compile tray helper. Requires .NET Framework 4.x (pre-installed on Windows 10/11).\");\r\n process.exit(1);\r\n }\r\n await runNativeHelper(helperPath, [], pidFile);\r\n } else {\r\n const result = findLinuxHelper();\r\n if (!result) {\r\n console.error(\"Could not find tray helper. Requires python3 with PyGObject (python3-gi).\");\r\n process.exit(1);\r\n }\r\n await runNativeHelper(result.python, [result.script], pidFile);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,63 +1,62 @@
1
- {
2
- "name": "skillo",
3
- "version": "0.2.6",
4
- "description": "Autonomous workflow learning & skill generation system - Learn workflows by observation, not explanation",
5
- "keywords": [
6
- "cli",
7
- "workflow",
8
- "automation",
9
- "ai",
10
- "skills",
11
- "claude",
12
- "claude-code",
13
- "learning",
14
- "terminal"
15
- ],
16
- "author": "Erkan Dogan",
17
- "license": "UNLICENSED",
18
- "homepage": "https://skillo.one",
19
- "type": "module",
20
- "bin": {
21
- "skillo": "./dist/cli.js"
22
- },
23
- "main": "./dist/index.js",
24
- "types": "./dist/index.d.ts",
25
- "exports": {
26
- ".": {
27
- "import": "./dist/index.js",
28
- "types": "./dist/index.d.ts"
29
- }
30
- },
31
- "files": [
32
- "dist",
33
- "scripts",
34
- "assets",
35
- "README.md"
36
- ],
37
- "engines": {
38
- "node": ">=18.0.0"
39
- },
40
- "scripts": {
41
- "build": "tsup",
42
- "dev": "tsup --watch",
43
- "start": "node dist/cli.js",
44
- "typecheck": "tsc --noEmit",
45
- "lint": "eslint src/",
46
- "postinstall": "node scripts/postinstall.mjs",
47
- "prepublishOnly": "npm run build"
48
- },
49
- "dependencies": {
50
- "chalk": "^5.4.1",
51
- "commander": "^13.1.0",
52
- "ora": "^8.2.0",
53
- "sql.js": "^1.12.0",
54
- "systray2": "^2.1.4",
55
- "yaml": "^2.7.0"
56
- },
57
- "devDependencies": {
58
- "@types/node": "^22.10.10",
59
- "@types/sql.js": "^1.4.9",
60
- "tsup": "^8.3.5",
61
- "typescript": "^5.7.3"
62
- }
63
- }
1
+ {
2
+ "name": "skillo",
3
+ "version": "0.2.8",
4
+ "description": "Autonomous workflow learning & skill generation system - Learn workflows by observation, not explanation",
5
+ "keywords": [
6
+ "cli",
7
+ "workflow",
8
+ "automation",
9
+ "ai",
10
+ "skills",
11
+ "claude",
12
+ "claude-code",
13
+ "learning",
14
+ "terminal"
15
+ ],
16
+ "author": "Erkan Dogan",
17
+ "license": "UNLICENSED",
18
+ "homepage": "https://skillo.one",
19
+ "type": "module",
20
+ "bin": {
21
+ "skillo": "./dist/cli.js"
22
+ },
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "import": "./dist/index.js",
28
+ "types": "./dist/index.d.ts"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "scripts",
34
+ "assets",
35
+ "README.md"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "dev": "tsup --watch",
43
+ "start": "node dist/cli.js",
44
+ "typecheck": "tsc --noEmit",
45
+ "lint": "eslint src/",
46
+ "postinstall": "node scripts/postinstall.mjs",
47
+ "prepublishOnly": "npm run build"
48
+ },
49
+ "dependencies": {
50
+ "chalk": "^5.4.1",
51
+ "commander": "^13.1.0",
52
+ "ora": "^8.2.0",
53
+ "sql.js": "^1.12.0",
54
+ "yaml": "^2.7.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^22.10.10",
58
+ "@types/sql.js": "^1.4.9",
59
+ "tsup": "^8.3.5",
60
+ "typescript": "^5.7.3"
61
+ }
62
+ }