cc-dev-template 0.1.46 → 0.1.49
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/bin/install.js +54 -8
- package/package.json +4 -2
- package/src/scripts/env-config.json +5 -0
- package/src/scripts/statusline.js +129 -38
- package/src/skills/creating-agent-skills/SKILL.md +7 -43
- package/src/skills/creating-agent-skills/references/create-step-1-understand.md +42 -0
- package/src/skills/creating-agent-skills/references/create-step-2-design.md +113 -0
- package/src/skills/creating-agent-skills/references/create-step-3-write.md +177 -0
- package/src/skills/creating-agent-skills/references/create-step-4-review.md +63 -0
- package/src/skills/creating-agent-skills/references/create-step-5-install.md +39 -0
- package/src/skills/creating-agent-skills/references/fix-step-1-diagnose.md +83 -0
- package/src/skills/creating-agent-skills/references/fix-step-2-apply.md +90 -0
- package/src/skills/creating-agent-skills/references/fix-step-3-validate.md +52 -0
- package/src/hooks/bash-precheck-hook.json +0 -15
- package/src/hooks/bash-precheck.sh +0 -117
- package/src/skills/creating-agent-skills/references/audit.md +0 -121
- package/src/skills/creating-agent-skills/references/create.md +0 -157
- package/src/skills/creating-agent-skills/references/modify.md +0 -131
- package/src/skills/creating-agent-skills/references/principles.md +0 -345
package/bin/install.js
CHANGED
|
@@ -233,7 +233,7 @@ if (fs.existsSync(mergeSettingsPath)) {
|
|
|
233
233
|
{ file: 'read-guard-hook.json', name: 'Context guard for large reads' },
|
|
234
234
|
{ file: 'statusline-config.json', name: 'Custom status line' },
|
|
235
235
|
{ file: 'bash-overflow-hook.json', name: 'Bash overflow guard hook' },
|
|
236
|
-
{ file: '
|
|
236
|
+
{ file: 'env-config.json', name: 'Environment variables' }
|
|
237
237
|
];
|
|
238
238
|
|
|
239
239
|
configs.forEach(({ file, name }) => {
|
|
@@ -251,23 +251,69 @@ if (fs.existsSync(mergeSettingsPath)) {
|
|
|
251
251
|
});
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
// Remove deprecated
|
|
254
|
+
// Remove deprecated files and settings
|
|
255
255
|
console.log('\nCleanup:');
|
|
256
|
+
let cleanupPerformed = false;
|
|
257
|
+
|
|
258
|
+
// Remove deprecated bash wrapper files
|
|
259
|
+
const deprecatedFiles = [
|
|
260
|
+
path.join(CLAUDE_DIR, 'hooks', 'bash-precheck.sh'),
|
|
261
|
+
path.join(CLAUDE_DIR, 'hooks', 'bash-wrapper-helper.sh'),
|
|
262
|
+
path.join(CLAUDE_DIR, 'scripts', 'bash-precheck-hook.json')
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
deprecatedFiles.forEach(file => {
|
|
266
|
+
if (fs.existsSync(file)) {
|
|
267
|
+
fs.unlinkSync(file);
|
|
268
|
+
console.log(`✓ Removed deprecated ${path.basename(file)}`);
|
|
269
|
+
cleanupPerformed = true;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Remove deprecated hooks from settings.json
|
|
256
274
|
if (fs.existsSync(settingsFile)) {
|
|
257
275
|
try {
|
|
258
276
|
const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
277
|
+
let settingsModified = false;
|
|
278
|
+
|
|
279
|
+
// Remove deprecated code-simplifier plugin
|
|
259
280
|
if (settings.enabledPlugins && settings.enabledPlugins['code-simplifier@claude-plugins-official']) {
|
|
260
281
|
delete settings.enabledPlugins['code-simplifier@claude-plugins-official'];
|
|
261
|
-
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
|
|
262
282
|
console.log('✓ Removed deprecated code-simplifier plugin');
|
|
263
|
-
|
|
264
|
-
|
|
283
|
+
settingsModified = true;
|
|
284
|
+
cleanupPerformed = true;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Remove bash-precheck hooks from settings
|
|
288
|
+
if (settings.hooks) {
|
|
289
|
+
const hookTypes = ['PreToolUse', 'PostToolUse'];
|
|
290
|
+
hookTypes.forEach(hookType => {
|
|
291
|
+
if (settings.hooks[hookType] && Array.isArray(settings.hooks[hookType])) {
|
|
292
|
+
const originalLength = settings.hooks[hookType].length;
|
|
293
|
+
settings.hooks[hookType] = settings.hooks[hookType].filter(hook => {
|
|
294
|
+
const command = hook.hooks?.[0]?.command || '';
|
|
295
|
+
return !command.includes('bash-precheck');
|
|
296
|
+
});
|
|
297
|
+
if (settings.hooks[hookType].length < originalLength) {
|
|
298
|
+
console.log(`✓ Removed deprecated bash-precheck hook from ${hookType}`);
|
|
299
|
+
settingsModified = true;
|
|
300
|
+
cleanupPerformed = true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
if (settingsModified) {
|
|
308
|
+
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
|
|
265
309
|
}
|
|
266
310
|
} catch (e) {
|
|
267
|
-
|
|
311
|
+
// Ignore errors reading settings
|
|
268
312
|
}
|
|
269
|
-
}
|
|
270
|
-
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (!cleanupPerformed) {
|
|
316
|
+
console.log(' No deprecated items to remove');
|
|
271
317
|
}
|
|
272
318
|
|
|
273
319
|
console.log('\n' + '='.repeat(50));
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-dev-template",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
4
4
|
"description": "Structured AI-assisted development framework for Claude Code",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cc-dev-template": "./bin/install.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"bin/",
|
|
10
|
-
"src/"
|
|
10
|
+
"src/",
|
|
11
|
+
"!src/mcp-servers/*/node_modules/",
|
|
12
|
+
"!src/mcp-servers/*/dist/"
|
|
11
13
|
],
|
|
12
14
|
"keywords": [
|
|
13
15
|
"claude",
|
|
@@ -161,6 +161,71 @@ function getGitBranch(projectDir) {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Get submodule paths from .gitmodules
|
|
166
|
+
*/
|
|
167
|
+
function getSubmodulePaths(projectDir) {
|
|
168
|
+
try {
|
|
169
|
+
const output = execSync('git config --file .gitmodules --get-regexp path', {
|
|
170
|
+
cwd: projectDir,
|
|
171
|
+
encoding: 'utf-8',
|
|
172
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
173
|
+
});
|
|
174
|
+
// Parse lines like "submodule.packages/core.path packages/core"
|
|
175
|
+
return output
|
|
176
|
+
.trim()
|
|
177
|
+
.split('\n')
|
|
178
|
+
.map((line) => line.split(' ')[1])
|
|
179
|
+
.filter(Boolean);
|
|
180
|
+
} catch {
|
|
181
|
+
return []; // No .gitmodules or no submodules
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get all modules (main + submodules) that have changes
|
|
187
|
+
* Returns array of { name, path, branch, status }
|
|
188
|
+
*/
|
|
189
|
+
function getModulesWithChanges(projectDir) {
|
|
190
|
+
const submodulePaths = getSubmodulePaths(projectDir);
|
|
191
|
+
|
|
192
|
+
// If no submodules, return null to indicate regular repo
|
|
193
|
+
if (submodulePaths.length === 0) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const modules = [];
|
|
198
|
+
|
|
199
|
+
// Check main repo
|
|
200
|
+
const mainStatus = getGitStatus(projectDir);
|
|
201
|
+
const mainStatusStr = mainStatus ? formatGitStatus(mainStatus) : '';
|
|
202
|
+
if (mainStatusStr) {
|
|
203
|
+
modules.push({
|
|
204
|
+
name: 'MAIN',
|
|
205
|
+
path: projectDir,
|
|
206
|
+
branch: getGitBranch(projectDir),
|
|
207
|
+
status: mainStatusStr,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Check each submodule
|
|
212
|
+
for (const subPath of submodulePaths) {
|
|
213
|
+
const fullPath = join(projectDir, subPath);
|
|
214
|
+
const subStatus = getGitStatus(fullPath);
|
|
215
|
+
const subStatusStr = subStatus ? formatGitStatus(subStatus) : '';
|
|
216
|
+
if (subStatusStr) {
|
|
217
|
+
modules.push({
|
|
218
|
+
name: basename(subPath).toUpperCase(),
|
|
219
|
+
path: fullPath,
|
|
220
|
+
branch: getGitBranch(fullPath),
|
|
221
|
+
status: subStatusStr,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return modules;
|
|
227
|
+
}
|
|
228
|
+
|
|
164
229
|
/**
|
|
165
230
|
* Main function
|
|
166
231
|
*/
|
|
@@ -237,14 +302,17 @@ function main() {
|
|
|
237
302
|
ctxDisplay = `CTX: ${greyColor}[${bar}] ${pct}%${DIM_GREY} | ${usedTokens}/${limitTokens}`;
|
|
238
303
|
}
|
|
239
304
|
|
|
240
|
-
// Get git information
|
|
241
|
-
const gitBranch = getGitBranch(data.workspace.project_dir);
|
|
242
|
-
const gitStatus = getGitStatus(data.workspace.project_dir);
|
|
243
|
-
const gitStatusStr = gitStatus ? formatGitStatus(gitStatus) : '';
|
|
244
|
-
|
|
245
305
|
// Multi-line bordered box format
|
|
246
306
|
const width = 56;
|
|
247
307
|
|
|
308
|
+
// Helper to create a padded box line
|
|
309
|
+
const makeBoxLine = (content) => {
|
|
310
|
+
const plain = content.replace(/\x1b\[[0-9;]*m/g, '');
|
|
311
|
+
const padding = width - plain.length;
|
|
312
|
+
const padded = content + ' '.repeat(Math.max(0, padding));
|
|
313
|
+
return `${DIM_GREY}║ ${padded} ║${RESET}`;
|
|
314
|
+
};
|
|
315
|
+
|
|
248
316
|
// Top border with model name (add 2 to match content line width: ║ + space + 56 + space + ║ = 60)
|
|
249
317
|
const modelName = data.model.display_name.toUpperCase();
|
|
250
318
|
const labelWidth = modelName.length + 2; // +2 for brackets
|
|
@@ -255,46 +323,69 @@ function main() {
|
|
|
255
323
|
const maxDirLen = width - 5; // "DIR: " = 5 chars
|
|
256
324
|
const dirName =
|
|
257
325
|
rawDirName.length > maxDirLen ? rawDirName.substring(0, maxDirLen - 3) + '...' : rawDirName;
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
326
|
+
const line0 = makeBoxLine(`DIR: ${dirName}`);
|
|
327
|
+
|
|
328
|
+
// Get git information - check for submodules
|
|
329
|
+
const modulesWithChanges = getModulesWithChanges(data.workspace.project_dir);
|
|
330
|
+
|
|
331
|
+
// Build branch/module lines
|
|
332
|
+
const branchLines = [];
|
|
333
|
+
|
|
334
|
+
if (modulesWithChanges === null) {
|
|
335
|
+
// No submodules - use original single-line format
|
|
336
|
+
const gitBranch = getGitBranch(data.workspace.project_dir);
|
|
337
|
+
const gitStatus = getGitStatus(data.workspace.project_dir);
|
|
338
|
+
const gitStatusStr = gitStatus ? formatGitStatus(gitStatus) : '';
|
|
339
|
+
|
|
340
|
+
let line1Content = '';
|
|
341
|
+
if (gitBranch) {
|
|
342
|
+
const branchPrefix = 'BRANCH: ';
|
|
343
|
+
const branchSuffix = ' ⎇';
|
|
344
|
+
const gitStatusSpace = gitStatusStr ? ` ${gitStatusStr}` : '';
|
|
345
|
+
|
|
346
|
+
const availableSpace = width - branchPrefix.length - branchSuffix.length - gitStatusSpace.length;
|
|
347
|
+
const displayBranch =
|
|
348
|
+
gitBranch.length > availableSpace
|
|
349
|
+
? gitBranch.substring(0, availableSpace - 3) + '...'
|
|
350
|
+
: gitBranch;
|
|
351
|
+
|
|
352
|
+
line1Content = `${branchPrefix}${displayBranch.toUpperCase()}${branchSuffix}${gitStatusSpace}`;
|
|
353
|
+
} else {
|
|
354
|
+
line1Content = 'BRANCH: (none)';
|
|
355
|
+
}
|
|
356
|
+
branchLines.push(makeBoxLine(line1Content));
|
|
357
|
+
} else if (modulesWithChanges.length === 0) {
|
|
358
|
+
// Has submodules but all clean
|
|
359
|
+
const gitBranch = getGitBranch(data.workspace.project_dir);
|
|
360
|
+
const branchName = gitBranch ? gitBranch.toUpperCase() : '(none)';
|
|
361
|
+
branchLines.push(makeBoxLine(`BRANCH: ${branchName} ⎇ (all clean)`));
|
|
279
362
|
} else {
|
|
280
|
-
|
|
363
|
+
// Has submodules with changes - one line per module
|
|
364
|
+
for (const mod of modulesWithChanges) {
|
|
365
|
+
const branchName = mod.branch ? mod.branch.toUpperCase() : '(none)';
|
|
366
|
+
const prefix = `[${mod.name}] `;
|
|
367
|
+
const suffix = ' ⎇';
|
|
368
|
+
const statusSpace = ` ${mod.status}`;
|
|
369
|
+
|
|
370
|
+
const availableSpace = width - prefix.length - suffix.length - statusSpace.length;
|
|
371
|
+
const displayBranch =
|
|
372
|
+
branchName.length > availableSpace
|
|
373
|
+
? branchName.substring(0, availableSpace - 3) + '...'
|
|
374
|
+
: branchName;
|
|
375
|
+
|
|
376
|
+
branchLines.push(makeBoxLine(`${prefix}${displayBranch}${suffix}${statusSpace}`));
|
|
377
|
+
}
|
|
281
378
|
}
|
|
282
379
|
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
const paddedLine1 = line1Content + ' '.repeat(Math.max(0, padding1));
|
|
286
|
-
const line1 = `${DIM_GREY}║ ${paddedLine1} ║${RESET}`;
|
|
287
|
-
|
|
288
|
-
// Line 2: Context bar (padded to width)
|
|
289
|
-
const plainCtx = ctxDisplay.replace(/\x1b\[[0-9;]*m/g, '');
|
|
290
|
-
const padding2 = width - plainCtx.length;
|
|
291
|
-
const paddedCtx = ctxDisplay + ' '.repeat(Math.max(0, padding2));
|
|
292
|
-
const line2 = `${DIM_GREY}║ ${paddedCtx} ║${RESET}`;
|
|
380
|
+
// Context bar line
|
|
381
|
+
const ctxLine = makeBoxLine(ctxDisplay);
|
|
293
382
|
|
|
294
383
|
// Bottom border (add 2 to match content line width)
|
|
295
384
|
const bottomBorder = `${DIM_GREY}╚${'═'.repeat(width + 2)}╝${RESET}`;
|
|
296
385
|
|
|
297
|
-
|
|
386
|
+
// Combine all lines
|
|
387
|
+
const allLines = [topBorder, line0, ...branchLines, ctxLine, bottomBorder];
|
|
388
|
+
console.log(allLines.join('\n'));
|
|
298
389
|
} catch (error) {
|
|
299
390
|
// Log error for debugging (goes to stderr, not visible in status line)
|
|
300
391
|
console.error(`Status line error: ${error.message}`);
|
|
@@ -1,54 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: creating-agent-skills
|
|
3
|
-
description: Expert guidance for creating
|
|
3
|
+
description: Expert guidance for creating and fixing Claude Code skills. Use when the user asks to "create a skill", "build a new skill", "fix a skill", "audit skills", "review my skills", "update a skill", "modify a skill", "improve a skill", or mentions skill development, SKILL.md files, or progressive disclosure.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Creating Agent Skills
|
|
7
7
|
|
|
8
8
|
## What To Do Now
|
|
9
9
|
|
|
10
|
-
Ask
|
|
10
|
+
Ask the user what they need.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- **Create a new skill** - Build a skill through guided conversation
|
|
14
|
-
- **Audit existing skills** - Review skills for best practices compliance
|
|
15
|
-
- **Modify a skill** - Update or improve an existing skill
|
|
16
|
-
- **Something else** - Free-form request
|
|
17
|
-
|
|
18
|
-
## Route to Workflow
|
|
19
|
-
|
|
20
|
-
Based on choice, read the appropriate workflow:
|
|
21
|
-
|
|
22
|
-
| Choice | Action |
|
|
12
|
+
| Intent | Action |
|
|
23
13
|
|--------|--------|
|
|
24
|
-
| Create | Read `references/create.md` |
|
|
25
|
-
|
|
|
26
|
-
| Modify | Read `references/modify.md` |
|
|
27
|
-
| Something else | Help find the right approach |
|
|
28
|
-
|
|
29
|
-
## Essential Knowledge
|
|
30
|
-
|
|
31
|
-
**A skill IS a prompt.** When activated, Claude reads SKILL.md. It must contain instructions, not documentation about the skill.
|
|
32
|
-
|
|
33
|
-
**Progressive disclosure.** SKILL.md should be lean (<150 lines). Heavy content goes in references/. This keeps context efficient.
|
|
34
|
-
|
|
35
|
-
**The test:** After reading SKILL.md, would Claude know what to DO? If it only knows what the skill is about, it's written wrong.
|
|
36
|
-
|
|
37
|
-
For complete principles, workflows load `references/principles.md` as needed.
|
|
38
|
-
|
|
39
|
-
## Quick Reference
|
|
40
|
-
|
|
41
|
-
**Skill locations:**
|
|
42
|
-
|
|
43
|
-
| Level | Path |
|
|
44
|
-
|-------|------|
|
|
45
|
-
| User | `~/.claude/skills/` |
|
|
46
|
-
| Project | `.claude/skills/` |
|
|
47
|
-
|
|
48
|
-
**Bundled scripts:**
|
|
49
|
-
- `scripts/find-skills.js` - Discover all installed skills
|
|
50
|
-
- `scripts/validate-skill.js` - Validate a skill's structure
|
|
51
|
-
|
|
52
|
-
## Requirements
|
|
14
|
+
| Create a new skill | Read `references/create-step-1-understand.md` |
|
|
15
|
+
| Fix, improve, audit, or modify an existing skill | Read `references/fix-step-1-diagnose.md` |
|
|
53
16
|
|
|
54
|
-
|
|
17
|
+
If the user says "audit my skills", that is the fix path.
|
|
18
|
+
If they mention a specific skill that needs changes, that is also the fix path.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Step 1: Understand the Domain
|
|
2
|
+
|
|
3
|
+
The skill's quality depends entirely on understanding the domain. Start a conversation with the user.
|
|
4
|
+
|
|
5
|
+
## What To Uncover
|
|
6
|
+
|
|
7
|
+
- **The task** they want to standardize — what do they do repeatedly that they want encoded?
|
|
8
|
+
- **Domain knowledge** Claude does not naturally have — terminology, patterns, edge cases, gotchas
|
|
9
|
+
- **Why certain approaches work** — not just what the steps are, but the reasoning behind them
|
|
10
|
+
- **Concrete examples** of the task done well — ask for real examples or walk-throughs
|
|
11
|
+
- **Common mistakes** people make when doing this task
|
|
12
|
+
|
|
13
|
+
## How To Have This Conversation
|
|
14
|
+
|
|
15
|
+
If the user already provided comprehensive context (a detailed spec, all the steps, domain knowledge), verify your understanding and move on — do not re-ask what they already answered. If the context is thin or ambiguous, have a real conversation.
|
|
16
|
+
|
|
17
|
+
Ask one or two questions at a time. This should feel like a conversation, not a form.
|
|
18
|
+
|
|
19
|
+
Good questions:
|
|
20
|
+
- "Walk me through how you do this today."
|
|
21
|
+
- "What's the most important thing to get right?"
|
|
22
|
+
- "What mistakes do people commonly make?"
|
|
23
|
+
- "What would an expert know that a beginner wouldn't?"
|
|
24
|
+
- "Can you show me an example of this done well?"
|
|
25
|
+
|
|
26
|
+
Ask follow-up questions. Dig into the WHY behind their answers. If they say "always do X before Y", ask why that order matters.
|
|
27
|
+
|
|
28
|
+
## If the Task Is Non-Obvious
|
|
29
|
+
|
|
30
|
+
If this is a domain where Claude would not naturally know how to proceed — research it. Look at examples. Try to figure out how you would approach the task yourself. The skill author needs to understand the domain, not just record what the user says.
|
|
31
|
+
|
|
32
|
+
Use the Explore agent or web search if the domain requires knowledge you lack.
|
|
33
|
+
|
|
34
|
+
## When To Move On
|
|
35
|
+
|
|
36
|
+
Move on when all of these are true:
|
|
37
|
+
- You can articulate what makes this task hard or nuanced
|
|
38
|
+
- You have enough domain knowledge to write instructions a fresh Claude instance could follow
|
|
39
|
+
- You understand WHY the approaches work, not just WHAT they are
|
|
40
|
+
- The user confirms you understand their needs
|
|
41
|
+
|
|
42
|
+
Read `references/create-step-2-design.md`.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Step 2: Design the Skill
|
|
2
|
+
|
|
3
|
+
Based on what you learned in the conversation, design the skill's structure before writing anything.
|
|
4
|
+
|
|
5
|
+
## Determine the Name
|
|
6
|
+
|
|
7
|
+
- Hyphen-case: lowercase letters, numbers, and hyphens only
|
|
8
|
+
- Prefer gerund form: `processing-pdfs`, `creating-reports`, `reviewing-code`
|
|
9
|
+
- Must match the directory name
|
|
10
|
+
- Max 64 characters
|
|
11
|
+
|
|
12
|
+
## Determine the Skill Type
|
|
13
|
+
|
|
14
|
+
There are two types. Pick one:
|
|
15
|
+
|
|
16
|
+
**Informational** — A single SKILL.md file that captures knowledge, conventions, or best practices. No sequential workflow. The agent absorbs it and applies it to whatever it's doing. Example: a `prompting` skill that teaches how to write good prompts.
|
|
17
|
+
|
|
18
|
+
**Procedural** — A chain of step files for a sequential process. SKILL.md routes to step 1. Step 1 chains to step 2. Each step file covers ONE phase. The agent only sees the current step. Example: a skill that downloads a video, transcribes it, formats it, and summarizes it — four distinct phases, four files.
|
|
19
|
+
|
|
20
|
+
**How to decide:** If the skill describes a process with distinct sequential phases, it is procedural. If it captures principles or knowledge applied whenever relevant, it is informational.
|
|
21
|
+
|
|
22
|
+
## Design the Frontmatter
|
|
23
|
+
|
|
24
|
+
Every skill has YAML frontmatter. Required and optional fields:
|
|
25
|
+
|
|
26
|
+
### Required
|
|
27
|
+
|
|
28
|
+
| Field | Rules |
|
|
29
|
+
|-------|-------|
|
|
30
|
+
| `name` | Hyphen-case, matches directory name, max 64 chars |
|
|
31
|
+
| `description` | Third person, quoted trigger phrases, WHEN to use not HOW it works, max 1024 chars |
|
|
32
|
+
|
|
33
|
+
### Optional
|
|
34
|
+
|
|
35
|
+
| Field | Purpose |
|
|
36
|
+
|-------|---------|
|
|
37
|
+
| `argument-hint` | Placeholder shown after slash command (e.g., `[issue-number]`, `[filename]`) |
|
|
38
|
+
| `disable-model-invocation` | Set `true` to prevent Claude from auto-activating — use for side-effect workflows like deploy or commit |
|
|
39
|
+
| `user-invocable` | Set `false` to hide from the `/` menu — use for background knowledge skills |
|
|
40
|
+
| `allowed-tools` | Restrict which tools the skill can use (e.g., `Read, Grep, Glob` for read-only) |
|
|
41
|
+
| `model` | Override the model used when this skill is active |
|
|
42
|
+
| `context` | Set `fork` to run in an isolated sub-agent context |
|
|
43
|
+
| `agent` | Sub-agent type when `context: fork` is set (`Explore`, `Plan`, `general-purpose`, or custom) |
|
|
44
|
+
| `hooks` | Lifecycle hooks scoped to this skill |
|
|
45
|
+
|
|
46
|
+
### String Substitutions Available in Skill Content
|
|
47
|
+
|
|
48
|
+
| Syntax | What It Does |
|
|
49
|
+
|--------|--------------|
|
|
50
|
+
| `$ARGUMENTS` | Full argument string passed after `/skill-name` |
|
|
51
|
+
| `$ARGUMENTS[N]` or `$N` | Positional argument (0-based) |
|
|
52
|
+
| `${CLAUDE_SESSION_ID}` | Current session ID |
|
|
53
|
+
| `` !`command` `` | Output of a shell command, injected at activation time before Claude sees the content |
|
|
54
|
+
|
|
55
|
+
## Craft the Description
|
|
56
|
+
|
|
57
|
+
The description determines when Claude activates the skill. This is the most important piece of metadata.
|
|
58
|
+
|
|
59
|
+
Collect 5-10 trigger phrases from the user: "When you need this skill, what would you say to Claude?"
|
|
60
|
+
|
|
61
|
+
Combine into a description that:
|
|
62
|
+
- Uses third person: "This skill should be used when..."
|
|
63
|
+
- Includes the actual trigger phrases in quotes
|
|
64
|
+
- Focuses on WHEN to use, not HOW it works
|
|
65
|
+
- Stays under 1024 characters
|
|
66
|
+
|
|
67
|
+
**Key insight:** If the description explains too much about WHAT the skill does, Claude believes it already knows enough and will not activate. Keep it about WHEN.
|
|
68
|
+
|
|
69
|
+
**Context budget note:** Skill descriptions load at startup and share a character budget (default 15,000 chars across all skills). Keep descriptions tight — they cost tokens every session.
|
|
70
|
+
|
|
71
|
+
## Plan the File Layout
|
|
72
|
+
|
|
73
|
+
**For informational skills:**
|
|
74
|
+
```
|
|
75
|
+
skill-name/
|
|
76
|
+
└── SKILL.md
|
|
77
|
+
```
|
|
78
|
+
Optionally add `references/` for depth that is not always needed.
|
|
79
|
+
|
|
80
|
+
**For procedural skills:**
|
|
81
|
+
```
|
|
82
|
+
skill-name/
|
|
83
|
+
├── SKILL.md # Routes to step 1
|
|
84
|
+
└── references/
|
|
85
|
+
├── step-1-[name].md # Chains to step 2
|
|
86
|
+
├── step-2-[name].md # Chains to step 3
|
|
87
|
+
└── step-3-[name].md # Final step
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**When to add `scripts/`:** Deterministic operations that need reliability — validation, code generation, file operations.
|
|
91
|
+
|
|
92
|
+
**When to add `templates/`:** Boilerplate files that get copied or modified by the agent.
|
|
93
|
+
|
|
94
|
+
## For Procedural Skills: Plan the Steps
|
|
95
|
+
|
|
96
|
+
List out the steps. Each step becomes one markdown file in `references/`. For each step, determine:
|
|
97
|
+
- What the agent does during this step
|
|
98
|
+
- What signals the step is complete (the chain condition)
|
|
99
|
+
- What the next step is
|
|
100
|
+
|
|
101
|
+
## Confirm With the User
|
|
102
|
+
|
|
103
|
+
Present the design:
|
|
104
|
+
- Name
|
|
105
|
+
- Type (informational or procedural)
|
|
106
|
+
- Frontmatter configuration
|
|
107
|
+
- Description text
|
|
108
|
+
- File layout
|
|
109
|
+
- For procedural: the step breakdown
|
|
110
|
+
|
|
111
|
+
Ask: "Does this design look right?"
|
|
112
|
+
|
|
113
|
+
Read `references/create-step-3-write.md` when the design is confirmed.
|