vunor 0.1.0 → 0.1.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/package.json +3 -2
- package/scripts/setup-skills.js +43 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vunor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"bin": {
|
|
5
5
|
"setup-skills": "./scripts/setup-skills.js"
|
|
6
6
|
},
|
|
@@ -184,7 +184,8 @@
|
|
|
184
184
|
"type-check": "vue-tsc --build --force",
|
|
185
185
|
"test": "vitest run && playwright test",
|
|
186
186
|
"test:e2e": "playwright test",
|
|
187
|
-
"setup-skills": "node ./scripts/setup-skills.js"
|
|
187
|
+
"setup-skills": "node ./scripts/setup-skills.js",
|
|
188
|
+
"postinstall": "node ./scripts/setup-skills.js --postinstall"
|
|
188
189
|
},
|
|
189
190
|
"dependencies": {
|
|
190
191
|
"@internationalized/date": "^3.11.0",
|
package/scripts/setup-skills.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
/* prettier-ignore */
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import os from 'os'
|
|
6
|
+
import { fileURLToPath } from 'url'
|
|
3
7
|
|
|
4
|
-
const
|
|
5
|
-
const path = require('path')
|
|
6
|
-
const os = require('os')
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
7
9
|
|
|
8
10
|
const SKILL_NAME = 'vunor'
|
|
9
|
-
|
|
10
|
-
// Source skill folder ships inside this package
|
|
11
11
|
const SKILL_SRC = path.join(__dirname, '..', 'skills', SKILL_NAME)
|
|
12
12
|
|
|
13
13
|
if (!fs.existsSync(SKILL_SRC)) {
|
|
@@ -16,54 +16,63 @@ if (!fs.existsSync(SKILL_SRC)) {
|
|
|
16
16
|
process.exit(1)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
// Known agent skill directories (project-relative and global)
|
|
20
19
|
const AGENTS = {
|
|
21
|
-
'Claude Code':
|
|
22
|
-
'Cursor':
|
|
23
|
-
'Windsurf':
|
|
24
|
-
'Codex':
|
|
25
|
-
'OpenCode':
|
|
20
|
+
'Claude Code': { dir: '.claude/skills', global: path.join(os.homedir(), '.claude', 'skills') },
|
|
21
|
+
'Cursor': { dir: '.cursor/skills', global: path.join(os.homedir(), '.cursor', 'skills') },
|
|
22
|
+
'Windsurf': { dir: '.windsurf/skills', global: path.join(os.homedir(), '.windsurf', 'skills') },
|
|
23
|
+
'Codex': { dir: '.codex/skills', global: path.join(os.homedir(), '.codex', 'skills') },
|
|
24
|
+
'OpenCode': { dir: '.opencode/skills', global: path.join(os.homedir(), '.opencode', 'skills') },
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
const args = process.argv.slice(2)
|
|
29
28
|
const isGlobal = args.includes('--global') || args.includes('-g')
|
|
30
|
-
|
|
31
|
-
let installed = 0
|
|
32
|
-
|
|
29
|
+
const isPostinstall = args.includes('--postinstall')
|
|
30
|
+
let installed = 0, skipped = 0
|
|
31
|
+
const installedDirs = []
|
|
33
32
|
|
|
34
33
|
for (const [agentName, cfg] of Object.entries(AGENTS)) {
|
|
35
34
|
const targetBase = isGlobal ? cfg.global : path.join(process.cwd(), cfg.dir)
|
|
36
|
-
const
|
|
35
|
+
const agentRootDir = path.dirname(cfg.global) // Check if the agent has ever been installed globally
|
|
37
36
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const agentHome = path.dirname(cfg.global)
|
|
42
|
-
if (!fs.existsSync(agentHome)) {
|
|
43
|
-
skipped++
|
|
44
|
-
continue
|
|
45
|
-
}
|
|
37
|
+
// In postinstall mode: silently skip agents that aren't set up globally
|
|
38
|
+
if (isPostinstall || isGlobal) {
|
|
39
|
+
if (!fs.existsSync(agentRootDir)) { skipped++; continue }
|
|
46
40
|
}
|
|
47
41
|
|
|
42
|
+
const dest = path.join(targetBase, SKILL_NAME)
|
|
48
43
|
try {
|
|
49
44
|
fs.mkdirSync(dest, { recursive: true })
|
|
50
45
|
fs.cpSync(SKILL_SRC, dest, { recursive: true })
|
|
51
|
-
console.log(
|
|
46
|
+
console.log(`✅ ${agentName}: installed to ${dest}`)
|
|
52
47
|
installed++
|
|
48
|
+
if (!isGlobal) installedDirs.push(cfg.dir + '/' + SKILL_NAME)
|
|
53
49
|
} catch (err) {
|
|
54
|
-
console.warn(
|
|
50
|
+
console.warn(`⚠️ ${agentName}: failed — ${err.message}`)
|
|
55
51
|
}
|
|
56
52
|
}
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
// Add locally-installed skill dirs to .gitignore
|
|
55
|
+
if (!isGlobal && installedDirs.length > 0) {
|
|
56
|
+
const gitignorePath = path.join(process.cwd(), '.gitignore')
|
|
57
|
+
let gitignoreContent = ''
|
|
58
|
+
try { gitignoreContent = fs.readFileSync(gitignorePath, 'utf8') } catch {}
|
|
59
|
+
const linesToAdd = installedDirs.filter(d => !gitignoreContent.includes(d))
|
|
60
|
+
if (linesToAdd.length > 0) {
|
|
61
|
+
const hasHeader = gitignoreContent.includes('# AI agent skills')
|
|
62
|
+
const block = (gitignoreContent && !gitignoreContent.endsWith('\n') ? '\n' : '')
|
|
63
|
+
+ (hasHeader ? '' : '\n# AI agent skills (auto-generated by setup-skills)\n')
|
|
64
|
+
+ linesToAdd.join('\n') + '\n'
|
|
65
|
+
fs.appendFileSync(gitignorePath, block)
|
|
66
|
+
console.log(`📝 Added ${linesToAdd.length} entries to .gitignore`)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (installed === 0 && isPostinstall) {
|
|
71
|
+
// Silence is fine — no agents present, nothing to do
|
|
72
|
+
} else if (installed === 0 && skipped === Object.keys(AGENTS).length) {
|
|
73
|
+
console.log('No agent directories detected. Try --global or run without it for project-local install.')
|
|
61
74
|
} else if (installed === 0) {
|
|
62
75
|
console.log('Nothing installed. Run without --global to install project-locally.')
|
|
63
76
|
} else {
|
|
64
|
-
console.log(`\n
|
|
65
|
-
if (!isGlobal) {
|
|
66
|
-
console.log('Tip: commit the generated .*/skills/ directories to share skills with your team.')
|
|
67
|
-
console.log(' Or add them to .gitignore if you prefer each developer to opt in.')
|
|
68
|
-
}
|
|
77
|
+
console.log(`\n✨ Done! Restart your AI agent to pick up the "${SKILL_NAME}" skill.`)
|
|
69
78
|
}
|