ani-skills 1.0.2 → 1.0.3

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 (2) hide show
  1. package/bin/install.js +157 -18
  2. package/package.json +3 -2
package/bin/install.js CHANGED
@@ -28,6 +28,13 @@ A repository of 444 AI agent skills and prompts.
28
28
  `);
29
29
  }
30
30
 
31
+ function shouldLink() {
32
+ const isGit = fs.existsSync(path.join(projectRoot, '.git'));
33
+ const isNodeModules = projectRoot.includes('node_modules');
34
+ const isNpx = projectRoot.includes('npm-cache') || projectRoot.includes('_npx');
35
+ return isGit && !isNodeModules && !isNpx;
36
+ }
37
+
31
38
  function copyRecursiveSync(src, dest) {
32
39
  const exists = fs.existsSync(src);
33
40
  const stats = exists && fs.statSync(src);
@@ -38,42 +45,70 @@ function copyRecursiveSync(src, dest) {
38
45
  copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
39
46
  });
40
47
  } else {
41
- fs.copyFileSync(src, dest);
48
+ try {
49
+ if (fs.existsSync(dest)) {
50
+ fs.unlinkSync(dest);
51
+ }
52
+ fs.copyFileSync(src, dest);
53
+ } catch (e) {
54
+ try {
55
+ fs.chmodSync(dest, 0o666);
56
+ if (fs.existsSync(dest)) {
57
+ fs.unlinkSync(dest);
58
+ }
59
+ fs.copyFileSync(src, dest);
60
+ } catch (err) {
61
+ console.error(`[Warning] Failed to copy ${src} to ${dest}: ${err.message}`);
62
+ }
63
+ }
42
64
  }
43
65
  }
44
66
 
45
67
  function linkOrCopy(src, dest) {
46
- if (fs.existsSync(dest)) {
47
- // If it's a symlink or directory, remove it first
68
+ let pathExists = false;
69
+ let isSymlinkOrFile = false;
70
+
71
+ try {
72
+ const stat = fs.lstatSync(dest);
73
+ pathExists = true;
74
+ isSymlinkOrFile = stat.isSymbolicLink() || stat.isFile();
75
+ } catch (e) {
76
+ // Path does not exist at all
77
+ }
78
+
79
+ if (pathExists) {
48
80
  try {
49
- const stat = fs.lstatSync(dest);
50
- if (stat.isSymbolicLink() || stat.isFile()) {
81
+ if (isSymlinkOrFile) {
51
82
  fs.unlinkSync(dest);
52
83
  } else {
53
84
  fs.rmSync(dest, { recursive: true, force: true });
54
85
  }
55
86
  } catch (e) {
56
- console.log(`Note: overwriting existing target ${dest}`);
87
+ console.log(`Note: overwriting existing target ${dest} failed: ${e.message}`);
57
88
  }
58
89
  }
59
90
 
60
91
  // Create parent directories if they don't exist
61
92
  fs.mkdirSync(path.dirname(dest), { recursive: true });
62
93
 
63
- try {
64
- // Try junction link on Windows, symlink on other platforms
65
- const type = process.platform === 'win32' ? 'junction' : 'dir';
66
- fs.symlinkSync(src, dest, type);
67
- console.log(`[Success] Symlinked ${src} -> ${dest}`);
68
- } catch (e) {
69
- console.log(`[Permission Warning] Symlinking failed (requires administrator on Windows). Falling back to direct copying...`);
94
+ if (shouldLink()) {
70
95
  try {
71
- copyRecursiveSync(src, dest);
72
- console.log(`[Success] Copied ${src} -> ${dest}`);
73
- } catch (copyErr) {
74
- console.error(`[Error] Copy failed: ${copyErr.message}`);
96
+ // Try junction link on Windows, symlink on other platforms
97
+ const type = process.platform === 'win32' ? 'junction' : 'dir';
98
+ fs.symlinkSync(src, dest, type);
99
+ console.log(`[Success] Symlinked ${src} -> ${dest}`);
100
+ return;
101
+ } catch (e) {
102
+ console.log(`[Permission Warning] Symlinking failed. Falling back to direct copying...`);
75
103
  }
76
104
  }
105
+
106
+ try {
107
+ copyRecursiveSync(src, dest);
108
+ console.log(`[Success] Copied ${src} -> ${dest}`);
109
+ } catch (copyErr) {
110
+ console.error(`[Error] Copy failed: ${copyErr.message}`);
111
+ }
77
112
  }
78
113
 
79
114
  function configureEnvironment(envName, skillsDest, commandsDests) {
@@ -267,5 +302,109 @@ function mainMenu() {
267
302
  });
268
303
  }
269
304
 
305
+ function runAutoInstall() {
306
+ console.log('Running Antigravity Skills Library Setup in Auto/Non-Interactive Mode...');
307
+ const homeDir = process.env.HOME || process.env.USERPROFILE || os.homedir();
308
+
309
+ const targets = [
310
+ {
311
+ name: 'Antigravity IDE',
312
+ skillsDest: path.join(homeDir, '.gemini', 'config', 'skills'),
313
+ commandsDests: [path.join(homeDir, '.gemini', 'commands'), path.join(homeDir, '.gemini', 'config', 'commands')],
314
+ trigger: path.join(homeDir, '.gemini', 'config')
315
+ },
316
+ {
317
+ name: 'Antigravity 2.0',
318
+ skillsDest: path.join(homeDir, '.gemini', 'antigravity', 'skills'),
319
+ commandsDests: [path.join(homeDir, '.gemini', 'commands'), path.join(homeDir, '.gemini', 'antigravity', 'commands')],
320
+ trigger: path.join(homeDir, '.gemini', 'antigravity')
321
+ },
322
+ {
323
+ name: 'Claude Code CLI',
324
+ skillsDest: path.join(homeDir, '.claude', 'skills'),
325
+ commandsDests: null,
326
+ trigger: path.join(homeDir, '.claude')
327
+ },
328
+ {
329
+ name: 'Trae',
330
+ skillsDest: path.join(homeDir, '.trae', 'skills'),
331
+ commandsDests: null,
332
+ trigger: path.join(homeDir, '.trae')
333
+ },
334
+ {
335
+ name: 'Cursor',
336
+ skillsDest: path.join(homeDir, '.cursor', 'skills'),
337
+ commandsDests: null,
338
+ trigger: path.join(homeDir, '.cursor')
339
+ },
340
+ {
341
+ name: 'Kiro',
342
+ skillsDest: path.join(homeDir, '.kiro', 'skills'),
343
+ commandsDests: null,
344
+ trigger: path.join(homeDir, '.kiro')
345
+ },
346
+ {
347
+ name: 'Qoderworker',
348
+ skillsDest: path.join(homeDir, '.qoderwork', 'skills'),
349
+ commandsDests: null,
350
+ trigger: path.join(homeDir, '.qoderwork')
351
+ },
352
+ {
353
+ name: 'CodeBuddy',
354
+ skillsDest: path.join(homeDir, '.codebuddy', 'skills'),
355
+ commandsDests: null,
356
+ trigger: path.join(homeDir, '.codebuddy')
357
+ },
358
+ {
359
+ name: 'Cline',
360
+ skillsDest: path.join(homeDir, '.cline', 'skills'),
361
+ commandsDests: null,
362
+ trigger: path.join(homeDir, '.cline')
363
+ }
364
+ ];
365
+
366
+ let configuredAny = false;
367
+
368
+ targets.forEach(target => {
369
+ if (fs.existsSync(target.trigger)) {
370
+ console.log(`\nDetected environment: ${target.name}. Configuring targets...`);
371
+ try {
372
+ // Copy skills
373
+ linkOrCopy(skillsSrc, target.skillsDest);
374
+
375
+ // Copy commands
376
+ if (target.commandsDests) {
377
+ const geminiConfSrc = path.join(projectRoot, '.gemini', 'commands');
378
+ const dests = Array.isArray(target.commandsDests) ? target.commandsDests : [target.commandsDests];
379
+ dests.forEach(dest => {
380
+ linkOrCopy(geminiConfSrc, dest);
381
+ });
382
+ }
383
+ console.log(`[Success] Configured ${target.name} skills and commands.`);
384
+ configuredAny = true;
385
+ } catch (err) {
386
+ console.error(`[Error] Failed configuring ${target.name}: ${err.message}`);
387
+ }
388
+ }
389
+ });
390
+
391
+ if (!configuredAny) {
392
+ console.log('\nNo standard AI environment directories detected (like .gemini, .cursor, .claude, etc.).');
393
+ console.log('Skipping auto configuration. To run interactively, run the script in a TTY terminal.');
394
+ } else {
395
+ console.log('\nAuto configuration completed successfully.');
396
+ }
397
+
398
+ rl.close();
399
+ process.exit(0);
400
+ }
401
+
270
402
  // Start execution
271
- mainMenu();
403
+ const args = process.argv.slice(2);
404
+ const isAuto = args.includes('--auto') || args.includes('--yes') || args.includes('-y') || !process.stdout.isTTY;
405
+
406
+ if (isAuto) {
407
+ runAutoInstall();
408
+ } else {
409
+ mainMenu();
410
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ani-skills",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "ani-skills is a professional AI Agent Skills library for Cursor, Claude Code, Windsurf, Trae, Cline, and Antigravity IDE, specializing in creative frontend GSAP/ScrollTrigger/Lenis animations, system planning, browser testing, and DSA workflows.",
5
5
  "main": "skills_index.json",
6
6
  "bin": {
@@ -8,7 +8,8 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build:index": "python scripts/update_skills_index.py",
11
- "lint:skills": "python scripts/verify_library.py"
11
+ "lint:skills": "python scripts/verify_library.py",
12
+ "postinstall": "node bin/install.js --auto"
12
13
  },
13
14
  "keywords": [
14
15
  "skills",