Skip to content

Commit 528044a

Browse files
committed
feat: 更新 postinstall 脚本以支持技能链接和文件链接
1 parent 7cf493a commit 528044a

2 files changed

Lines changed: 96 additions & 1 deletion

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"lint:eslint": "eslint . --cache --fix",
1717
"lint:stylelint": "stylelint \"{apps,packages}/**/*.{css,scss,vue}\" --cache --fix",
1818
"preinstall": "npx only-allow pnpm",
19-
"postinstall": "simple-git-hooks",
19+
"postinstall": "simple-git-hooks && tsx scripts/postinstall.ts",
2020
"taze": "taze minor -wIr",
2121
"commit": "git cz",
2222
"release": "bumpp"

scripts/postinstall.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'node:fs'
4+
import path from 'node:path'
5+
import process from 'node:process'
6+
import { fileURLToPath } from 'node:url'
7+
8+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
9+
const rootDir = path.resolve(__dirname, '..')
10+
const isWindows = process.platform === 'win32'
11+
12+
const sourceDir = path.resolve(rootDir, '.agents/skills')
13+
const targetDirs = [
14+
'.claude/skills',
15+
// '.other-agent/skills',
16+
]
17+
18+
// 根目录文件链接:[source, link]
19+
const fileLinks = [
20+
['AGENTS.md', 'CLAUDE.md'],
21+
]
22+
23+
function syncSkillLinks() {
24+
if (!fs.existsSync(sourceDir)) {
25+
return
26+
}
27+
28+
const skills = fs.readdirSync(sourceDir, { withFileTypes: true })
29+
.filter(entry => entry.isDirectory())
30+
.map(entry => entry.name)
31+
32+
for (const targetDir of targetDirs) {
33+
const absTargetDir = path.resolve(rootDir, targetDir)
34+
fs.mkdirSync(absTargetDir, { recursive: true })
35+
36+
let created = 0
37+
38+
for (const skill of skills) {
39+
const linkPath = path.join(absTargetDir, skill)
40+
const skillSourcePath = path.join(sourceDir, skill)
41+
42+
// 已存在则先删除(兼容 symlink / junction / 普通目录)
43+
try {
44+
fs.lstatSync(linkPath)
45+
fs.rmSync(linkPath, { recursive: true, force: true })
46+
}
47+
catch {
48+
// 不存在,正常继续创建
49+
}
50+
51+
if (isWindows) {
52+
// Windows 使用 junction(目录联接),无需管理员权限
53+
fs.symlinkSync(skillSourcePath, linkPath, 'junction')
54+
}
55+
else {
56+
// Mac/Linux 使用相对路径软链接
57+
const relativePath = path.relative(absTargetDir, skillSourcePath)
58+
fs.symlinkSync(relativePath, linkPath)
59+
}
60+
61+
created++
62+
}
63+
64+
if (created > 0) {
65+
console.log(`[postinstall] Linked ${created} skill(s) to ${targetDir}/`)
66+
}
67+
}
68+
}
69+
70+
function syncFileLinks() {
71+
for (const [source, link] of fileLinks) {
72+
const sourcePath = path.resolve(rootDir, source)
73+
const linkPath = path.resolve(rootDir, link)
74+
75+
if (!fs.existsSync(sourcePath)) {
76+
console.warn(`[postinstall] Source file not found, skipping: ${source}`)
77+
continue
78+
}
79+
80+
// 已存在则先删除
81+
try {
82+
fs.lstatSync(linkPath)
83+
fs.rmSync(linkPath, { force: true })
84+
}
85+
catch {
86+
// 不存在,正常继续创建
87+
}
88+
const relativePath = isWindows ? sourcePath : path.relative(rootDir, sourcePath)
89+
fs.symlinkSync(relativePath, linkPath, 'file')
90+
console.log(`[postinstall] Linked file: ${link} -> ${source}`)
91+
}
92+
}
93+
94+
syncSkillLinks()
95+
syncFileLinks()

0 commit comments

Comments
 (0)