@codenhub/skills 0.0.2
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/LICENSE +201 -0
- package/README.md +53 -0
- package/dist/cli.js +213 -0
- package/package.json +36 -0
- package/src/agents-md-improver/SKILL.md +216 -0
- package/src/agents-md-improver/agents/openai.yaml +4 -0
- package/src/agents-md-improver/references/quality-criteria.md +116 -0
- package/src/agents-md-improver/references/templates.md +255 -0
- package/src/agents-md-improver/references/update-guidelines.md +155 -0
- package/src/brainstorming/SKILL.md +118 -0
- package/src/brainstorming/agents/openai.yaml +4 -0
- package/src/caveman/SKILL.md +59 -0
- package/src/caveman/agents/openai.yaml +4 -0
- package/src/caveman-commit/SKILL.md +68 -0
- package/src/caveman-commit/agents/openai.yaml +4 -0
- package/src/caveman-review/SKILL.md +54 -0
- package/src/caveman-review/agents/openai.yaml +4 -0
- package/src/cli.test.ts +102 -0
- package/src/cli.ts +311 -0
- package/src/executing-plans/SKILL.md +92 -0
- package/src/executing-plans/agents/openai.yaml +4 -0
- package/src/frontend-design/SKILL.md +60 -0
- package/src/frontend-design/agents/openai.yaml +4 -0
- package/src/subagent-specialist/SKILL.md +226 -0
- package/src/subagent-specialist/agents/openai.yaml +4 -0
- package/src/subagent-specialist/references/code-quality-reviewer-prompt.md +48 -0
- package/src/subagent-specialist/references/implementer-prompt.md +84 -0
- package/src/subagent-specialist/references/parallel-investigator-prompt.md +49 -0
- package/src/subagent-specialist/references/spec-reviewer-prompt.md +52 -0
- package/src/test-driven-development/SKILL.md +239 -0
- package/src/test-driven-development/agents/openai.yaml +11 -0
- package/src/test-driven-development/testing-anti-patterns.md +162 -0
- package/src/test-driven-development/verification-baselines.md +42 -0
- package/src/writing-plans/SKILL.md +169 -0
- package/src/writing-plans/agents/openai.yaml +4 -0
- package/src/writing-skills/SKILL.md +222 -0
- package/src/writing-skills/agents/openai.yaml +4 -0
- package/src/writing-skills/best-practices.md +321 -0
- package/src/writing-skills/examples/SKILL_AUTHORING_GUIDE_TESTING.md +156 -0
- package/src/writing-skills/persuasion-principles.md +172 -0
- package/src/writing-skills/testing-skills-with-subagents.md +310 -0
- package/src/writing-specs/SKILL.md +72 -0
- package/src/writing-specs/agents/openai.yaml +4 -0
package/src/cli.ts
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
interface Skill {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
path: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function parseFrontmatter(content: string): Record<string, string> {
|
|
14
|
+
const match = content.match(/^---\r?\n([\s\S]+?)\r?\n---/);
|
|
15
|
+
const metadata: Record<string, string> = {};
|
|
16
|
+
if (!match) {
|
|
17
|
+
return metadata;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const lines = match[1].split(/\r?\n/);
|
|
21
|
+
for (const line of lines) {
|
|
22
|
+
const colonIndex = line.indexOf(":");
|
|
23
|
+
if (colonIndex !== -1) {
|
|
24
|
+
const key = line.slice(0, colonIndex).trim();
|
|
25
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
26
|
+
metadata[key] = value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return metadata;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getSkills(srcDir: string): Skill[] {
|
|
33
|
+
if (!fs.existsSync(srcDir)) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const items = fs.readdirSync(srcDir);
|
|
38
|
+
const skills: Skill[] = [];
|
|
39
|
+
|
|
40
|
+
for (const item of items) {
|
|
41
|
+
const itemPath = path.join(srcDir, item);
|
|
42
|
+
const stat = fs.statSync(itemPath);
|
|
43
|
+
|
|
44
|
+
if (stat.isDirectory()) {
|
|
45
|
+
const skillMdPath = path.join(itemPath, "SKILL.md");
|
|
46
|
+
if (fs.existsSync(skillMdPath)) {
|
|
47
|
+
const content = fs.readFileSync(skillMdPath, "utf8");
|
|
48
|
+
const meta = parseFrontmatter(content);
|
|
49
|
+
skills.push({
|
|
50
|
+
id: item,
|
|
51
|
+
name: meta.name || item,
|
|
52
|
+
description: meta.description || "",
|
|
53
|
+
path: itemPath,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return skills;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function copyRecursiveSync(src: string, dest: string, ignoreList: string[] = []): void {
|
|
63
|
+
const exists = fs.existsSync(src);
|
|
64
|
+
const stats = exists && fs.statSync(src);
|
|
65
|
+
const isDirectory = exists && stats && stats.isDirectory();
|
|
66
|
+
|
|
67
|
+
if (isDirectory) {
|
|
68
|
+
if (!fs.existsSync(dest)) {
|
|
69
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
fs.readdirSync(src).forEach((childItemName) => {
|
|
72
|
+
if (ignoreList.includes(childItemName)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName), ignoreList);
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
const destDir = path.dirname(dest);
|
|
79
|
+
if (!fs.existsSync(destDir)) {
|
|
80
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
fs.copyFileSync(src, dest);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
87
|
+
const __dirname = path.dirname(__filename);
|
|
88
|
+
|
|
89
|
+
// Find skills source directory
|
|
90
|
+
let skillsSrcDir = path.resolve(__dirname, "../src");
|
|
91
|
+
if (
|
|
92
|
+
!fs.existsSync(skillsSrcDir) ||
|
|
93
|
+
!fs.readdirSync(skillsSrcDir).some((f) => fs.statSync(path.join(skillsSrcDir, f)).isDirectory())
|
|
94
|
+
) {
|
|
95
|
+
skillsSrcDir = __dirname;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const home = os.homedir();
|
|
99
|
+
|
|
100
|
+
const HARNESS_MAPPING: Record<string, string> = {
|
|
101
|
+
"Antigravity Global": path.join(home, ".gemini/config/skills"),
|
|
102
|
+
"Antigravity Workspace": path.resolve("./.agents/skills"),
|
|
103
|
+
"OpenCode Global": path.join(home, ".config/opencode/skills"),
|
|
104
|
+
"OpenCode Workspace": path.resolve("./.opencode/skills"),
|
|
105
|
+
"Claude Global": path.join(home, ".claude/skills"),
|
|
106
|
+
"Claude Workspace": path.resolve("./.claude/skills"),
|
|
107
|
+
"Codex Global": path.join(home, ".codex/skills"),
|
|
108
|
+
"Codex Workspace": path.resolve("./.codex/skills"),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const ANSI = {
|
|
112
|
+
HIDE_CURSOR: "\x1b[?25l",
|
|
113
|
+
SHOW_CURSOR: "\x1b[?25h",
|
|
114
|
+
CLEAR_LINE: "\x1b[2K",
|
|
115
|
+
CURSOR_UP: (n: number) => `\x1b[${n}A`,
|
|
116
|
+
RESET: "\x1b[0m",
|
|
117
|
+
BOLD: "\x1b[1m",
|
|
118
|
+
DIM: "\x1b[2m",
|
|
119
|
+
CYAN: "\x1b[36m",
|
|
120
|
+
GREEN: "\x1b[32m",
|
|
121
|
+
RED: "\x1b[31m",
|
|
122
|
+
BLUE: "\x1b[34m",
|
|
123
|
+
YELLOW: "\x1b[33m",
|
|
124
|
+
WHITE: "\x1b[37m",
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const CONSTANTS = {
|
|
128
|
+
CODEX_IDENTIFIER: "Codex",
|
|
129
|
+
EXCLUDE_FOLDER_AGENTS: "agents",
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
interface Choice {
|
|
133
|
+
name: string;
|
|
134
|
+
value: string;
|
|
135
|
+
checked: boolean;
|
|
136
|
+
description?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function checkboxPrompt(message: string, choices: Choice[]): Promise<string[]> {
|
|
140
|
+
return new Promise((resolve) => {
|
|
141
|
+
const stdout = process.stdout;
|
|
142
|
+
if (!process.stdin.isTTY) {
|
|
143
|
+
resolve(choices.filter((c) => c.checked).map((c) => c.value));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
let cursor = 0;
|
|
147
|
+
|
|
148
|
+
// Hide terminal cursor
|
|
149
|
+
stdout.write(ANSI.HIDE_CURSOR);
|
|
150
|
+
|
|
151
|
+
function render(first = false) {
|
|
152
|
+
if (!first) {
|
|
153
|
+
// Move cursor up to overwrite previous render
|
|
154
|
+
const linesToMove = choices.length + 2;
|
|
155
|
+
stdout.write(ANSI.CURSOR_UP(linesToMove));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Title/Message
|
|
159
|
+
stdout.write(`${ANSI.BOLD}${ANSI.CYAN}? ${ANSI.WHITE}${message}${ANSI.RESET}\n`);
|
|
160
|
+
|
|
161
|
+
// Choices
|
|
162
|
+
choices.forEach((choice, index) => {
|
|
163
|
+
const isCurrent = index === cursor;
|
|
164
|
+
const pointer = isCurrent ? `${ANSI.CYAN}❯${ANSI.RESET}` : " ";
|
|
165
|
+
const checkbox = choice.checked ? `${ANSI.GREEN}[◼]${ANSI.RESET}` : "[ ]";
|
|
166
|
+
const name = isCurrent ? `${ANSI.CYAN}${ANSI.BOLD}${choice.name}${ANSI.RESET}` : choice.name;
|
|
167
|
+
const desc = choice.description ? ` ${ANSI.DIM}(${choice.description})${ANSI.RESET}` : "";
|
|
168
|
+
|
|
169
|
+
stdout.write(`${ANSI.CLEAR_LINE}${pointer} ${checkbox} ${name}${desc}\n`);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Instructions
|
|
173
|
+
stdout.write(
|
|
174
|
+
`${ANSI.CLEAR_LINE}${ANSI.DIM}(Use arrows to navigate, Space to toggle, Enter to confirm, Ctrl+C to exit)${ANSI.RESET}\n`,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
render(true);
|
|
179
|
+
|
|
180
|
+
function onKeypress(_str: string | undefined, key: { ctrl?: boolean; name?: string } | undefined) {
|
|
181
|
+
if (key && key.ctrl && key.name === "c") {
|
|
182
|
+
cleanup();
|
|
183
|
+
stdout.write(`\n${ANSI.RED}Installation cancelled.${ANSI.RESET}\n`);
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!key) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
switch (key.name) {
|
|
192
|
+
case "up":
|
|
193
|
+
cursor = (cursor - 1 + choices.length) % choices.length;
|
|
194
|
+
render();
|
|
195
|
+
break;
|
|
196
|
+
case "down":
|
|
197
|
+
cursor = (cursor + 1) % choices.length;
|
|
198
|
+
render();
|
|
199
|
+
break;
|
|
200
|
+
case "space":
|
|
201
|
+
choices[cursor].checked = !choices[cursor].checked;
|
|
202
|
+
render();
|
|
203
|
+
break;
|
|
204
|
+
case "return":
|
|
205
|
+
cleanup();
|
|
206
|
+
const selectedValues = choices.filter((c) => c.checked).map((c) => c.value);
|
|
207
|
+
stdout.write(`${ANSI.CLEAR_LINE}\r${ANSI.GREEN}✔${ANSI.RESET} Selection confirmed.\n`);
|
|
208
|
+
resolve(selectedValues);
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function cleanup() {
|
|
214
|
+
process.stdin.removeListener("keypress", onKeypress);
|
|
215
|
+
if (process.stdin.isTTY) {
|
|
216
|
+
process.stdin.setRawMode(false);
|
|
217
|
+
}
|
|
218
|
+
process.stdin.pause();
|
|
219
|
+
stdout.write(ANSI.SHOW_CURSOR); // Show cursor
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Setup keypress listener
|
|
223
|
+
if (process.stdin.isTTY) {
|
|
224
|
+
process.stdin.setRawMode(true);
|
|
225
|
+
}
|
|
226
|
+
process.stdin.resume();
|
|
227
|
+
process.stdin.setEncoding("utf8");
|
|
228
|
+
|
|
229
|
+
const readline = require("readline");
|
|
230
|
+
readline.emitKeypressEvents(process.stdin);
|
|
231
|
+
|
|
232
|
+
process.stdin.on("keypress", onKeypress);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Helper to use require safely in ESM
|
|
237
|
+
import { createRequire } from "module";
|
|
238
|
+
const require = createRequire(import.meta.url);
|
|
239
|
+
|
|
240
|
+
async function main() {
|
|
241
|
+
console.log(`\n${ANSI.BOLD}${ANSI.CYAN}=========================================${ANSI.RESET}`);
|
|
242
|
+
console.log(`${ANSI.BOLD}${ANSI.CYAN} Codenhub AI Agent Skills Installer${ANSI.RESET}`);
|
|
243
|
+
console.log(`${ANSI.BOLD}${ANSI.CYAN}=========================================${ANSI.RESET}\n`);
|
|
244
|
+
|
|
245
|
+
const skills = getSkills(skillsSrcDir);
|
|
246
|
+
if (skills.length === 0) {
|
|
247
|
+
console.error(`${ANSI.RED}Error: No skills found in source directory.${ANSI.RESET}`);
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 1. Prompt for skills selection
|
|
252
|
+
const skillChoices: Choice[] = skills.map((s) => ({
|
|
253
|
+
name: s.name,
|
|
254
|
+
value: s.id,
|
|
255
|
+
checked: true,
|
|
256
|
+
description: s.description,
|
|
257
|
+
}));
|
|
258
|
+
|
|
259
|
+
const selectedSkills = await checkboxPrompt("Which skills do you want to install?", skillChoices);
|
|
260
|
+
if (selectedSkills.length === 0) {
|
|
261
|
+
console.log(`\n${ANSI.YELLOW}No skills selected. Exiting.${ANSI.RESET}`);
|
|
262
|
+
process.exit(0);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// 2. Prompt for harnesses selection
|
|
266
|
+
const harnessChoices: Choice[] = Object.keys(HARNESS_MAPPING).map((name) => ({
|
|
267
|
+
name,
|
|
268
|
+
value: name,
|
|
269
|
+
checked: true,
|
|
270
|
+
description: HARNESS_MAPPING[name],
|
|
271
|
+
}));
|
|
272
|
+
|
|
273
|
+
const selectedHarnesses = await checkboxPrompt("Which harnesses do you want to install to?", harnessChoices);
|
|
274
|
+
if (selectedHarnesses.length === 0) {
|
|
275
|
+
console.log(`\n${ANSI.YELLOW}No harnesses selected. Exiting.${ANSI.RESET}`);
|
|
276
|
+
process.exit(0);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
console.log(`\n${ANSI.BOLD}Installing skills...${ANSI.RESET}\n`);
|
|
280
|
+
|
|
281
|
+
for (const harness of selectedHarnesses) {
|
|
282
|
+
const destBaseDir = HARNESS_MAPPING[harness];
|
|
283
|
+
const isCodex = harness.includes(CONSTANTS.CODEX_IDENTIFIER);
|
|
284
|
+
console.log(`${ANSI.BLUE}→ Installing to ${harness}...${ANSI.RESET}`);
|
|
285
|
+
|
|
286
|
+
for (const skillId of selectedSkills) {
|
|
287
|
+
const skill = skills.find((s) => s.id === skillId);
|
|
288
|
+
if (!skill) {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const destSkillDir = path.join(destBaseDir, skillId);
|
|
293
|
+
try {
|
|
294
|
+
copyRecursiveSync(skill.path, destSkillDir, isCodex ? [] : [CONSTANTS.EXCLUDE_FOLDER_AGENTS]);
|
|
295
|
+
console.log(` ${ANSI.GREEN}✔${ANSI.RESET} Copied: ${skill.name}`);
|
|
296
|
+
} catch (err: unknown) {
|
|
297
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
298
|
+
console.error(` ${ANSI.RED}✘${ANSI.RESET} Failed copying ${skill.name}: ${msg}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
console.log(`\n${ANSI.GREEN}${ANSI.BOLD}✔ All selected skills successfully installed/updated!${ANSI.RESET}\n`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (typeof process !== "undefined" && !process.env.VITEST) {
|
|
307
|
+
main().catch((err) => {
|
|
308
|
+
console.error(`${ANSI.RED}Unhandled exception:${ANSI.RESET}`, err);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: executing-plans
|
|
3
|
+
description: Use when you have a written implementation plan to execute in a separate session with review checkpoints.
|
|
4
|
+
metadata:
|
|
5
|
+
short-description: Execute implementation plans step by step
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Executing Plans
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Load the plan, confirm documented approval, review it critically, execute all tasks, and report when complete.
|
|
13
|
+
|
|
14
|
+
**Announce at start:** "I'm using the executing-plans skill to implement this plan."
|
|
15
|
+
|
|
16
|
+
Prefer delegated execution via subagents when practical. Use inline execution when subagents are unavailable, the work is too tightly coupled to split cleanly, or the user explicitly prefers inline.
|
|
17
|
+
|
|
18
|
+
Default git workflow: work on a new branch, make atomic commits as clean milestones land, and open a PR at the end. These are soft defaults; follow repo conventions or explicit user instructions when they differ.
|
|
19
|
+
|
|
20
|
+
## Tool Compatibility
|
|
21
|
+
|
|
22
|
+
- Keep instructions tool-agnostic and avoid provider-specific wording.
|
|
23
|
+
- When behavior differs across tools, resolve conflicts in this order: OpenCode > Claude Code > Codex CLI > Gemini CLI.
|
|
24
|
+
|
|
25
|
+
## The Process
|
|
26
|
+
|
|
27
|
+
### Step 1: Load and Review Plan
|
|
28
|
+
|
|
29
|
+
1. Read the plan file and any referenced spec.
|
|
30
|
+
2. Confirm the plan is documented as `Approved`, and confirm the referenced spec is also documented as `Approved`.
|
|
31
|
+
3. If either document is not documented as approved, stop and ask. Only continue without documented approval if the user explicitly tells you to.
|
|
32
|
+
4. Review the plan critically and identify any questions or concerns about it.
|
|
33
|
+
5. If there are concerns, raise them with the human partner before starting.
|
|
34
|
+
6. If there are no concerns, create or update the session plan tracker and proceed.
|
|
35
|
+
7. If you are not already on an appropriate working branch, create a new one before implementation unless the repo or user calls for another approach.
|
|
36
|
+
|
|
37
|
+
### Step 2: Execute Tasks
|
|
38
|
+
|
|
39
|
+
For each task:
|
|
40
|
+
|
|
41
|
+
1. Prefer dispatching a fresh subagent with task-local context when practical.
|
|
42
|
+
2. Mark it as `in_progress`.
|
|
43
|
+
3. Follow each step exactly, whether delegated or inline. The plan should already contain bite-sized steps.
|
|
44
|
+
4. Review the resulting artifacts and run verifications as specified.
|
|
45
|
+
5. Make an atomic commit when the task or another clean milestone is complete, if the workflow allows it.
|
|
46
|
+
6. Mark it as completed.
|
|
47
|
+
|
|
48
|
+
### Step 3: Complete Development
|
|
49
|
+
|
|
50
|
+
After all tasks are complete and verified:
|
|
51
|
+
|
|
52
|
+
- Run the final verification the plan requires.
|
|
53
|
+
- Summarize what changed, what was verified, and any open issues.
|
|
54
|
+
- Suggest updating the relevant spec and plan docs to reflect the completed work.
|
|
55
|
+
- If the user wants you to make those doc updates, do them explicitly. Never assume approval or completion status on your own.
|
|
56
|
+
- If the usual git workflow applies, make sure the work stays on its branch and open a PR before closing out.
|
|
57
|
+
|
|
58
|
+
## When to Stop and Ask for Help
|
|
59
|
+
|
|
60
|
+
**STOP executing immediately when:**
|
|
61
|
+
|
|
62
|
+
- You hit a blocker: missing dependency, test fails, instruction unclear.
|
|
63
|
+
- The plan has critical gaps preventing a safe start.
|
|
64
|
+
- You do not understand an instruction.
|
|
65
|
+
- Verification fails repeatedly.
|
|
66
|
+
|
|
67
|
+
Ask for clarification rather than guessing.
|
|
68
|
+
|
|
69
|
+
## When to Revisit Earlier Steps
|
|
70
|
+
|
|
71
|
+
**Return to Review (Step 1) when:**
|
|
72
|
+
|
|
73
|
+
- The partner updates the plan based on your feedback.
|
|
74
|
+
- The fundamental approach needs rethinking.
|
|
75
|
+
|
|
76
|
+
Do not force through blockers. Stop and ask.
|
|
77
|
+
|
|
78
|
+
## Remember
|
|
79
|
+
|
|
80
|
+
- Review the plan critically first.
|
|
81
|
+
- Check documented approval before starting implementation.
|
|
82
|
+
- Follow plan steps exactly.
|
|
83
|
+
- Do not skip verifications.
|
|
84
|
+
- Stop when blocked, do not guess.
|
|
85
|
+
- Never start implementation on `main` or `master` without explicit user consent.
|
|
86
|
+
|
|
87
|
+
## Integration
|
|
88
|
+
|
|
89
|
+
Related workflow skills:
|
|
90
|
+
|
|
91
|
+
- `writing-plans` - creates the plan this skill executes
|
|
92
|
+
- `subagent-specialist` - preferred when subagent-based or parallel execution fits the plan
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Executing Plans"
|
|
3
|
+
short_description: "Execute written plans with review checkpoints"
|
|
4
|
+
default_prompt: "Use $executing-plans to load the plan, confirm the plan and spec are documented as approved before execution unless the user explicitly says otherwise, prefer subagent-based execution, work on a new branch with atomic commits, open a PR at the end when appropriate, and suggest doc status updates when finished."
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
This skill guides the coding agent in creating distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
7
|
+
|
|
8
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
9
|
+
|
|
10
|
+
## Tool Compatibility
|
|
11
|
+
|
|
12
|
+
- Keep instructions tool-agnostic and avoid provider-specific wording.
|
|
13
|
+
- When behavior differs across tools, resolve conflicts in this order: OpenCode > Claude Code > Codex CLI > Gemini CLI.
|
|
14
|
+
|
|
15
|
+
## Design Thinking
|
|
16
|
+
|
|
17
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
18
|
+
|
|
19
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
20
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
|
21
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
22
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
23
|
+
|
|
24
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
|
25
|
+
|
|
26
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
27
|
+
|
|
28
|
+
- Production-grade and functional
|
|
29
|
+
- Visually striking and memorable
|
|
30
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
31
|
+
- Meticulously refined in every detail
|
|
32
|
+
|
|
33
|
+
## Frontend Aesthetics Guidelines
|
|
34
|
+
|
|
35
|
+
Focus on:
|
|
36
|
+
|
|
37
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
38
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
39
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
|
40
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
41
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
|
42
|
+
|
|
43
|
+
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
|
44
|
+
|
|
45
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
|
46
|
+
|
|
47
|
+
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
|
48
|
+
|
|
49
|
+
## Execution Guidance
|
|
50
|
+
|
|
51
|
+
When applying this skill:
|
|
52
|
+
|
|
53
|
+
- Build the requested interface directly instead of stopping at ideas or mock descriptions.
|
|
54
|
+
- Preserve the existing design system, component patterns, and frontend architecture when working inside an established codebase.
|
|
55
|
+
- Use the strongest visual direction that still fits the product and the repository's technical constraints.
|
|
56
|
+
- Refine the result for both desktop and mobile instead of treating responsiveness as a follow-up.
|
|
57
|
+
- Prefer modern, production-ready framework patterns already present in the codebase instead of introducing novelty for its own sake.
|
|
58
|
+
- Push toward concrete design decisions, polished implementation details, and cohesive execution rather than generic safe choices.
|
|
59
|
+
|
|
60
|
+
Remember: strong creative results come from a clear aesthetic direction and enough room to execute it with conviction. Do not hold back; think outside the box and commit fully to a distinctive vision.
|