From a093f8e8308b43aafbc4960b69bac798eda58389 Mon Sep 17 00:00:00 2001 From: shog86 Date: Thu, 19 Mar 2026 11:18:16 +0800 Subject: [PATCH] Add Trae IDE support - Add trae.js transformer with full metadata support (same as Claude Code) - Update build.js to include Trae in provider transformations - Update README.md with Trae installation instructions - Update DEVELOP.md with Trae transformer documentation Trae uses ~/.trae-cn/builtin_skills/ for skills installation. --- DEVELOP.md | 20 ++++++--- README.md | 9 +++++ scripts/build.js | 9 ++++- scripts/lib/transformers/index.js | 1 + scripts/lib/transformers/trae.js | 67 +++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 scripts/lib/transformers/trae.js diff --git a/DEVELOP.md b/DEVELOP.md index 16219237e..76ecd751d 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -9,7 +9,7 @@ This repository uses a **feature-rich source format** that transforms into provi ### Why This Approach? Different providers have different capabilities: -- **Claude Code, OpenCode**: Full metadata — args, user-invokable, allowed-tools, license, compatibility +- **Claude Code, OpenCode, Trae**: Full metadata — args, user-invokable, allowed-tools, license, compatibility - **Codex, Agents**: Args converted to `argument-hint` format - **Gemini**: Minimal frontmatter, `{{arg}}` placeholders become `{{args}}` - **Cursor, Kiro, Pi**: Basic frontmatter (name, description, license/compatibility) @@ -77,6 +77,7 @@ source/ → dist/ kiro/.kiro/skills/{name}/SKILL.md opencode/.opencode/skills/{name}/SKILL.md pi/.pi/skills/{name}/SKILL.md + trae/.trae-cn/builtin_skills/{name}/SKILL.md ``` ## Provider Transformations @@ -121,6 +122,12 @@ All providers output skills to `dist/{provider}/.{config}/skills/{name}/SKILL.md - Output: `dist/pi/.pi/skills/{name}/SKILL.md` - Frontmatter: name, description, license, compatibility, metadata +### Trae (Full Featured) +- Output: `dist/trae/.trae-cn/builtin_skills/{name}/SKILL.md` +- Frontmatter: name, description, user-invokable, args, license, compatibility, metadata, allowed-tools +- Same format as Claude Code +- Skills are installed to `~/.trae-cn/builtin_skills/` + ## Adding New Content ### 1. Create Source File @@ -138,7 +145,7 @@ Add frontmatter and content following the format above. bun run build ``` -This generates all 8 provider formats automatically. +This generates all 9 provider formats automatically. ### 3. Test @@ -159,7 +166,7 @@ The build system uses a modular architecture under `scripts/`: - `build.js` — Main orchestrator - `lib/utils.js` — Shared utilities (frontmatter parsing, file I/O, placeholder replacement) - `lib/zip.js` — ZIP bundle generation -- `lib/transformers/*.js` — One file per provider (cursor, claude-code, gemini, codex, agents, kiro, opencode, pi) +- `lib/transformers/*.js` — One file per provider (cursor, claude-code, gemini, codex, agents, kiro, opencode, pi, trae) ### Key Functions @@ -174,6 +181,7 @@ The build system uses a modular architecture under `scripts/`: - `transformKiro()`: Basic frontmatter with license/compatibility/metadata - `transformOpenCode()`: Full metadata (same as Claude Code) - `transformPi()`: Basic frontmatter with license/compatibility/metadata +- `transformTrae()`: Full metadata (same as Claude Code), outputs to `.trae-cn/builtin_skills/` ## Best Practices @@ -220,7 +228,8 @@ impeccable/ │ ├── agents/ │ ├── kiro/ │ ├── opencode/ -│ └── pi/ +│ ├── pi/ +│ └── trae/ ├── scripts/ │ ├── build.js # Main orchestrator │ └── lib/ @@ -234,7 +243,8 @@ impeccable/ │ ├── agents.js │ ├── kiro.js │ ├── opencode.js -│ └── pi.js +│ ├── pi.js +│ └── trae.js ├── tests/ # Bun test suite ├── package.json # ESM project config ├── README.md # User documentation diff --git a/README.md b/README.md index 37c942024..be1f48442 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,14 @@ cp -r dist/gemini/.gemini your-project/ cp -r dist/codex/.codex/* ~/.codex/ ``` +**Trae:** +```bash +# Global installation (recommended) +cp -r dist/trae/.trae-cn/builtin_skills/* ~/.trae-cn/builtin_skills/ +``` + +> **Note:** Trae uses `~/.trae-cn/builtin_skills/` for skills. After copying, restart Trae IDE to activate the skills. + ## Usage Once installed, use commands in your AI harness: @@ -155,6 +163,7 @@ Most commands accept an optional argument to focus on a specific area: - [Codex CLI](https://github.com/openai/codex) - [VS Code Copilot](https://code.visualstudio.com) - [Kiro](https://kiro.dev) +- [Trae](https://trae.ai) ## Contributing diff --git a/scripts/build.js b/scripts/build.js index 2e51691b6..6287c5a00 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -26,7 +26,8 @@ import { transformAgents, transformKiro, transformOpenCode, - transformPi + transformPi, + transformTrae } from './lib/transformers/index.js'; import { createAllZips } from './lib/zip.js'; import { execSync } from 'child_process'; @@ -149,7 +150,8 @@ function assembleUniversal(distDir, suffix = '') { { provider: 'agents', configDir: '.agents' }, { provider: 'kiro', configDir: '.kiro' }, { provider: 'opencode', configDir: '.opencode' }, - { provider: 'pi', configDir: '.pi' } + { provider: 'pi', configDir: '.pi' }, + { provider: 'trae', configDir: '.trae-cn' } ]; for (const { provider, configDir } of providerMappings) { @@ -177,6 +179,7 @@ This folder contains skills for all supported tools: .kiro/ → Kiro .opencode/ → OpenCode .pi/ → Pi + .trae-cn/ → Trae To install, copy the relevant folder(s) into your project root. These are hidden folders (dotfiles) — press Cmd+Shift+. in Finder to see them. @@ -349,6 +352,7 @@ async function build() { transformKiro(skills, DIST_DIR, patterns); transformOpenCode(skills, DIST_DIR, patterns); transformPi(skills, DIST_DIR, patterns); + transformTrae(skills, DIST_DIR, patterns); // Transform for each provider (prefixed with i-) const prefixOptions = { prefix: 'i-', outputSuffix: '-prefixed' }; @@ -360,6 +364,7 @@ async function build() { transformKiro(skills, DIST_DIR, patterns, prefixOptions); transformOpenCode(skills, DIST_DIR, patterns, prefixOptions); transformPi(skills, DIST_DIR, patterns, prefixOptions); + transformTrae(skills, DIST_DIR, patterns, prefixOptions); // Assemble universal directory (unprefixed and prefixed) assembleUniversal(DIST_DIR); diff --git a/scripts/lib/transformers/index.js b/scripts/lib/transformers/index.js index da00044f3..fe6c4650a 100644 --- a/scripts/lib/transformers/index.js +++ b/scripts/lib/transformers/index.js @@ -6,3 +6,4 @@ export { transformAgents } from './agents.js'; export { transformKiro } from './kiro.js'; export { transformOpenCode } from "./opencode.js"; export { transformPi } from './pi.js'; +export { transformTrae } from './trae.js'; diff --git a/scripts/lib/transformers/trae.js b/scripts/lib/transformers/trae.js new file mode 100644 index 000000000..e997e4396 --- /dev/null +++ b/scripts/lib/transformers/trae.js @@ -0,0 +1,67 @@ +import path from 'path'; +import { cleanDir, ensureDir, writeFile, generateYamlFrontmatter, replacePlaceholders, prefixSkillReferences } from '../utils.js'; + +/** + * Trae Transformer (Skills Only) + * + * All skills output to .trae-cn/builtin_skills/{name}/SKILL.md + * Trae uses a similar format to Claude Code with full metadata support. + * + * @param {Array} skills - All skills (including user-invokable ones) + * @param {string} distDir - Distribution output directory + * @param {Object} patterns - Design patterns data (unused, kept for interface consistency) + * @param {Object} options - Optional settings + * @param {string} options.prefix - Prefix to add to user-invokable skill names (e.g., 'i-') + * @param {string} options.outputSuffix - Suffix for output directory (e.g., '-prefixed') + */ +export function transformTrae(skills, distDir, patterns = null, options = {}) { + const { prefix = '', outputSuffix = '' } = options; + const traeDir = path.join(distDir, `trae${outputSuffix}`); + const skillsDir = path.join(traeDir, '.trae-cn/builtin_skills'); + + cleanDir(traeDir); + ensureDir(skillsDir); + + const allSkillNames = skills.map(s => s.name); + const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`); + let refCount = 0; + for (const skill of skills) { + const skillName = `${prefix}${skill.name}`; + const skillDir = path.join(skillsDir, skillName); + + const frontmatterObj = { + name: skillName, + description: skill.description, + }; + + if (skill.userInvokable) frontmatterObj['user-invokable'] = true; + if (skill.args && skill.args.length > 0) frontmatterObj.args = skill.args; + if (skill.license) frontmatterObj.license = skill.license; + if (skill.compatibility) frontmatterObj.compatibility = skill.compatibility; + if (skill.metadata) frontmatterObj.metadata = skill.metadata; + if (skill.allowedTools) frontmatterObj['allowed-tools'] = skill.allowedTools; + + const frontmatter = generateYamlFrontmatter(frontmatterObj); + let skillBody = replacePlaceholders(skill.body, 'trae', commandNames); + if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames); + const content = `${frontmatter}\n\n${skillBody}`; + const outputPath = path.join(skillDir, 'SKILL.md'); + writeFile(outputPath, content); + + if (skill.references && skill.references.length > 0) { + const refDir = path.join(skillDir, 'reference'); + ensureDir(refDir); + for (const ref of skill.references) { + const refOutputPath = path.join(refDir, `${ref.name}.md`); + const refContent = replacePlaceholders(ref.content, 'trae'); + writeFile(refOutputPath, refContent); + refCount++; + } + } + } + + const userInvokableCount = skills.filter(s => s.userInvokable).length; + const refInfo = refCount > 0 ? ` (${refCount} reference files)` : ''; + const prefixInfo = prefix ? ` [${prefix}prefixed]` : ''; + console.log(`✓ Trae${prefixInfo}: ${skills.length} skills (${userInvokableCount} user-invokable)${refInfo}`); +}