@neyugn/agent-kits 0.2.8 โ 0.3.1
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/README.md +16 -16
- package/README.vi.md +12 -14
- package/README.zh.md +12 -14
- package/dist/cli.js +665 -88
- package/kits/coder/rules/CURSOR.md +16 -13
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
- ๐ **Workflows** โ Slash commands for common tasks
|
|
41
41
|
- ๐ **Smart Filtering** โ Auto-detect techstack and optimize loaded skills
|
|
42
42
|
|
|
43
|
-
Works with **any AI tool** โ Claude, Gemini, Codex, Cursor, and more.
|
|
43
|
+
Works with **any AI tool** โ Claude, Gemini, Codex, Cursor, OpenCode, and more.
|
|
44
44
|
|
|
45
45
|
<br/>
|
|
46
46
|
|
|
@@ -68,7 +68,7 @@ npx @neyugn/agent-kits
|
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
```
|
|
71
|
-
|
|
71
|
+
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
|
|
72
72
|
โ โ
|
|
73
73
|
โ _ ____ _____ _ _ _____ _ __ ___ _____ ____ โ
|
|
74
74
|
โ / \ / ___|| ____|| \ | ||_ _| | |/ /|_ _||_ _|/ ___| โ
|
|
@@ -78,15 +78,13 @@ npx @neyugn/agent-kits
|
|
|
78
78
|
โ โ
|
|
79
79
|
โ โก The Universal AI Agent Toolkit โก โ
|
|
80
80
|
โ โ
|
|
81
|
-
|
|
81
|
+
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
|
|
82
82
|
|
|
83
83
|
SETUP WIZARD
|
|
84
84
|
|
|
85
85
|
โ ๐ค Which AI assistant are you using?
|
|
86
|
-
โ
|
|
87
|
-
โ โ Gemini CLI (.gemini/)
|
|
86
|
+
โ โ Antigravity (.agent/)
|
|
88
87
|
โ โ Cursor (.cursor/)
|
|
89
|
-
โ โ Custom...
|
|
90
88
|
|
|
91
89
|
โ ๐ Where should we install?
|
|
92
90
|
โ โ Workspace (Project)
|
|
@@ -108,6 +106,7 @@ npx @neyugn/agent-kits
|
|
|
108
106
|
| Gemini CLI | `~/.gemini/` | `.gemini/` |
|
|
109
107
|
| Codex CLI | `~/.codex/` | `.codex/` |
|
|
110
108
|
| Antigravity | `~/.agent/` | `.agent/` |
|
|
109
|
+
| OpenCode | `~/.config/opencode/` | `.opencode/` |
|
|
111
110
|
| Cursor | `~/.cursor/` | `.cursor/` |
|
|
112
111
|
|
|
113
112
|
> **Note:** On Windows, `~` is replaced with `C:\Users\<username>\`
|
|
@@ -123,16 +122,17 @@ If the installer detects an existing installation, you'll be prompted:
|
|
|
123
122
|
|
|
124
123
|
### ๐ Universal Compatibility
|
|
125
124
|
|
|
126
|
-
| Tool | Workspace Path | Global Path | Status
|
|
127
|
-
| ----------- | ----------------- | ------------ |
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
|
|
135
|
-
|
|
125
|
+
| Tool | Workspace Path | Global Path | Status |
|
|
126
|
+
| ----------- | ----------------- | ------------ | ------------------ |
|
|
127
|
+
| Antigravity | `.agent/skills/` | `~/.agent/` | โ
Fully Supported |
|
|
128
|
+
| OpenCode | `.opencode/` | `~/.config/opencode/` | โ
Fully Supported |
|
|
129
|
+
| Cursor | `.cursor/skills/` | `~/.cursor/` | โ
Fully Supported |
|
|
130
|
+
| Claude Code | `.claude/skills/` | `~/.claude/` | ๐ Coming Soon |
|
|
131
|
+
| Gemini CLI | `.gemini/skills/` | `~/.gemini/` | ๐ Coming Soon |
|
|
132
|
+
| Codex CLI | `.codex/skills/` | `~/.codex/` | ๐ Coming Soon |
|
|
133
|
+
| Custom | Configurable | `~/.ai/` | ๐ Coming Soon |
|
|
134
|
+
|
|
135
|
+
> **Note:** Tools marked as ๐ Coming Soon are planned for future releases. The infrastructure is ready, but these tools require additional testing and configuration.
|
|
136
136
|
|
|
137
137
|
### ๐ป Cross-Platform Support
|
|
138
138
|
|
package/README.vi.md
CHANGED
|
@@ -60,7 +60,7 @@ npx @neyugn/agent-kits
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
```
|
|
63
|
-
|
|
63
|
+
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
|
|
64
64
|
โ โ
|
|
65
65
|
โ _ ____ _____ _ _ _____ _ __ ___ _____ ____ โ
|
|
66
66
|
โ / \ / ___|| ____|| \ | ||_ _| | |/ /|_ _||_ _|/ ___| โ
|
|
@@ -70,15 +70,13 @@ npx @neyugn/agent-kits
|
|
|
70
70
|
โ โ
|
|
71
71
|
โ โก The Universal AI Agent Toolkit โก โ
|
|
72
72
|
โ โ
|
|
73
|
-
|
|
73
|
+
โฏโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
|
|
74
74
|
|
|
75
75
|
SETUP WIZARD
|
|
76
76
|
|
|
77
77
|
โ ๐ค Bแบกn ฤang sแปญ dแปฅng cรดng cแปฅ AI nร o?
|
|
78
|
-
โ
|
|
79
|
-
โ โ Gemini CLI (.gemini/)
|
|
78
|
+
โ โ Antigravity (.agent/)
|
|
80
79
|
โ โ Cursor (.cursor/)
|
|
81
|
-
โ โ Tรนy chแปnh...
|
|
82
80
|
|
|
83
81
|
โ ๐ Bแบกn muแปn cร i ฤแบทt แป ฤรขu?
|
|
84
82
|
โ โ Workspace (Dแปฑ รกn hiแปn tแบกi)
|
|
@@ -115,16 +113,16 @@ Nแบฟu installer phรกt hiแปn cร i ฤแบทt ฤรฃ tแปn tแบกi, bแบกn sแบฝ ฤฦฐแปฃc h
|
|
|
115
113
|
|
|
116
114
|
### ๐ Tฦฐฦกng thรญch phแป quรกt
|
|
117
115
|
|
|
118
|
-
| Cรดng cแปฅ | ฤฦฐแปng dแบซn Workspace | ฤฦฐแปng dแบซn Global | Trแบกng thรกi
|
|
119
|
-
| ----------- | ------------------- | ---------------- |
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
| Claude Code | `.claude/skills/` | `~/.claude/` |
|
|
123
|
-
| Gemini CLI | `.gemini/skills/` | `~/.gemini/` |
|
|
124
|
-
| Codex CLI | `.codex/skills/` | `~/.codex/` |
|
|
125
|
-
| Tรนy chแปnh | Cรณ thแป cแบฅu hรฌnh | `~/.ai/` |
|
|
116
|
+
| Cรดng cแปฅ | ฤฦฐแปng dแบซn Workspace | ฤฦฐแปng dแบซn Global | Trแบกng thรกi |
|
|
117
|
+
| ----------- | ------------------- | ---------------- | ---------------- |
|
|
118
|
+
| Antigravity | `.agent/skills/` | `~/.agent/` | โ
Hแป trแปฃ ฤแบงy ฤแปง |
|
|
119
|
+
| Cursor | `.cursor/skills/` | `~/.cursor/` | โ
Hแป trแปฃ ฤแบงy ฤแปง |
|
|
120
|
+
| Claude Code | `.claude/skills/` | `~/.claude/` | ๐ Sแบฏp ra mแบฏt |
|
|
121
|
+
| Gemini CLI | `.gemini/skills/` | `~/.gemini/` | ๐ Sแบฏp ra mแบฏt |
|
|
122
|
+
| Codex CLI | `.codex/skills/` | `~/.codex/` | ๐ Sแบฏp ra mแบฏt |
|
|
123
|
+
| Tรนy chแปnh | Cรณ thแป cแบฅu hรฌnh | `~/.ai/` | ๐ Sแบฏp ra mแบฏt |
|
|
126
124
|
|
|
127
|
-
> **Lฦฐu รฝ:** Cรกc cรดng cแปฅ ฤรกnh dแบฅu
|
|
125
|
+
> **Lฦฐu รฝ:** Cรกc cรดng cแปฅ ฤรกnh dแบฅu ๐ Sแบฏp ra mแบฏt ฤang ฤฦฐแปฃc lรชn kแบฟ hoแบกch cho cรกc phiรชn bแบฃn tฦฐฦกng lai. Hแบก tแบงng ฤรฃ sแบตn sร ng, nhฦฐng cรกc cรดng cแปฅ nร y cแบงn thรชm kiแปm tra vร cแบฅu hรฌnh.
|
|
128
126
|
|
|
129
127
|
### ๐ป Hแป trแปฃ ฤa nแปn tแบฃng
|
|
130
128
|
|
package/README.zh.md
CHANGED
|
@@ -60,7 +60,7 @@ npx @neyugn/agent-kits
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
```
|
|
63
|
-
|
|
63
|
+
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
|
|
64
64
|
โ โ
|
|
65
65
|
โ _ ____ _____ _ _ _____ _ __ ___ _____ ____ โ
|
|
66
66
|
โ / \ / ___|| ____|| \ | ||_ _| | |/ /|_ _||_ _|/ ___| โ
|
|
@@ -70,15 +70,13 @@ npx @neyugn/agent-kits
|
|
|
70
70
|
โ โ
|
|
71
71
|
โ โก The Universal AI Agent Toolkit โก โ
|
|
72
72
|
โ โ
|
|
73
|
-
|
|
73
|
+
โฏโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
|
|
74
74
|
|
|
75
75
|
SETUP WIZARD
|
|
76
76
|
|
|
77
77
|
โ ๐ค ๆจๆญฃๅจไฝฟ็จๅชไธช AI ๅทฅๅ
ท๏ผ
|
|
78
|
-
โ
|
|
79
|
-
โ โ Gemini CLI (.gemini/)
|
|
78
|
+
โ โ Antigravity (.agent/)
|
|
80
79
|
โ โ Cursor (.cursor/)
|
|
81
|
-
โ โ ่ชๅฎไน...
|
|
82
80
|
|
|
83
81
|
โ ๐ ๆจๆณๅฎ่ฃ
ๅจๅช้๏ผ
|
|
84
82
|
โ โ Workspace๏ผๅฝๅ้กน็ฎ๏ผ
|
|
@@ -115,16 +113,16 @@ npx @neyugn/agent-kits
|
|
|
115
113
|
|
|
116
114
|
### ๐ ้็จๅ
ผๅฎนๆง
|
|
117
115
|
|
|
118
|
-
| ๅทฅๅ
ท | Workspace ่ทฏๅพ | Global ่ทฏๅพ | ็ถๆ
|
|
119
|
-
| ----------- | ----------------- | ------------ |
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
| Claude Code | `.claude/skills/` | `~/.claude/` |
|
|
123
|
-
| Gemini CLI | `.gemini/skills/` | `~/.gemini/` |
|
|
124
|
-
| Codex CLI | `.codex/skills/` | `~/.codex/` |
|
|
125
|
-
| ่ชๅฎไน | ๅฏ้
็ฝฎ | `~/.ai/` |
|
|
116
|
+
| ๅทฅๅ
ท | Workspace ่ทฏๅพ | Global ่ทฏๅพ | ็ถๆ |
|
|
117
|
+
| ----------- | ----------------- | ------------ | ----------- |
|
|
118
|
+
| Antigravity | `.agent/skills/` | `~/.agent/` | โ
ๅฎๅ
จๆฏๆ |
|
|
119
|
+
| Cursor | `.cursor/skills/` | `~/.cursor/` | โ
ๅฎๅ
จๆฏๆ |
|
|
120
|
+
| Claude Code | `.claude/skills/` | `~/.claude/` | ๐ ๅณๅฐๆจๅบ |
|
|
121
|
+
| Gemini CLI | `.gemini/skills/` | `~/.gemini/` | ๐ ๅณๅฐๆจๅบ |
|
|
122
|
+
| Codex CLI | `.codex/skills/` | `~/.codex/` | ๐ ๅณๅฐๆจๅบ |
|
|
123
|
+
| ่ชๅฎไน | ๅฏ้
็ฝฎ | `~/.ai/` | ๐ ๅณๅฐๆจๅบ |
|
|
126
124
|
|
|
127
|
-
> **ๆณจๆ๏ผ** ๆ ่ฎฐไธบ
|
|
125
|
+
> **ๆณจๆ๏ผ** ๆ ่ฎฐไธบ ๐ ๅณๅฐๆจๅบ็ๅทฅๅ
ทๅทฒ็บณๅ
ฅๆชๆฅ็ๆฌ่ฎกๅใๅบ็กๆถๆๅทฒๅฐฑ็ปช๏ผไฝ่ฟไบๅทฅๅ
ท้่ฆ้ขๅค็ๆต่ฏๅ้
็ฝฎใ
|
|
128
126
|
|
|
129
127
|
### ๐ป ่ทจๅนณๅฐๆฏๆ
|
|
130
128
|
|
package/dist/cli.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
import * as p from "@clack/prompts";
|
|
5
5
|
import boxen from "boxen";
|
|
6
6
|
import figlet from "figlet";
|
|
7
|
-
import
|
|
7
|
+
import fs5 from "fs";
|
|
8
8
|
import gradient from "gradient-string";
|
|
9
9
|
import os2 from "os";
|
|
10
|
-
import
|
|
10
|
+
import path6 from "path";
|
|
11
11
|
import pc from "picocolors";
|
|
12
12
|
|
|
13
13
|
// src/config.ts
|
|
@@ -33,8 +33,10 @@ var AI_TOOLS = [
|
|
|
33
33
|
// Resolved to home dir at runtime
|
|
34
34
|
rulesFile: "CLAUDE.md",
|
|
35
35
|
kitRulesFile: "CLAUDE.md",
|
|
36
|
-
rulesInsideKit: true
|
|
36
|
+
rulesInsideKit: true,
|
|
37
37
|
// Claude reads from .claude/CLAUDE.md (2025 standard)
|
|
38
|
+
available: false
|
|
39
|
+
// Coming soon
|
|
38
40
|
},
|
|
39
41
|
{
|
|
40
42
|
id: "gemini",
|
|
@@ -44,8 +46,10 @@ var AI_TOOLS = [
|
|
|
44
46
|
globalPathPattern: "~/.gemini",
|
|
45
47
|
rulesFile: "GEMINI.md",
|
|
46
48
|
kitRulesFile: "GEMINI.md",
|
|
47
|
-
rulesInsideKit: true
|
|
49
|
+
rulesInsideKit: true,
|
|
48
50
|
// Gemini reads from .gemini/GEMINI.md
|
|
51
|
+
available: false
|
|
52
|
+
// Coming soon
|
|
49
53
|
},
|
|
50
54
|
{
|
|
51
55
|
id: "codex",
|
|
@@ -55,8 +59,10 @@ var AI_TOOLS = [
|
|
|
55
59
|
globalPathPattern: "~/.codex",
|
|
56
60
|
rulesFile: "AGENTS.md",
|
|
57
61
|
kitRulesFile: "AGENTS.md",
|
|
58
|
-
rulesInsideKit: true
|
|
62
|
+
rulesInsideKit: true,
|
|
59
63
|
// Codex reads from .codex/AGENTS.md
|
|
64
|
+
available: false
|
|
65
|
+
// Coming soon
|
|
60
66
|
},
|
|
61
67
|
{
|
|
62
68
|
id: "antigravity",
|
|
@@ -66,21 +72,39 @@ var AI_TOOLS = [
|
|
|
66
72
|
globalPathPattern: "~/.agent",
|
|
67
73
|
rulesFile: "GEMINI.md",
|
|
68
74
|
kitRulesFile: "GEMINI.md",
|
|
69
|
-
rulesInsideKit: true
|
|
75
|
+
rulesInsideKit: true,
|
|
70
76
|
// Antigravity reads GEMINI.md from inside .agent/
|
|
77
|
+
available: true
|
|
71
78
|
},
|
|
72
79
|
{
|
|
73
80
|
id: "cursor",
|
|
74
81
|
name: "Cursor",
|
|
75
82
|
icon: "\u26AA",
|
|
76
|
-
path: ".cursor
|
|
77
|
-
//
|
|
78
|
-
globalPathPattern: "~/.cursor
|
|
79
|
-
rulesFile: "rules.md",
|
|
83
|
+
path: ".cursor",
|
|
84
|
+
// Base path for Cursor (contains rules/ and commands/)
|
|
85
|
+
globalPathPattern: "~/.cursor",
|
|
86
|
+
rulesFile: "rules/rules.md",
|
|
80
87
|
// Modern: .cursor/rules/rules.md instead of .cursorrules
|
|
81
88
|
kitRulesFile: "CURSOR.md",
|
|
82
89
|
// Source file in kit
|
|
83
|
-
rulesInsideKit: true
|
|
90
|
+
rulesInsideKit: true,
|
|
91
|
+
workflowsAs: "commands",
|
|
92
|
+
// Cursor calls workflows "commands" in .cursor/commands/
|
|
93
|
+
available: true
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: "opencode",
|
|
97
|
+
name: "OpenCode",
|
|
98
|
+
icon: "\u232C",
|
|
99
|
+
path: ".opencode",
|
|
100
|
+
globalPathPattern: "~/.config/opencode",
|
|
101
|
+
rulesFile: "AGENTS.md",
|
|
102
|
+
kitRulesFile: "AGENTS.md",
|
|
103
|
+
rulesInsideKit: false,
|
|
104
|
+
// OpenCode reads AGENTS.md from project root
|
|
105
|
+
workflowsAs: "commands",
|
|
106
|
+
// OpenCode calls workflows "commands" in .opencode/commands/
|
|
107
|
+
available: true
|
|
84
108
|
},
|
|
85
109
|
{
|
|
86
110
|
id: "custom",
|
|
@@ -89,8 +113,10 @@ var AI_TOOLS = [
|
|
|
89
113
|
path: ".ai",
|
|
90
114
|
globalPathPattern: "~/.ai",
|
|
91
115
|
rulesFile: "RULES.md",
|
|
92
|
-
kitRulesFile: "GEMINI.md"
|
|
116
|
+
kitRulesFile: "GEMINI.md",
|
|
93
117
|
// Use GEMINI.md as base for custom
|
|
118
|
+
available: false
|
|
119
|
+
// Coming soon
|
|
94
120
|
}
|
|
95
121
|
];
|
|
96
122
|
var KITS = [
|
|
@@ -136,85 +162,28 @@ var KITS = [
|
|
|
136
162
|
}
|
|
137
163
|
];
|
|
138
164
|
|
|
139
|
-
// src/installers/
|
|
165
|
+
// src/installers/antigravity.ts
|
|
166
|
+
import fs2 from "fs/promises";
|
|
167
|
+
import path3 from "path";
|
|
168
|
+
|
|
169
|
+
// src/installers/base.ts
|
|
140
170
|
import fs from "fs/promises";
|
|
141
171
|
import path2 from "path";
|
|
142
172
|
import { fileURLToPath } from "url";
|
|
143
173
|
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
144
174
|
var KITS_DIR = path2.resolve(__dirname, "../kits");
|
|
145
175
|
var COMMON_DIR = path2.resolve(__dirname, "../common");
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const kit = KITS.find((k) => k.id === kitId);
|
|
151
|
-
if (!kit || !kit.available) {
|
|
152
|
-
throw new Error(`Kit "${kitId}" is not available`);
|
|
153
|
-
}
|
|
154
|
-
const kitSourcePath = path2.join(KITS_DIR, kitId);
|
|
155
|
-
const kitTargetPath = path2.join(targetPath, aiTool.path);
|
|
156
|
-
await fs.mkdir(kitTargetPath, { recursive: true });
|
|
157
|
-
await copyDirectory(kitSourcePath, kitTargetPath, ["rules"], aiTool.path);
|
|
158
|
-
const rulesSource = path2.join(kitSourcePath, "rules", aiTool.kitRulesFile);
|
|
159
|
-
const rulesTarget = options.scope === "global" || aiTool.rulesInsideKit ? path2.join(kitTargetPath, aiTool.rulesFile) : path2.join(targetPath, aiTool.rulesFile);
|
|
160
|
-
try {
|
|
161
|
-
let rulesContent = await fs.readFile(rulesSource, "utf-8");
|
|
162
|
-
rulesContent = rulesContent.replace(
|
|
163
|
-
/\.(agent|claude|gemini|cursor|codex)\//g,
|
|
164
|
-
`${aiTool.path}/`
|
|
165
|
-
);
|
|
166
|
-
await fs.writeFile(rulesTarget, rulesContent);
|
|
167
|
-
} catch {
|
|
168
|
-
try {
|
|
169
|
-
const fallbackSource = path2.join(kitSourcePath, "rules", "GEMINI.md");
|
|
170
|
-
let rulesContent = await fs.readFile(fallbackSource, "utf-8");
|
|
171
|
-
rulesContent = rulesContent.replace(
|
|
172
|
-
/\.(agent|claude|gemini|cursor|codex)\//g,
|
|
173
|
-
`${aiTool.path}/`
|
|
174
|
-
);
|
|
175
|
-
await fs.writeFile(rulesTarget, rulesContent);
|
|
176
|
-
} catch {
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
try {
|
|
180
|
-
const commonSkillsPath = path2.join(COMMON_DIR, "skills");
|
|
181
|
-
const commonWorkflowsPath = path2.join(COMMON_DIR, "workflows");
|
|
182
|
-
const commonDocPath = path2.join(COMMON_DIR, "COMMON.md");
|
|
183
|
-
const targetSkillsPath = path2.join(kitTargetPath, "skills");
|
|
184
|
-
await fs.mkdir(targetSkillsPath, { recursive: true });
|
|
185
|
-
await copyDirectory(commonSkillsPath, targetSkillsPath, [], aiTool.path);
|
|
186
|
-
const targetWorkflowsPath = path2.join(kitTargetPath, "workflows");
|
|
187
|
-
await fs.mkdir(targetWorkflowsPath, { recursive: true });
|
|
188
|
-
await copyDirectory(
|
|
189
|
-
commonWorkflowsPath,
|
|
190
|
-
targetWorkflowsPath,
|
|
191
|
-
[],
|
|
192
|
-
aiTool.path
|
|
193
|
-
);
|
|
194
|
-
const targetCommonDoc = path2.join(kitTargetPath, "COMMON.md");
|
|
195
|
-
const commonContent = await fs.readFile(commonDocPath, "utf-8");
|
|
196
|
-
const updatedCommonContent = commonContent.replace(
|
|
197
|
-
/\.(agent|claude|gemini|cursor|codex)\//g,
|
|
198
|
-
`${aiTool.path}/`
|
|
199
|
-
);
|
|
200
|
-
await fs.writeFile(targetCommonDoc, updatedCommonContent);
|
|
201
|
-
} catch {
|
|
202
|
-
}
|
|
203
|
-
const agents = await countItems(path2.join(kitTargetPath, "agents"));
|
|
204
|
-
const skills = await countItems(path2.join(kitTargetPath, "skills"));
|
|
205
|
-
const workflows = await countItems(path2.join(kitTargetPath, "workflows"));
|
|
206
|
-
results.push({
|
|
207
|
-
kit: kit.name,
|
|
208
|
-
agents,
|
|
209
|
-
skills,
|
|
210
|
-
workflows
|
|
211
|
-
});
|
|
176
|
+
function getKitSource(kitId) {
|
|
177
|
+
const kit = KITS.find((k) => k.id === kitId);
|
|
178
|
+
if (!kit || !kit.available) {
|
|
179
|
+
throw new Error(`Kit "${kitId}" is not available`);
|
|
212
180
|
}
|
|
213
|
-
|
|
181
|
+
const kitSourcePath = path2.join(KITS_DIR, kitId);
|
|
182
|
+
return { kitSourcePath, kit };
|
|
214
183
|
}
|
|
215
184
|
function replaceToolPaths(content, targetPath) {
|
|
216
185
|
return content.replace(
|
|
217
|
-
/\.(agent|claude|gemini|cursor|codex)\//g,
|
|
186
|
+
/\.(agent|claude|gemini|cursor|codex|opencode)\//g,
|
|
218
187
|
`${targetPath}/`
|
|
219
188
|
);
|
|
220
189
|
}
|
|
@@ -250,17 +219,625 @@ async function countItems(dirPath) {
|
|
|
250
219
|
return 0;
|
|
251
220
|
}
|
|
252
221
|
}
|
|
222
|
+
async function copyRulesFile(kitSourcePath, kitTargetPath, targetPath, aiTool, scope, workflowsReplacement) {
|
|
223
|
+
const rulesSource = path2.join(kitSourcePath, "rules", aiTool.kitRulesFile);
|
|
224
|
+
const rulesTarget = scope === "global" || aiTool.rulesInsideKit ? path2.join(kitTargetPath, aiTool.rulesFile) : path2.join(targetPath, aiTool.rulesFile);
|
|
225
|
+
await fs.mkdir(path2.dirname(rulesTarget), { recursive: true });
|
|
226
|
+
try {
|
|
227
|
+
let rulesContent = await fs.readFile(rulesSource, "utf-8");
|
|
228
|
+
rulesContent = replaceToolPaths(rulesContent, aiTool.path);
|
|
229
|
+
if (workflowsReplacement) {
|
|
230
|
+
rulesContent = rulesContent.replace(
|
|
231
|
+
/workflows\//g,
|
|
232
|
+
`${workflowsReplacement}/`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
await fs.writeFile(rulesTarget, rulesContent);
|
|
236
|
+
} catch {
|
|
237
|
+
try {
|
|
238
|
+
const fallbackSource = path2.join(kitSourcePath, "rules", "GEMINI.md");
|
|
239
|
+
let rulesContent = await fs.readFile(fallbackSource, "utf-8");
|
|
240
|
+
rulesContent = replaceToolPaths(rulesContent, aiTool.path);
|
|
241
|
+
if (workflowsReplacement) {
|
|
242
|
+
rulesContent = rulesContent.replace(
|
|
243
|
+
/workflows\//g,
|
|
244
|
+
`${workflowsReplacement}/`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
await fs.writeFile(rulesTarget, rulesContent);
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function copyCommonAssets(kitTargetPath, aiTool, workflowsFolderName = "workflows") {
|
|
253
|
+
const commonSkillsPath = path2.join(COMMON_DIR, "skills");
|
|
254
|
+
const commonWorkflowsPath = path2.join(COMMON_DIR, "workflows");
|
|
255
|
+
const commonDocPath = path2.join(COMMON_DIR, "COMMON.md");
|
|
256
|
+
const targetSkillsPath = path2.join(kitTargetPath, "skills");
|
|
257
|
+
await fs.mkdir(targetSkillsPath, { recursive: true });
|
|
258
|
+
await copyDirectory(commonSkillsPath, targetSkillsPath, [], aiTool.path);
|
|
259
|
+
const targetWorkflowsPath = path2.join(kitTargetPath, workflowsFolderName);
|
|
260
|
+
await fs.mkdir(targetWorkflowsPath, { recursive: true });
|
|
261
|
+
await copyDirectory(
|
|
262
|
+
commonWorkflowsPath,
|
|
263
|
+
targetWorkflowsPath,
|
|
264
|
+
[],
|
|
265
|
+
aiTool.path
|
|
266
|
+
);
|
|
267
|
+
const targetCommonDoc = path2.join(kitTargetPath, "COMMON.md");
|
|
268
|
+
const commonContent = await fs.readFile(commonDocPath, "utf-8");
|
|
269
|
+
const updatedCommonContent = replaceToolPaths(commonContent, aiTool.path);
|
|
270
|
+
await fs.writeFile(targetCommonDoc, updatedCommonContent);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/installers/antigravity.ts
|
|
274
|
+
var AntigravityInstaller = class {
|
|
275
|
+
async install(options) {
|
|
276
|
+
const { aiTool, kits, targetPath } = options;
|
|
277
|
+
const results = [];
|
|
278
|
+
for (const kitId of kits) {
|
|
279
|
+
const { kitSourcePath, kit } = getKitSource(kitId);
|
|
280
|
+
const kitTargetPath = path3.join(targetPath, aiTool.path);
|
|
281
|
+
await fs2.mkdir(kitTargetPath, { recursive: true });
|
|
282
|
+
await copyDirectory(kitSourcePath, kitTargetPath, ["rules"], aiTool.path);
|
|
283
|
+
await copyRulesFile(
|
|
284
|
+
kitSourcePath,
|
|
285
|
+
kitTargetPath,
|
|
286
|
+
targetPath,
|
|
287
|
+
aiTool,
|
|
288
|
+
options.scope
|
|
289
|
+
);
|
|
290
|
+
try {
|
|
291
|
+
await copyCommonAssets(kitTargetPath, aiTool, "workflows");
|
|
292
|
+
} catch {
|
|
293
|
+
}
|
|
294
|
+
const agents = await countItems(path3.join(kitTargetPath, "agents"));
|
|
295
|
+
const skills = await countItems(path3.join(kitTargetPath, "skills"));
|
|
296
|
+
const workflows = await countItems(path3.join(kitTargetPath, "workflows"));
|
|
297
|
+
results.push({
|
|
298
|
+
kit: kit.name,
|
|
299
|
+
agents,
|
|
300
|
+
skills,
|
|
301
|
+
workflows
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
return results;
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// src/installers/cursor.ts
|
|
309
|
+
import fs3 from "fs/promises";
|
|
310
|
+
import path4 from "path";
|
|
311
|
+
|
|
312
|
+
// src/transformers/utils.ts
|
|
313
|
+
function parseFrontmatter(content) {
|
|
314
|
+
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;
|
|
315
|
+
const match = content.match(frontmatterRegex);
|
|
316
|
+
if (!match) {
|
|
317
|
+
return {
|
|
318
|
+
data: {},
|
|
319
|
+
content,
|
|
320
|
+
raw: ""
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const rawFrontmatter = match[1];
|
|
324
|
+
const bodyContent = match[2];
|
|
325
|
+
const data = {};
|
|
326
|
+
const lines = rawFrontmatter.split("\n");
|
|
327
|
+
for (const line of lines) {
|
|
328
|
+
const colonIndex = line.indexOf(":");
|
|
329
|
+
if (colonIndex === -1) continue;
|
|
330
|
+
const key = line.slice(0, colonIndex).trim();
|
|
331
|
+
let value = line.slice(colonIndex + 1).trim();
|
|
332
|
+
if (value === "true") value = true;
|
|
333
|
+
else if (value === "false") value = false;
|
|
334
|
+
else if (!isNaN(Number(value)) && value !== "") value = Number(value);
|
|
335
|
+
if (key) {
|
|
336
|
+
data[key] = value;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
data,
|
|
341
|
+
content: bodyContent,
|
|
342
|
+
raw: rawFrontmatter
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function serializeFrontmatter(data) {
|
|
346
|
+
const lines = ["---"];
|
|
347
|
+
for (const [key, value] of Object.entries(data)) {
|
|
348
|
+
if (value === void 0 || value === null) continue;
|
|
349
|
+
lines.push(`${key}: ${value}`);
|
|
350
|
+
}
|
|
351
|
+
lines.push("---");
|
|
352
|
+
return lines.join("\n");
|
|
353
|
+
}
|
|
354
|
+
function combineMarkdown(frontmatter, content) {
|
|
355
|
+
return `${frontmatter}
|
|
356
|
+
${content}`;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/transformers/cursor-agent.ts
|
|
360
|
+
var CursorAgentTransformer = class {
|
|
361
|
+
/**
|
|
362
|
+
* Transform agent content from Agent-Kits format to Cursor subagent format
|
|
363
|
+
*/
|
|
364
|
+
transform(content, context) {
|
|
365
|
+
const parsed = parseFrontmatter(content);
|
|
366
|
+
const originalData = parsed.data;
|
|
367
|
+
const skillsString = originalData.skills;
|
|
368
|
+
const skills = skillsString ? skillsString.split(",").map((s) => s.trim()) : [];
|
|
369
|
+
const cursorFrontmatter = {
|
|
370
|
+
name: originalData.name,
|
|
371
|
+
description: originalData.description,
|
|
372
|
+
model: originalData.model || "inherit",
|
|
373
|
+
readonly: false,
|
|
374
|
+
is_background: false
|
|
375
|
+
};
|
|
376
|
+
const newFrontmatter = serializeFrontmatter(
|
|
377
|
+
cursorFrontmatter
|
|
378
|
+
);
|
|
379
|
+
let skillsSection = "";
|
|
380
|
+
if (skills.length > 0) {
|
|
381
|
+
skillsSection = this.createSkillsSection(
|
|
382
|
+
skills,
|
|
383
|
+
context.skillDescriptions || {}
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
const bodyContent = parsed.content;
|
|
387
|
+
const insertedBody = this.insertSkillsSection(bodyContent, skillsSection);
|
|
388
|
+
return combineMarkdown(newFrontmatter, insertedBody);
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Create markdown section for required skills
|
|
392
|
+
* Uses descriptions from context (loaded from SKILL.md files)
|
|
393
|
+
*/
|
|
394
|
+
createSkillsSection(skills, skillDescriptions) {
|
|
395
|
+
const lines = [
|
|
396
|
+
"",
|
|
397
|
+
"## \u{1F4DA} Required Skills",
|
|
398
|
+
"",
|
|
399
|
+
"This agent uses the following skills from `.cursor/skills/`:",
|
|
400
|
+
""
|
|
401
|
+
];
|
|
402
|
+
for (const skill of skills) {
|
|
403
|
+
const description = skillDescriptions[skill] || "Domain-specific knowledge module";
|
|
404
|
+
lines.push(`- **${skill}** - ${description}`);
|
|
405
|
+
}
|
|
406
|
+
lines.push("", "---", "");
|
|
407
|
+
return lines.join("\n");
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Insert skills section after the first heading
|
|
411
|
+
*/
|
|
412
|
+
insertSkillsSection(body, skillsSection) {
|
|
413
|
+
if (!skillsSection) return body;
|
|
414
|
+
const lines = body.split("\n");
|
|
415
|
+
let insertIndex = 0;
|
|
416
|
+
for (let i = 0; i < lines.length; i++) {
|
|
417
|
+
const line = lines[i].trim();
|
|
418
|
+
if (line.startsWith("# ")) {
|
|
419
|
+
insertIndex = i + 1;
|
|
420
|
+
while (insertIndex < lines.length && lines[insertIndex].trim() === "") {
|
|
421
|
+
insertIndex++;
|
|
422
|
+
}
|
|
423
|
+
if (insertIndex < lines.length && !lines[insertIndex].trim().startsWith("#")) {
|
|
424
|
+
insertIndex++;
|
|
425
|
+
}
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
lines.splice(insertIndex, 0, skillsSection);
|
|
430
|
+
return lines.join("\n");
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
function createCursorAgentTransformer() {
|
|
434
|
+
return new CursorAgentTransformer();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/transformers/cursor-workflow.ts
|
|
438
|
+
var CursorWorkflowTransformer = class {
|
|
439
|
+
/**
|
|
440
|
+
* Transform workflow content from Agent-Kits format to Cursor command format
|
|
441
|
+
*/
|
|
442
|
+
transform(content, context) {
|
|
443
|
+
const parsed = parseFrontmatter(content);
|
|
444
|
+
const originalData = parsed.data;
|
|
445
|
+
const cursorFrontmatter = {
|
|
446
|
+
description: originalData.description
|
|
447
|
+
};
|
|
448
|
+
const newFrontmatter = serializeFrontmatter(
|
|
449
|
+
cursorFrontmatter
|
|
450
|
+
);
|
|
451
|
+
let bodyContent = parsed.content;
|
|
452
|
+
bodyContent = this.transformPaths(bodyContent, context);
|
|
453
|
+
bodyContent = this.transformTerminology(bodyContent);
|
|
454
|
+
return combineMarkdown(newFrontmatter, bodyContent);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Transform path references from .agent/ to .cursor/
|
|
458
|
+
*/
|
|
459
|
+
transformPaths(content, context) {
|
|
460
|
+
let transformed = content;
|
|
461
|
+
const toolPath = context.aiTool?.path || ".cursor";
|
|
462
|
+
transformed = transformed.replace(/\.agent\//g, `${toolPath}/`);
|
|
463
|
+
return transformed;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Transform terminology from Agent-Kits to Cursor
|
|
467
|
+
*/
|
|
468
|
+
transformTerminology(content) {
|
|
469
|
+
let transformed = content;
|
|
470
|
+
transformed = transformed.replace(/workflows?\//gi, "commands/");
|
|
471
|
+
transformed = transformed.replace(/\/workflow/gi, "/command");
|
|
472
|
+
transformed = transformed.replace(/workflow/gi, "command");
|
|
473
|
+
transformed = transformed.replace(/Workflow/g, "Command");
|
|
474
|
+
transformed = transformed.replace(/WORKFLOW/g, "COMMAND");
|
|
475
|
+
return transformed;
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
function createCursorWorkflowTransformer() {
|
|
479
|
+
return new CursorWorkflowTransformer();
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// src/transformers/opencode-workflow.ts
|
|
483
|
+
var OpenCodeWorkflowTransformer = class {
|
|
484
|
+
/**
|
|
485
|
+
* Transform workflow content from Agent-Kits format to OpenCode command format
|
|
486
|
+
*/
|
|
487
|
+
transform(content, context) {
|
|
488
|
+
const parsed = parseFrontmatter(content);
|
|
489
|
+
const originalData = parsed.data;
|
|
490
|
+
const commandFrontmatter = {
|
|
491
|
+
description: String(originalData.description || "")
|
|
492
|
+
};
|
|
493
|
+
const newFrontmatter = serializeFrontmatter(
|
|
494
|
+
commandFrontmatter
|
|
495
|
+
);
|
|
496
|
+
let bodyContent = parsed.content;
|
|
497
|
+
bodyContent = this.transformPaths(bodyContent, context);
|
|
498
|
+
bodyContent = this.transformTerminology(bodyContent);
|
|
499
|
+
return combineMarkdown(newFrontmatter, bodyContent);
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Replace .agent/ paths with .opencode/
|
|
503
|
+
*/
|
|
504
|
+
transformPaths(content, context) {
|
|
505
|
+
const toolPath = context.aiTool?.path || ".opencode";
|
|
506
|
+
return content.replace(/\.agent\//g, `${toolPath}/`);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Transform terminology: workflow โ command
|
|
510
|
+
*/
|
|
511
|
+
transformTerminology(content) {
|
|
512
|
+
let transformed = content;
|
|
513
|
+
transformed = transformed.replace(/workflows?\//gi, "commands/");
|
|
514
|
+
transformed = transformed.replace(/\/workflow/gi, "/command");
|
|
515
|
+
transformed = transformed.replace(/workflow/gi, "command");
|
|
516
|
+
transformed = transformed.replace(/Workflow/g, "Command");
|
|
517
|
+
transformed = transformed.replace(/WORKFLOW/g, "COMMAND");
|
|
518
|
+
return transformed;
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
function createOpenCodeWorkflowTransformer() {
|
|
522
|
+
return new OpenCodeWorkflowTransformer();
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/installers/cursor.ts
|
|
526
|
+
var CursorInstaller = class {
|
|
527
|
+
// Cursor uses "commands" instead of "workflows"
|
|
528
|
+
COMMANDS_FOLDER = "commands";
|
|
529
|
+
// Transformers for Cursor-specific formats
|
|
530
|
+
agentTransformer = createCursorAgentTransformer();
|
|
531
|
+
workflowTransformer = createCursorWorkflowTransformer();
|
|
532
|
+
async install(options) {
|
|
533
|
+
const { aiTool, kits, targetPath } = options;
|
|
534
|
+
const results = [];
|
|
535
|
+
for (const kitId of kits) {
|
|
536
|
+
const { kitSourcePath, kit } = getKitSource(kitId);
|
|
537
|
+
const kitTargetPath = path4.join(targetPath, aiTool.path);
|
|
538
|
+
await fs3.mkdir(kitTargetPath, { recursive: true });
|
|
539
|
+
const skillDescriptions = await this.loadSkillDescriptions(kitSourcePath);
|
|
540
|
+
await copyDirectory(
|
|
541
|
+
kitSourcePath,
|
|
542
|
+
kitTargetPath,
|
|
543
|
+
["rules", "workflows", "agents"],
|
|
544
|
+
aiTool.path
|
|
545
|
+
);
|
|
546
|
+
await this.copyAgentsWithTransform(
|
|
547
|
+
kitSourcePath,
|
|
548
|
+
kitTargetPath,
|
|
549
|
+
aiTool.path,
|
|
550
|
+
skillDescriptions
|
|
551
|
+
);
|
|
552
|
+
await this.copyWorkflowsWithTransform(
|
|
553
|
+
kitSourcePath,
|
|
554
|
+
kitTargetPath,
|
|
555
|
+
aiTool.path
|
|
556
|
+
);
|
|
557
|
+
await copyRulesFile(
|
|
558
|
+
kitSourcePath,
|
|
559
|
+
kitTargetPath,
|
|
560
|
+
targetPath,
|
|
561
|
+
aiTool,
|
|
562
|
+
options.scope,
|
|
563
|
+
this.COMMANDS_FOLDER
|
|
564
|
+
// Replace workflows/ with commands/
|
|
565
|
+
);
|
|
566
|
+
try {
|
|
567
|
+
await copyCommonAssets(kitTargetPath, aiTool, this.COMMANDS_FOLDER);
|
|
568
|
+
} catch {
|
|
569
|
+
}
|
|
570
|
+
const agents = await countItems(path4.join(kitTargetPath, "agents"));
|
|
571
|
+
const skills = await countItems(path4.join(kitTargetPath, "skills"));
|
|
572
|
+
const commands = await countItems(
|
|
573
|
+
path4.join(kitTargetPath, this.COMMANDS_FOLDER)
|
|
574
|
+
);
|
|
575
|
+
results.push({
|
|
576
|
+
kit: kit.name,
|
|
577
|
+
agents,
|
|
578
|
+
skills,
|
|
579
|
+
workflows: commands
|
|
580
|
+
// Still called "workflows" in result for consistency
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
return results;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Load skill descriptions from SKILL.md files
|
|
587
|
+
*
|
|
588
|
+
* Reads the `description` field from each skill's frontmatter.
|
|
589
|
+
* Loads from both kit-specific skills and common skills.
|
|
590
|
+
*
|
|
591
|
+
* @returns Map of skill name to description
|
|
592
|
+
*/
|
|
593
|
+
async loadSkillDescriptions(kitSourcePath) {
|
|
594
|
+
const descriptions = {};
|
|
595
|
+
const kitSkillsPath = path4.join(kitSourcePath, "skills");
|
|
596
|
+
await this.extractSkillDescriptions(kitSkillsPath, descriptions);
|
|
597
|
+
const commonSkillsPath = path4.join(COMMON_DIR, "skills");
|
|
598
|
+
await this.extractSkillDescriptions(commonSkillsPath, descriptions);
|
|
599
|
+
return descriptions;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Extract descriptions from all SKILL.md files in a directory
|
|
603
|
+
*/
|
|
604
|
+
async extractSkillDescriptions(skillsDir, descriptions) {
|
|
605
|
+
try {
|
|
606
|
+
const entries = await fs3.readdir(skillsDir, { withFileTypes: true });
|
|
607
|
+
for (const entry of entries) {
|
|
608
|
+
if (!entry.isDirectory()) continue;
|
|
609
|
+
const skillMdPath = path4.join(skillsDir, entry.name, "SKILL.md");
|
|
610
|
+
try {
|
|
611
|
+
const content = await fs3.readFile(skillMdPath, "utf-8");
|
|
612
|
+
const parsed = parseFrontmatter(content);
|
|
613
|
+
if (parsed.data.description) {
|
|
614
|
+
let desc = String(parsed.data.description);
|
|
615
|
+
const sentenceEnd = desc.indexOf(". ");
|
|
616
|
+
if (sentenceEnd > 0 && sentenceEnd < 80) {
|
|
617
|
+
desc = desc.slice(0, sentenceEnd);
|
|
618
|
+
} else if (desc.length > 80) {
|
|
619
|
+
desc = desc.slice(0, 77) + "...";
|
|
620
|
+
}
|
|
621
|
+
descriptions[entry.name] = desc;
|
|
622
|
+
}
|
|
623
|
+
} catch {
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
} catch {
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Copy agents with transformation to Cursor subagent format
|
|
631
|
+
*
|
|
632
|
+
* This method:
|
|
633
|
+
* 1. Reads each agent file from the kit
|
|
634
|
+
* 2. Transforms the frontmatter to Cursor subagent format
|
|
635
|
+
* 3. Embeds skills references into the agent body
|
|
636
|
+
* 4. Writes the transformed agent to the target directory
|
|
637
|
+
*/
|
|
638
|
+
async copyAgentsWithTransform(kitSourcePath, kitTargetPath, toolPath, skillDescriptions) {
|
|
639
|
+
const agentsSource = path4.join(kitSourcePath, "agents");
|
|
640
|
+
const agentsTarget = path4.join(kitTargetPath, "agents");
|
|
641
|
+
try {
|
|
642
|
+
await fs3.access(agentsSource);
|
|
643
|
+
} catch {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
await fs3.mkdir(agentsTarget, { recursive: true });
|
|
647
|
+
const entries = await fs3.readdir(agentsSource, { withFileTypes: true });
|
|
648
|
+
for (const entry of entries) {
|
|
649
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
const sourcePath = path4.join(agentsSource, entry.name);
|
|
653
|
+
const targetPath = path4.join(agentsTarget, entry.name);
|
|
654
|
+
let content = await fs3.readFile(sourcePath, "utf-8");
|
|
655
|
+
content = replaceToolPaths(content, toolPath);
|
|
656
|
+
const context = {
|
|
657
|
+
aiTool: { path: toolPath },
|
|
658
|
+
sourcePath,
|
|
659
|
+
targetPath,
|
|
660
|
+
skillDescriptions
|
|
661
|
+
};
|
|
662
|
+
const transformedContent = this.agentTransformer.transform(
|
|
663
|
+
content,
|
|
664
|
+
context
|
|
665
|
+
);
|
|
666
|
+
await fs3.writeFile(targetPath, transformedContent);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Copy workflows with transformation to Cursor command format
|
|
671
|
+
*
|
|
672
|
+
* This method:
|
|
673
|
+
* 1. Reads each workflow file from the kit
|
|
674
|
+
* 2. Transforms the frontmatter to Cursor command format
|
|
675
|
+
* 3. Replaces path references (.agent/ -> .cursor/)
|
|
676
|
+
* 4. Replaces terminology (workflow -> command)
|
|
677
|
+
* 5. Writes the transformed command to the commands directory
|
|
678
|
+
*/
|
|
679
|
+
async copyWorkflowsWithTransform(kitSourcePath, kitTargetPath, toolPath) {
|
|
680
|
+
const workflowsSource = path4.join(kitSourcePath, "workflows");
|
|
681
|
+
const commandsTarget = path4.join(kitTargetPath, this.COMMANDS_FOLDER);
|
|
682
|
+
try {
|
|
683
|
+
await fs3.access(workflowsSource);
|
|
684
|
+
} catch {
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
await fs3.mkdir(commandsTarget, { recursive: true });
|
|
688
|
+
const entries = await fs3.readdir(workflowsSource, { withFileTypes: true });
|
|
689
|
+
for (const entry of entries) {
|
|
690
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
const sourcePath = path4.join(workflowsSource, entry.name);
|
|
694
|
+
const targetPath = path4.join(commandsTarget, entry.name);
|
|
695
|
+
const content = await fs3.readFile(sourcePath, "utf-8");
|
|
696
|
+
const context = {
|
|
697
|
+
aiTool: { path: toolPath },
|
|
698
|
+
sourcePath,
|
|
699
|
+
targetPath
|
|
700
|
+
};
|
|
701
|
+
const transformedContent = this.workflowTransformer.transform(
|
|
702
|
+
content,
|
|
703
|
+
context
|
|
704
|
+
);
|
|
705
|
+
await fs3.writeFile(targetPath, transformedContent);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
// src/installers/opencode.ts
|
|
711
|
+
import fs4 from "fs/promises";
|
|
712
|
+
import path5 from "path";
|
|
713
|
+
var OpenCodeInstaller = class {
|
|
714
|
+
// OpenCode uses "commands" instead of "workflows"
|
|
715
|
+
COMMANDS_FOLDER = "commands";
|
|
716
|
+
// Transformer for OpenCode command format
|
|
717
|
+
workflowTransformer = createOpenCodeWorkflowTransformer();
|
|
718
|
+
async install(options) {
|
|
719
|
+
const { aiTool, kits, targetPath } = options;
|
|
720
|
+
const results = [];
|
|
721
|
+
for (const kitId of kits) {
|
|
722
|
+
const { kitSourcePath, kit } = getKitSource(kitId);
|
|
723
|
+
const kitTargetPath = path5.join(targetPath, aiTool.path);
|
|
724
|
+
await fs4.mkdir(kitTargetPath, { recursive: true });
|
|
725
|
+
await copyDirectory(
|
|
726
|
+
kitSourcePath,
|
|
727
|
+
kitTargetPath,
|
|
728
|
+
["rules", "workflows"],
|
|
729
|
+
aiTool.path
|
|
730
|
+
);
|
|
731
|
+
await this.copyWorkflowsWithTransform(
|
|
732
|
+
kitSourcePath,
|
|
733
|
+
kitTargetPath,
|
|
734
|
+
aiTool.path
|
|
735
|
+
);
|
|
736
|
+
await copyRulesFile(
|
|
737
|
+
kitSourcePath,
|
|
738
|
+
kitTargetPath,
|
|
739
|
+
targetPath,
|
|
740
|
+
aiTool,
|
|
741
|
+
options.scope,
|
|
742
|
+
this.COMMANDS_FOLDER
|
|
743
|
+
// Replace workflows/ with commands/
|
|
744
|
+
);
|
|
745
|
+
try {
|
|
746
|
+
await copyCommonAssets(kitTargetPath, aiTool, this.COMMANDS_FOLDER);
|
|
747
|
+
} catch {
|
|
748
|
+
}
|
|
749
|
+
const agents = await countItems(path5.join(kitTargetPath, "agents"));
|
|
750
|
+
const skills = await countItems(path5.join(kitTargetPath, "skills"));
|
|
751
|
+
const commands = await countItems(
|
|
752
|
+
path5.join(kitTargetPath, this.COMMANDS_FOLDER)
|
|
753
|
+
);
|
|
754
|
+
results.push({
|
|
755
|
+
kit: kit.name,
|
|
756
|
+
agents,
|
|
757
|
+
skills,
|
|
758
|
+
workflows: commands
|
|
759
|
+
// Still called "workflows" in result for consistency
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
return results;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Copy workflows with transformation to OpenCode command format
|
|
766
|
+
*
|
|
767
|
+
* This method:
|
|
768
|
+
* 1. Reads each workflow file from the kit
|
|
769
|
+
* 2. Transforms the frontmatter to OpenCode command format
|
|
770
|
+
* 3. Replaces path references (.agent/ โ .opencode/)
|
|
771
|
+
* 4. Replaces terminology (workflow โ command)
|
|
772
|
+
* 5. Writes the transformed command to the commands directory
|
|
773
|
+
*/
|
|
774
|
+
async copyWorkflowsWithTransform(kitSourcePath, kitTargetPath, toolPath) {
|
|
775
|
+
const workflowsSource = path5.join(kitSourcePath, "workflows");
|
|
776
|
+
const commandsTarget = path5.join(kitTargetPath, this.COMMANDS_FOLDER);
|
|
777
|
+
try {
|
|
778
|
+
await fs4.access(workflowsSource);
|
|
779
|
+
} catch {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
await fs4.mkdir(commandsTarget, { recursive: true });
|
|
783
|
+
const entries = await fs4.readdir(workflowsSource, { withFileTypes: true });
|
|
784
|
+
for (const entry of entries) {
|
|
785
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
const sourcePath = path5.join(workflowsSource, entry.name);
|
|
789
|
+
const targetPath = path5.join(commandsTarget, entry.name);
|
|
790
|
+
const content = await fs4.readFile(sourcePath, "utf-8");
|
|
791
|
+
const context = {
|
|
792
|
+
aiTool: { path: toolPath },
|
|
793
|
+
sourcePath,
|
|
794
|
+
targetPath
|
|
795
|
+
};
|
|
796
|
+
const transformedContent = this.workflowTransformer.transform(
|
|
797
|
+
content,
|
|
798
|
+
context
|
|
799
|
+
);
|
|
800
|
+
await fs4.writeFile(targetPath, transformedContent);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
// src/installers/index.ts
|
|
806
|
+
var installerRegistry = {
|
|
807
|
+
// Antigravity is the base/default installer
|
|
808
|
+
antigravity: new AntigravityInstaller(),
|
|
809
|
+
// These tools use the same installation logic as Antigravity
|
|
810
|
+
claude: new AntigravityInstaller(),
|
|
811
|
+
gemini: new AntigravityInstaller(),
|
|
812
|
+
codex: new AntigravityInstaller(),
|
|
813
|
+
custom: new AntigravityInstaller(),
|
|
814
|
+
// Cursor has special handling (workflows -> commands)
|
|
815
|
+
cursor: new CursorInstaller(),
|
|
816
|
+
// OpenCode has special handling (workflows -> commands, AGENTS.md at root)
|
|
817
|
+
opencode: new OpenCodeInstaller()
|
|
818
|
+
};
|
|
819
|
+
function getInstaller(toolId) {
|
|
820
|
+
const installer = installerRegistry[toolId];
|
|
821
|
+
if (!installer) {
|
|
822
|
+
return new AntigravityInstaller();
|
|
823
|
+
}
|
|
824
|
+
return installer;
|
|
825
|
+
}
|
|
826
|
+
async function installKit(options) {
|
|
827
|
+
const installer = getInstaller(options.aiTool.id);
|
|
828
|
+
return installer.install(options);
|
|
829
|
+
}
|
|
253
830
|
|
|
254
831
|
// src/cli.ts
|
|
255
832
|
function expandPath(inputPath) {
|
|
256
833
|
if (inputPath.startsWith("~")) {
|
|
257
|
-
return
|
|
834
|
+
return path6.join(os2.homedir(), inputPath.slice(1));
|
|
258
835
|
}
|
|
259
836
|
return inputPath;
|
|
260
837
|
}
|
|
261
838
|
function directoryExists(dirPath) {
|
|
262
839
|
try {
|
|
263
|
-
return
|
|
840
|
+
return fs5.existsSync(dirPath) && fs5.statSync(dirPath).isDirectory();
|
|
264
841
|
} catch {
|
|
265
842
|
return false;
|
|
266
843
|
}
|
|
@@ -269,7 +846,7 @@ function getInstallPath(aiTool, scope, workspacePath) {
|
|
|
269
846
|
if (scope === "global") {
|
|
270
847
|
return getGlobalPath(aiTool);
|
|
271
848
|
}
|
|
272
|
-
return
|
|
849
|
+
return path6.join(workspacePath, aiTool.path);
|
|
273
850
|
}
|
|
274
851
|
function getDisplayPath(absolutePath) {
|
|
275
852
|
const home = os2.homedir();
|
|
@@ -307,7 +884,7 @@ async function main() {
|
|
|
307
884
|
p.intro(pc.bgCyan(pc.black(" SETUP WIZARD ")));
|
|
308
885
|
const aiToolResult = await p.select({
|
|
309
886
|
message: "\u{1F916} Which AI assistant are you using?",
|
|
310
|
-
options: AI_TOOLS.map((tool) => ({
|
|
887
|
+
options: AI_TOOLS.filter((tool) => tool.available).map((tool) => ({
|
|
311
888
|
value: tool.id,
|
|
312
889
|
label: `${tool.name}`,
|
|
313
890
|
hint: `${getGlobalPathDisplay(tool)}`
|
|
@@ -324,7 +901,7 @@ async function main() {
|
|
|
324
901
|
{
|
|
325
902
|
value: "workspace",
|
|
326
903
|
label: "Workspace (Project)",
|
|
327
|
-
hint: `Best for sharing with team (${
|
|
904
|
+
hint: `Best for sharing with team (${path6.join(process.cwd(), aiTool.path)})`
|
|
328
905
|
},
|
|
329
906
|
{
|
|
330
907
|
value: "global",
|
|
@@ -359,7 +936,7 @@ async function main() {
|
|
|
359
936
|
workspacePath = expandPath(pathResult);
|
|
360
937
|
}
|
|
361
938
|
const finalInstallPath = getInstallPath(aiTool, scope, workspacePath);
|
|
362
|
-
const rulesFilePath = scope === "global" || aiTool.rulesInsideKit ?
|
|
939
|
+
const rulesFilePath = scope === "global" || aiTool.rulesInsideKit ? path6.join(finalInstallPath, aiTool.rulesFile) : path6.join(workspacePath, aiTool.rulesFile);
|
|
363
940
|
if (directoryExists(finalInstallPath)) {
|
|
364
941
|
p.log.warn(
|
|
365
942
|
`${pc.yellow("\u26A0")} Existing toolkit found at: ${pc.cyan(getDisplayPath(finalInstallPath))}`
|
|
@@ -400,7 +977,7 @@ async function main() {
|
|
|
400
977
|
if (replaceResult === "replace") {
|
|
401
978
|
const s_rm = p.spinner();
|
|
402
979
|
s_rm.start("Cleaning up old files...");
|
|
403
|
-
|
|
980
|
+
fs5.rmSync(finalInstallPath, { recursive: true, force: true });
|
|
404
981
|
s_rm.stop("Cleanup complete.");
|
|
405
982
|
}
|
|
406
983
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
2
|
+
trigger: always_on
|
|
3
|
+
description: AGT-Kit - AI Agent system rules with 22 agents, 39 skills, 7 commands
|
|
3
4
|
alwaysApply: true
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
#
|
|
7
|
+
# CURSOR Rules - AGT-Kit
|
|
7
8
|
|
|
8
9
|
> AI Agent Capability Expansion Toolkit - This file defines AI behavior in this workspace.
|
|
9
10
|
|
|
@@ -15,7 +16,7 @@ AGT-Kit is a portable, modular AI agent system consisting of:
|
|
|
15
16
|
|
|
16
17
|
- **22 Specialist Agents** - Role-based AI personas
|
|
17
18
|
- **39 Skills** - Domain-specific knowledge modules
|
|
18
|
-
- **7
|
|
19
|
+
- **7 Commands** - Slash command procedures
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
@@ -118,7 +119,9 @@ Agent activated โ Check frontmatter `skills:` โ Read SKILL.md โ Apply.
|
|
|
118
119
|
|
|
119
120
|
---
|
|
120
121
|
|
|
121
|
-
## ๐
|
|
122
|
+
## ๐ COMMANDS (Slash Commands)
|
|
123
|
+
|
|
124
|
+
> **Note:** In Cursor, workflows are called "commands" and stored in `.cursor/commands/`
|
|
122
125
|
|
|
123
126
|
| Command | Description | Agent |
|
|
124
127
|
| -------------- | ------------------------------------ | --------------- |
|
|
@@ -139,10 +142,10 @@ User Request โ Check Profile โ Skill Description Match โ Load SKILL.md โ
|
|
|
139
142
|
|
|
140
143
|
### Profile-Aware Loading
|
|
141
144
|
|
|
142
|
-
> **CRITICAL:** Before loading any skill or selecting any agent, check `.
|
|
145
|
+
> **CRITICAL:** Before loading any skill or selecting any agent, check `.cursor/profile.json`
|
|
143
146
|
|
|
144
147
|
```
|
|
145
|
-
1. Check if `.
|
|
148
|
+
1. Check if `.cursor/profile.json` exists
|
|
146
149
|
2. If EXISTS:
|
|
147
150
|
- Read skills.enabled[] โ Only load these skills
|
|
148
151
|
- Read skills.disabled[] โ Skip these skills
|
|
@@ -190,7 +193,7 @@ Key skills: `api-patterns`, `database-design`, `react-patterns`, `typescript-pat
|
|
|
190
193
|
|
|
191
194
|
> ๐ด Read `ARCHITECTURE.md` at session start.
|
|
192
195
|
|
|
193
|
-
**Paths:** Agents `.
|
|
196
|
+
**Paths:** Agents `.cursor/agents/`, Skills `.cursor/skills/`, Commands `.cursor/commands/`
|
|
194
197
|
|
|
195
198
|
### ๐ง Read โ Understand โ Apply
|
|
196
199
|
|
|
@@ -297,12 +300,12 @@ python3 .agent/scripts/skills_manager.py search <query>
|
|
|
297
300
|
|
|
298
301
|
## ๐ Kit Statistics
|
|
299
302
|
|
|
300
|
-
| Metric
|
|
301
|
-
|
|
|
302
|
-
| Agents
|
|
303
|
-
| Skills
|
|
304
|
-
|
|
|
305
|
-
| Scripts
|
|
303
|
+
| Metric | Count |
|
|
304
|
+
| -------- | ----- |
|
|
305
|
+
| Agents | 22 |
|
|
306
|
+
| Skills | 39 |
|
|
307
|
+
| Commands | 7 |
|
|
308
|
+
| Scripts | 19 |
|
|
306
309
|
|
|
307
310
|
---
|
|
308
311
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neyugn/agent-kits",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Universal AI Agent Toolkit - Skills, Agents, and Workflows for any AI coding assistant",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"codex",
|
|
21
21
|
"cursor",
|
|
22
22
|
"copilot",
|
|
23
|
+
"opencode",
|
|
23
24
|
"workflow",
|
|
24
25
|
"prompt",
|
|
25
26
|
"toolkit"
|