ai-lens 0.7.0 → 0.7.2

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/.commithash CHANGED
@@ -1 +1 @@
1
- 7773594
1
+ 13ac046
package/cli/init.js CHANGED
@@ -441,6 +441,18 @@ export default async function init() {
441
441
  }
442
442
  blank();
443
443
 
444
+ // Verify hooks were written correctly
445
+ heading('Verifying hooks...');
446
+ for (const { tool } of pending) {
447
+ const recheck = analyzeToolHooks(tool);
448
+ if (recheck.status === 'current') {
449
+ success(` ${tool.name}: hooks verified`);
450
+ } else {
451
+ error(` ${tool.name}: hooks not current (status: ${recheck.status})`);
452
+ }
453
+ }
454
+ blank();
455
+
444
456
  // Summary
445
457
  heading('Summary');
446
458
  for (const r of results) {
package/cli/status.js CHANGED
@@ -17,7 +17,7 @@ const RED = '\x1b[31m';
17
17
  const CHECK = `${GREEN}\u2713${RESET}`;
18
18
  const CROSS = `${RED}\u2717${RESET}`;
19
19
 
20
- const REPORT_PATH = join(DATA_DIR, 'status-report.txt');
20
+ const REPORT_PATH = join(homedir(), 'ai-lens-status.txt');
21
21
 
22
22
  function maskToken(token) {
23
23
  if (!token || token.length < 20) return token || '(none)';
@@ -49,6 +49,61 @@ function relativeTime(dateStr) {
49
49
  // Individual checks — each returns { ok, summary, detail }
50
50
  // ---------------------------------------------------------------------------
51
51
 
52
+ function extractHookCommand(tool) {
53
+ try {
54
+ const raw = readFileSync(tool.configPath, 'utf-8');
55
+ const config = JSON.parse(raw);
56
+ if (!config.hooks) return null;
57
+ for (const hookName of Object.keys(config.hooks)) {
58
+ const entries = config.hooks[hookName];
59
+ if (!Array.isArray(entries)) continue;
60
+ for (const entry of entries) {
61
+ // Flat format (Cursor): { command: "..." }
62
+ if (entry?.command?.includes('capture.js')) return entry.command;
63
+ // Nested format (Claude Code): { hooks: [{ command: "..." }] }
64
+ if (Array.isArray(entry?.hooks)) {
65
+ for (const h of entry.hooks) {
66
+ if (h?.command?.includes('capture.js')) return h.command;
67
+ }
68
+ }
69
+ }
70
+ }
71
+ } catch { /* config unreadable */ }
72
+ return null;
73
+ }
74
+
75
+ function checkCaptureRun(installedTools) {
76
+ let command = null;
77
+ for (const tool of installedTools) {
78
+ command = extractHookCommand(tool);
79
+ if (command) break;
80
+ }
81
+
82
+ if (!command) {
83
+ return { ok: null, summary: 'no hook command found', detail: 'Could not find an AI Lens hook command in any tool config' };
84
+ }
85
+
86
+ try {
87
+ execSync(`echo '{}' | ${command}`, {
88
+ encoding: 'utf-8',
89
+ timeout: 10_000,
90
+ stdio: ['pipe', 'pipe', 'pipe'],
91
+ });
92
+ return {
93
+ ok: true,
94
+ summary: 'capture runs OK',
95
+ detail: `Ran: echo '{}' | ${command}\nResult: exit 0`,
96
+ };
97
+ } catch (err) {
98
+ const stderr = err.stderr?.trim() || err.message;
99
+ return {
100
+ ok: false,
101
+ summary: 'capture failed',
102
+ detail: `Ran: echo '{}' | ${command}\nExit code: ${err.status}\nError: ${stderr}`,
103
+ };
104
+ }
105
+ }
106
+
52
107
  function checkVersion() {
53
108
  const { version, commit } = getVersionInfo();
54
109
  return {
@@ -434,6 +489,9 @@ export default async function status() {
434
489
  }
435
490
  }
436
491
 
492
+ // 6b. Smoke-test the hook command
493
+ printLine('Capture test', checkCaptureRun(installedTools));
494
+
437
495
  // 7. Queue
438
496
  printLine('Queue', checkQueue());
439
497
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-lens",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "type": "module",
5
5
  "description": "Centralized session analytics for AI coding tools",
6
6
  "bin": {