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 +1 -1
- package/cli/hooks.js +18 -0
- package/cli/init.js +17 -3
- package/cli/remove.js +9 -4
- package/package.json +1 -1
package/.commithash
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|