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.
- package/bin/install.js +157 -18
- 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
|
-
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.
|
|
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
|
-
|
|
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.
|
|
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",
|