ai-lens 0.8.34 → 0.8.35

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
- 5ed015e
1
+ b3f67d5
package/cli/hooks.js CHANGED
@@ -214,6 +214,24 @@ export const TOOL_CONFIGS = [
214
214
  },
215
215
  ];
216
216
 
217
+ /**
218
+ * Cursor tool config with hooks in project's .cursor/ instead of ~/.cursor/.
219
+ * Use for init (--project-hooks) and remove (when project has .cursor/hooks.json).
220
+ * @param {string} projectRoot - Absolute path to project root (e.g. process.cwd()).
221
+ * @param {string} [label] - Display name (default: 'Cursor (project)').
222
+ * @returns {{ name: string, dirPath: string, configPath: string, hookDefs: object, topLevelFields: object }}
223
+ */
224
+ export function getCursorToolConfig(projectRoot, label = 'Cursor (project)') {
225
+ const base = TOOL_CONFIGS.find(t => t.name === 'Cursor');
226
+ if (!base) return null;
227
+ return {
228
+ ...base,
229
+ name: label,
230
+ dirPath: join(projectRoot, '.cursor'),
231
+ configPath: join(projectRoot, '.cursor', 'hooks.json'),
232
+ };
233
+ }
234
+
217
235
  // ---------------------------------------------------------------------------
218
236
  // AI Lens hook detection
219
237
  // ---------------------------------------------------------------------------
package/cli/init.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  import { getGitIdentity } from '../client/config.js';
14
14
  import { migrateIfNeeded } from '../client/sender.js';
15
15
  import {
16
- CAPTURE_PATH, detectInstalledTools,
16
+ CAPTURE_PATH, detectInstalledTools, getCursorToolConfig,
17
17
  analyzeToolHooks, buildMergedConfig, writeHooksConfig, describePlan,
18
18
  installClientFiles, readLensConfig, saveLensConfig, getVersionInfo,
19
19
  cleanupLegacyHooks, cleanupEmptyMcpJson, addCursorMcp, removeCursorMcp,
@@ -298,6 +298,9 @@ function getInitArgs() {
298
298
  case '--no-mcp':
299
299
  flags.noMcp = true;
300
300
  break;
301
+ case '--project-hooks':
302
+ flags.projectHooks = true;
303
+ break;
301
304
  case '--mcp-scope':
302
305
  if (i + 1 < args.length) flags.mcpScope = args[++i];
303
306
  else process.stderr.write('Warning: --mcp-scope requires a value\n');
@@ -306,7 +309,7 @@ function getInitArgs() {
306
309
  const a = args[i];
307
310
  if (a.startsWith('-')) {
308
311
  process.stderr.write(`Warning: unknown flag "${a}" — did you mean --${a.replace(/^-+/, '')}?\n`);
309
- } else if (['server', 'projects', 'yes', 'no-mcp', 'mcp-scope'].includes(a)) {
312
+ } else if (['server', 'projects', 'yes', 'no-mcp', 'project-hooks', 'mcp-scope'].includes(a)) {
310
313
  process.stderr.write(`Warning: unexpected argument "${a}" — did you mean --${a}?\n`);
311
314
  }
312
315
  }
@@ -329,7 +332,18 @@ export default async function init() {
329
332
 
330
333
  // Detect installed tools
331
334
  heading('Detecting installed AI tools...');
332
- const tools = detectInstalledTools();
335
+ let tools = detectInstalledTools();
336
+
337
+ // When --project-hooks: put Cursor hooks in project's .cursor/ instead of ~/.cursor/
338
+ if (flags.projectHooks) {
339
+ const projectRoot = resolve(process.cwd());
340
+ const cursorProject = getCursorToolConfig(projectRoot);
341
+ if (cursorProject) {
342
+ tools = tools.filter(t => t.name !== 'Cursor');
343
+ tools.push(cursorProject);
344
+ info(' Cursor hooks will be written to this project (.cursor/hooks.json).');
345
+ }
346
+ }
333
347
 
334
348
  if (tools.length === 0) {
335
349
  warn('No supported AI tools detected.');
package/cli/remove.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { createInterface } from 'node:readline';
2
2
  import { unlinkSync, existsSync, rmSync, readdirSync } from 'node:fs';
3
3
  import { execSync } from 'node:child_process';
4
- import { join } from 'node:path';
4
+ import { join, resolve } from 'node:path';
5
5
  import { homedir } from 'node:os';
6
6
  import {
7
7
  initLogger, info, success, warn, error,
8
8
  heading, detail, blank, getLogPath,
9
9
  } from './logger.js';
10
10
  import {
11
- detectInstalledTools, analyzeToolHooks,
11
+ detectInstalledTools, getCursorToolConfig, analyzeToolHooks,
12
12
  buildStrippedConfig, writeHooksConfig, removeClientFiles, getVersionInfo,
13
13
  cleanupLegacyHooks, cleanupEmptyMcpJson, removeCursorMcp,
14
14
  } from './hooks.js';
@@ -31,9 +31,14 @@ export default async function remove() {
31
31
  heading(`AI Lens — Remove v${version} (${commit})`);
32
32
  blank();
33
33
 
34
- // Detect tools with AI Lens hooks
34
+ // Detect tools with AI Lens hooks (global + project .cursor/hooks.json if present)
35
35
  heading('Scanning for AI Lens hooks...');
36
- const tools = detectInstalledTools();
36
+ let tools = detectInstalledTools();
37
+ const projectCursor = getCursorToolConfig(resolve(process.cwd()), 'Cursor (project)');
38
+ if (projectCursor && existsSync(projectCursor.configPath)) {
39
+ tools = tools.filter(t => t.name !== 'Cursor' || t.configPath !== projectCursor.configPath);
40
+ tools.push(projectCursor);
41
+ }
37
42
  const withHooks = [];
38
43
 
39
44
  for (const tool of tools) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-lens",
3
- "version": "0.8.34",
3
+ "version": "0.8.35",
4
4
  "type": "module",
5
5
  "description": "Centralized session analytics for AI coding tools",
6
6
  "bin": {