opencodekit 0.2.4 → 0.2.6
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/dist/index.js +1 -1
- package/dist/template/.opencode/dcp.jsonc +41 -32
- package/dist/template/.opencode/opencode.json +430 -430
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/plugin/superpowers.ts +227 -288
- package/package.json +1 -1
- /package/dist/template/.opencode/{superpowers/skills → skills}/brainstorming/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/condition-based-waiting/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/condition-based-waiting/example.ts +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/defense-in-depth/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/dispatching-parallel-agents/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/executing-plans/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/finishing-a-development-branch/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/frontend-aesthetics/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/gemini-large-context/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/receiving-code-review/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/requesting-code-review/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/requesting-code-review/code-reviewer.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/root-cause-tracing/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/root-cause-tracing/find-polluter.sh +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/sharing-skills/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/subagent-driven-development/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/CREATION-LOG.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/test-academic.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/test-pressure-1.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/test-pressure-2.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/test-pressure-3.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/test-driven-development/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/testing-anti-patterns/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/testing-skills-with-subagents/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/testing-skills-with-subagents/examples/CLAUDE_MD_TESTING.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/ui-ux-research/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/using-git-worktrees/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/using-superpowers/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/verification-before-completion/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/writing-plans/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/writing-skills/SKILL.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/writing-skills/anthropic-best-practices.md +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/writing-skills/graphviz-conventions.dot +0 -0
- /package/dist/template/.opencode/{superpowers/skills → skills}/writing-skills/persuasion-principles.md +0 -0
|
@@ -5,28 +5,28 @@
|
|
|
5
5
|
* Skills are loaded on-demand via use_skill tool, not auto-injected.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import path from "path";
|
|
9
8
|
import fs from "fs";
|
|
10
9
|
import os from "os";
|
|
10
|
+
import path from "path";
|
|
11
11
|
import { type Plugin, tool } from "@opencode-ai/plugin";
|
|
12
12
|
|
|
13
13
|
interface SkillResolution {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
skillFile: string;
|
|
15
|
+
sourceType: "project" | "personal";
|
|
16
|
+
skillPath: string;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
interface SkillInfo {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
path: string;
|
|
21
|
+
skillFile: string;
|
|
22
|
+
name: string;
|
|
23
|
+
description: string;
|
|
24
|
+
sourceType: "project" | "personal";
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
interface Frontmatter {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// ============================================
|
|
@@ -34,142 +34,97 @@ interface Frontmatter {
|
|
|
34
34
|
// ============================================
|
|
35
35
|
|
|
36
36
|
function extractFrontmatter(filePath: string): Frontmatter {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
37
|
+
try {
|
|
38
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
39
|
+
const lines = content.split("\n");
|
|
40
|
+
|
|
41
|
+
let inFrontmatter = false;
|
|
42
|
+
let name = "";
|
|
43
|
+
let description = "";
|
|
44
|
+
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
if (line.trim() === "---") {
|
|
47
|
+
if (inFrontmatter) break;
|
|
48
|
+
inFrontmatter = true;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (inFrontmatter) {
|
|
53
|
+
const match = line.match(/^(\w+):\s*(.*)$/);
|
|
54
|
+
if (match) {
|
|
55
|
+
const [, key, value] = match;
|
|
56
|
+
if (key === "name") name = value.trim();
|
|
57
|
+
if (key === "description") description = value.trim();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { name, description };
|
|
63
|
+
} catch {
|
|
64
|
+
return { name: "", description: "" };
|
|
65
|
+
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function findSkillsInDir(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
dir: string,
|
|
70
|
+
sourceType: "project" | "personal",
|
|
71
|
+
maxDepth = 3,
|
|
72
72
|
): SkillInfo[] {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function resolveSkillPath(
|
|
107
|
-
skillName: string,
|
|
108
|
-
superpowersDir: string,
|
|
109
|
-
personalDir: string,
|
|
110
|
-
): SkillResolution | null {
|
|
111
|
-
const forceSuperpowers = skillName.startsWith("superpowers:");
|
|
112
|
-
const actualSkillName = forceSuperpowers
|
|
113
|
-
? skillName.replace(/^superpowers:/, "")
|
|
114
|
-
: skillName;
|
|
115
|
-
|
|
116
|
-
// Try personal skills first (unless explicitly superpowers:)
|
|
117
|
-
if (!forceSuperpowers && personalDir) {
|
|
118
|
-
const personalSkillFile = path.join(
|
|
119
|
-
personalDir,
|
|
120
|
-
actualSkillName,
|
|
121
|
-
"SKILL.md",
|
|
122
|
-
);
|
|
123
|
-
if (fs.existsSync(personalSkillFile)) {
|
|
124
|
-
return {
|
|
125
|
-
skillFile: personalSkillFile,
|
|
126
|
-
sourceType: "personal",
|
|
127
|
-
skillPath: actualSkillName,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Try superpowers skills
|
|
133
|
-
if (superpowersDir) {
|
|
134
|
-
const superpowersSkillFile = path.join(
|
|
135
|
-
superpowersDir,
|
|
136
|
-
actualSkillName,
|
|
137
|
-
"SKILL.md",
|
|
138
|
-
);
|
|
139
|
-
if (fs.existsSync(superpowersSkillFile)) {
|
|
140
|
-
return {
|
|
141
|
-
skillFile: superpowersSkillFile,
|
|
142
|
-
sourceType: "superpowers",
|
|
143
|
-
skillPath: actualSkillName,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return null;
|
|
73
|
+
const skills: SkillInfo[] = [];
|
|
74
|
+
|
|
75
|
+
if (!fs.existsSync(dir)) return skills;
|
|
76
|
+
|
|
77
|
+
function recurse(currentDir: string, depth: number) {
|
|
78
|
+
if (depth > maxDepth) return;
|
|
79
|
+
|
|
80
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
81
|
+
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
84
|
+
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
const skillFile = path.join(fullPath, "SKILL.md");
|
|
87
|
+
if (fs.existsSync(skillFile)) {
|
|
88
|
+
const { name, description } = extractFrontmatter(skillFile);
|
|
89
|
+
skills.push({
|
|
90
|
+
path: fullPath,
|
|
91
|
+
skillFile,
|
|
92
|
+
name: name || entry.name,
|
|
93
|
+
description: description || "",
|
|
94
|
+
sourceType,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
recurse(fullPath, depth + 1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
recurse(dir, 0);
|
|
103
|
+
return skills;
|
|
149
104
|
}
|
|
150
105
|
|
|
151
106
|
function stripFrontmatter(content: string): string {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
107
|
+
const lines = content.split("\n");
|
|
108
|
+
let inFrontmatter = false;
|
|
109
|
+
let frontmatterEnded = false;
|
|
110
|
+
const contentLines: string[] = [];
|
|
111
|
+
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
if (line.trim() === "---") {
|
|
114
|
+
if (inFrontmatter) {
|
|
115
|
+
frontmatterEnded = true;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
inFrontmatter = true;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (frontmatterEnded || !inFrontmatter) {
|
|
123
|
+
contentLines.push(line);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return contentLines.join("\n").trim();
|
|
173
128
|
}
|
|
174
129
|
|
|
175
130
|
// ============================================
|
|
@@ -177,156 +132,140 @@ function stripFrontmatter(content: string): string {
|
|
|
177
132
|
// ============================================
|
|
178
133
|
|
|
179
134
|
export const SuperpowersPlugin: Plugin = async ({ client, directory }) => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
135
|
+
const homeDir = os.homedir();
|
|
136
|
+
const projectSkillsDir = path.join(directory, ".opencode/skills");
|
|
137
|
+
const personalSkillsDir = path.join(homeDir, ".config/opencode/skills");
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
tool: {
|
|
141
|
+
use_skill: tool({
|
|
142
|
+
description:
|
|
143
|
+
"Load and read a specific skill to guide your work. Skills contain proven workflows, mandatory processes, and expert techniques.",
|
|
144
|
+
args: {
|
|
145
|
+
skill_name: tool.schema
|
|
146
|
+
.string()
|
|
147
|
+
.describe(
|
|
148
|
+
'Name of the skill to load (e.g., "superpowers:brainstorming", "my-custom-skill", or "project:my-skill")',
|
|
149
|
+
),
|
|
150
|
+
},
|
|
151
|
+
execute: async (
|
|
152
|
+
args: { skill_name: string },
|
|
153
|
+
context: { sessionID: string },
|
|
154
|
+
) => {
|
|
155
|
+
const { skill_name } = args;
|
|
156
|
+
|
|
157
|
+
// Resolve with priority: project > personal > superpowers
|
|
158
|
+
const forceProject = skill_name.startsWith("project:");
|
|
159
|
+
const actualSkillName = forceProject
|
|
160
|
+
? skill_name.replace(/^project:/, "")
|
|
161
|
+
: skill_name;
|
|
162
|
+
|
|
163
|
+
let resolved: SkillResolution | null = null;
|
|
164
|
+
|
|
165
|
+
// Try project skills first
|
|
166
|
+
if (forceProject || !skill_name.startsWith("superpowers:")) {
|
|
167
|
+
const projectSkillFile = path.join(
|
|
168
|
+
projectSkillsDir,
|
|
169
|
+
actualSkillName,
|
|
170
|
+
"SKILL.md",
|
|
171
|
+
);
|
|
172
|
+
if (fs.existsSync(projectSkillFile)) {
|
|
173
|
+
resolved = {
|
|
174
|
+
skillFile: projectSkillFile,
|
|
175
|
+
sourceType: "project",
|
|
176
|
+
skillPath: actualSkillName,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Fall back to personal resolution
|
|
182
|
+
if (!resolved && !forceProject) {
|
|
183
|
+
const personalSkillFile = path.join(
|
|
184
|
+
personalSkillsDir,
|
|
185
|
+
skill_name,
|
|
186
|
+
"SKILL.md",
|
|
187
|
+
);
|
|
188
|
+
if (fs.existsSync(personalSkillFile)) {
|
|
189
|
+
resolved = {
|
|
190
|
+
skillFile: personalSkillFile,
|
|
191
|
+
sourceType: "personal",
|
|
192
|
+
skillPath: skill_name,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!resolved) {
|
|
198
|
+
return `Error: Skill "${skill_name}" not found.\n\nRun find_skills to see available skills.`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const fullContent = fs.readFileSync(resolved.skillFile, "utf8");
|
|
202
|
+
const { name, description } = extractFrontmatter(resolved.skillFile);
|
|
203
|
+
const content = stripFrontmatter(fullContent);
|
|
204
|
+
const skillDirectory = path.dirname(resolved.skillFile);
|
|
205
|
+
|
|
206
|
+
const skillHeader = `# ${name || skill_name}
|
|
249
207
|
# ${description || ""}
|
|
250
208
|
# Supporting tools and docs are in ${skillDirectory}
|
|
251
209
|
# ============================================`;
|
|
252
210
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
namespace = "";
|
|
314
|
-
break;
|
|
315
|
-
default:
|
|
316
|
-
namespace = "superpowers:";
|
|
317
|
-
}
|
|
318
|
-
const skillName = skill.name || path.basename(skill.path);
|
|
319
|
-
|
|
320
|
-
output += `${namespace}${skillName}\n`;
|
|
321
|
-
if (skill.description) {
|
|
322
|
-
output += ` ${skill.description}\n`;
|
|
323
|
-
}
|
|
324
|
-
output += ` Directory: ${skill.path}\n\n`;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return output;
|
|
328
|
-
},
|
|
329
|
-
}),
|
|
330
|
-
},
|
|
331
|
-
};
|
|
211
|
+
// Insert as user message with noReply for persistence across compaction
|
|
212
|
+
try {
|
|
213
|
+
await client.session.prompt({
|
|
214
|
+
path: { id: context.sessionID },
|
|
215
|
+
body: {
|
|
216
|
+
noReply: true,
|
|
217
|
+
parts: [
|
|
218
|
+
{
|
|
219
|
+
type: "text",
|
|
220
|
+
text: `Loading skill: ${name || skill_name}`,
|
|
221
|
+
},
|
|
222
|
+
{ type: "text", text: `${skillHeader}\n\n${content}` },
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
} catch {
|
|
227
|
+
// Fallback: return content directly if message insertion fails
|
|
228
|
+
return `${skillHeader}\n\n${content}`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return `Launching skill: ${name || skill_name}`;
|
|
232
|
+
},
|
|
233
|
+
}),
|
|
234
|
+
|
|
235
|
+
find_skills: tool({
|
|
236
|
+
description:
|
|
237
|
+
"List all available skills in the project, personal, and superpowers skill libraries.",
|
|
238
|
+
args: {},
|
|
239
|
+
execute: async () => {
|
|
240
|
+
const projectSkills = findSkillsInDir(projectSkillsDir, "project", 3);
|
|
241
|
+
const personalSkills = findSkillsInDir(
|
|
242
|
+
personalSkillsDir,
|
|
243
|
+
"personal",
|
|
244
|
+
3,
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const allSkills = [...projectSkills, ...personalSkills];
|
|
248
|
+
|
|
249
|
+
if (allSkills.length === 0) {
|
|
250
|
+
return "No skills found. Add project skills to .opencode/skills/ or personal skills to ~/.config/opencode/skills/";
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
let output = "Available skills:\n\n";
|
|
254
|
+
|
|
255
|
+
for (const skill of allSkills) {
|
|
256
|
+
const namespace = skill.sourceType === "project" ? "project:" : "";
|
|
257
|
+
const skillName = skill.name || path.basename(skill.path);
|
|
258
|
+
|
|
259
|
+
output += `${namespace}${skillName}\n`;
|
|
260
|
+
if (skill.description) {
|
|
261
|
+
output += ` ${skill.description}\n`;
|
|
262
|
+
}
|
|
263
|
+
output += ` Directory: ${skill.path}\n\n`;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return output;
|
|
267
|
+
},
|
|
268
|
+
}),
|
|
269
|
+
},
|
|
270
|
+
};
|
|
332
271
|
};
|
package/package.json
CHANGED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/condition-based-waiting/SKILL.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/condition-based-waiting/example.ts
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/dispatching-parallel-agents/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/gemini-large-context/SKILL.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/receiving-code-review/SKILL.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/requesting-code-review/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/root-cause-tracing/find-polluter.sh
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/subagent-driven-development/SKILL.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/CREATION-LOG.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/SKILL.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/systematic-debugging/test-academic.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/test-driven-development/SKILL.md
RENAMED
|
File without changes
|
/package/dist/template/.opencode/{superpowers/skills → skills}/testing-anti-patterns/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|