11#!/usr/bin/env node
22
3- import { existsSync , mkdirSync , cpSync , readdirSync , readFileSync } from 'fs' ;
3+ import { existsSync , mkdirSync , cpSync , readdirSync , readFileSync , writeFileSync } from 'fs' ;
44import { resolve , dirname } from 'path' ;
55import { fileURLToPath } from 'url' ;
66
@@ -16,7 +16,7 @@ const TARGETS = [
1616 { name : 'Codex CLI' , dir : '.codex/skills' , detect : '.codex' } ,
1717 { name : 'Kiro' , dir : '.kiro/steering' , detect : '.kiro' } ,
1818 { name : 'DeerFlow' , dir : 'skills/custom' , detect : 'deer_flow' } ,
19- { name : 'Trae' , dir : '.trae/rules' , detect : '.trae' } ,
19+ { name : 'Trae' , dir : '.trae/skills' , detect : '.trae' } ,
2020 { name : 'Antigravity' , dir : '.antigravity/skills' , detect : '.antigravity' } ,
2121 { name : 'VS Code' , dir : '.github/superpowers' , detect : '.github/copilot-instructions.md' } ,
2222 { name : 'OpenClaw' , dir : 'skills' , detect : '.openclaw' } ,
@@ -32,6 +32,67 @@ function countDirs(dir) {
3232 return readdirSync ( dir , { withFileTypes : true } ) . filter ( e => e . isDirectory ( ) ) . length ;
3333}
3434
35+ function generateTraeBootstrapRule ( projectDir ) {
36+ const rulesDir = resolve ( projectDir , '.trae' , 'rules' ) ;
37+ mkdirSync ( rulesDir , { recursive : true } ) ;
38+
39+ // 扫描已安装的 skills,读取 name 和 description
40+ const skillsDir = resolve ( projectDir , '.trae' , 'skills' ) ;
41+ const skillEntries = [ ] ;
42+ if ( existsSync ( skillsDir ) ) {
43+ for ( const entry of readdirSync ( skillsDir , { withFileTypes : true } ) ) {
44+ if ( ! entry . isDirectory ( ) ) continue ;
45+ const skillFile = resolve ( skillsDir , entry . name , 'SKILL.md' ) ;
46+ if ( ! existsSync ( skillFile ) ) continue ;
47+ const content = readFileSync ( skillFile , 'utf8' ) ;
48+ const fmMatch = content . match ( / ^ - - - \s * \n ( [ \s \S ] * ?) \n - - - / ) ;
49+ if ( ! fmMatch ) continue ;
50+ const nameMatch = fmMatch [ 1 ] . match ( / ^ n a m e : \s * ( .+ ) $ / m) ;
51+ const descMatch = fmMatch [ 1 ] . match ( / ^ d e s c r i p t i o n : \s * [ " ' ] ? ( .+ ?) [ " ' ] ? \s * $ / m) ;
52+ if ( nameMatch ) {
53+ skillEntries . push ( {
54+ name : nameMatch [ 1 ] . trim ( ) ,
55+ desc : descMatch ? descMatch [ 1 ] . trim ( ) : '' ,
56+ } ) ;
57+ }
58+ }
59+ }
60+
61+ const skillTable = skillEntries . map ( s => `| ${ s . name } | ${ s . desc } |` ) . join ( '\n' ) ;
62+
63+ const rule = `---
64+ alwaysApply: true
65+ ---
66+
67+ # Superpowers-ZH 中文增强版
68+
69+ 你已加载 superpowers-zh 技能框架(${ skillEntries . length } 个 skills)。
70+
71+ ## 核心规则
72+
73+ 1. **收到任务时,先检查是否有匹配的 skill** — 哪怕只有 1% 的可能性也要检查
74+ 2. **设计先于编码** — 收到功能需求时,先用 brainstorming skill 做需求分析
75+ 3. **测试先于实现** — 写代码前先写测试(TDD)
76+ 4. **验证先于完成** — 声称完成前必须运行验证命令
77+
78+ ## 可用 Skills
79+
80+ Skills 位于 \`.trae/skills/\` 目录,每个 skill 有独立的 \`SKILL.md\` 文件。
81+
82+ | Skill | 触发条件 |
83+ |-------|---------|
84+ ${ skillTable }
85+
86+ ## 如何使用
87+
88+ 当任务匹配某个 skill 的触发条件时,读取对应的 \`.trae/skills/<skill-name>/SKILL.md\` 并严格遵循其流程。
89+ ` ;
90+
91+ const rulePath = resolve ( rulesDir , 'superpowers-zh.md' ) ;
92+ writeFileSync ( rulePath , rule , 'utf8' ) ;
93+ console . log ( ` ✅ Trae: bootstrap rule -> ${ rulePath } ` ) ;
94+ }
95+
3596function showHelp ( ) {
3697 console . log ( `
3798 superpowers-zh v${ PKG . version } — AI 编程超能力中文版
@@ -78,6 +139,10 @@ function install() {
78139 console . log ( ` ✅ ${ target . name } : ${ count } 个 skills -> ${ dest } ` ) ;
79140 installed ++ ;
80141
142+ if ( target . name === 'Trae' ) {
143+ generateTraeBootstrapRule ( PROJECT_DIR ) ;
144+ }
145+
81146 if ( target . name === 'Claude Code' && existsSync ( AGENTS_SRC ) ) {
82147 const agentsDest = resolve ( PROJECT_DIR , '.claude' , 'agents' ) ;
83148 mkdirSync ( agentsDest , { recursive : true } ) ;
0 commit comments