From dev-workflow
Create new skills, improve existing skills, and measure skill performance with iterative eval-driven development. Use when users want to create a skill from scratch, edit or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy. Also use when the user says "build a skill", "make a slash command", "write a new skill", "improve this skill", or "test my skill". Do NOT use for domain-team skills with convention discipline (use domain-teams:skill-team instead). スキル作成・スキル改善・評価ループ。技能建立・技能改善・評估迴圈。
How this skill is triggered — by the user, by Claude, or both
Slash command
/dev-workflow:skill-creator-advanceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A skill for creating new skills and iteratively improving them.
LICENSENOTICEagents/analyzer.mdagents/comparator.mdagents/grader.mdreferences/eval-methodology.mdreferences/iteration-automation.mdreferences/mermaid-usage-guidelines.mdreferences/platform-adaptations.mdreferences/plugin-conventions.mdreferences/schemas.mdscripts/__init__.pyscripts/aggregate_benchmark.pyscripts/generate_report.pyscripts/improve_description.pyscripts/package_skill.pyscripts/quick_validate.pyscripts/run_eval.pyscripts/run_loop.pyscripts/utils.pyA skill for creating new skills and iteratively improving them.
The core loop: draft → test → review → improve → repeat.
Your job is to figure out where the user is in this process and help them progress. Maybe they want to start from scratch, or maybe they already have a draft. Be flexible — if they say "just vibe with me", skip the formal eval machinery.
Users range from non-technical to expert — plumbers opening terminals, grandparents googling "how to install npm", alongside experienced developers. Pay attention to context cues to gauge their familiarity:
When in doubt, briefly define terms inline. It's better to over-explain once than to lose someone.
Start by understanding the user's intent. The current conversation might already contain a workflow the user wants to capture (e.g., "turn this into a skill"). If so, extract answers from the conversation history first — the tools used, the sequence of steps, corrections the user made, input/output formats observed. The user may need to fill gaps, and should confirm before proceeding.
Clarify these four questions:
Proactively ask questions about edge cases, input/output formats, example files, success criteria, and dependencies. Wait to write test prompts until you've got this part ironed out.
Check available MCPs - if useful for research (searching docs, finding similar skills, looking up best practices), research in parallel via subagents if available, otherwise inline. Come prepared with context to reduce burden on the user.
Based on the user interview, fill in these components:
Beyond being "pushy" to avoid under-triggering, good descriptions also include:
Negative triggers — Explicitly state when NOT to use the skill to avoid collisions with similar skills:
Do NOT use for domain-team skills (use skill-team instead). Do NOT use for simple file edits that don't need a skill.
Multilingual trigger keywords — If the skill's users speak multiple languages, add keywords at the end of the description in those languages. This helps Claude match the skill even when the user prompts in another language:
スキル作成・評価。技能建立・評估。
Before/after example:
skill-name/
├── SKILL.md (required)
│ ├── YAML frontmatter (name, description required)
│ └── Markdown instructions
└── Bundled Resources (optional)
├── scripts/ - Executable code for deterministic/repetitive tasks
└── references/ - Docs loaded into context as needed
Each skill should also have a corresponding slash command entry point in the plugin's commands/ directory. See references/plugin-conventions.md for the format and examples.
Skills use a three-level loading system:
These word counts are approximate and you can feel free to go longer if needed.
Key patterns:
Domain organization: When a skill supports multiple domains/frameworks, organize by variant (e.g., references/aws.md, references/gcp.md) — Claude reads only the relevant reference file.
When creating a skill that will live inside an existing plugin, match the plugin's conventions rather than imposing a new structure. Read references/plugin-conventions.md for detailed guidance on:
This goes without saying, but skills must not contain malware, exploit code, or any content that could compromise system security. A skill's contents should not surprise the user in their intent if described. Don't go along with requests to create misleading skills or skills designed to facilitate unauthorized access, data exfiltration, or other malicious activities. Things like a "roleplay as an XYZ" are OK though.
Prefer using the imperative form in instructions.
Defining output formats - You can do it like this:
## Report structure
ALWAYS use this exact template:
# [Title]
## Executive summary
## Key findings
## Recommendations
Examples pattern - It's useful to include examples. You can format them like this (but if "Input" and "Output" are in the examples you might want to deviate a little):
## Commit message format
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authentication
Try to explain to the model why things are important in lieu of heavy-handed musty MUSTs. Use theory of mind and try to make the skill general and not super-narrow to specific examples. Start by writing a draft and then look at it with fresh eyes and improve it.
After writing the skill draft, come up with 2-3 realistic test prompts — the kind of thing a real user would actually say. Share them with the user: [you don't have to use this exact language] "Here are a few test cases I'd like to try. Do these look right, or do you want to add more?" Then run them.
Save test cases to evals/evals.json. Don't write assertions yet — just the prompts. You'll draft assertions in the next step while the runs are in progress.
{
"skill_name": "example-skill",
"evals": [
{
"id": 1,
"prompt": "User's task prompt",
"expected_output": "Description of expected result",
"files": []
}
]
}
See references/schemas.md for the full schema (including the assertions field, which you'll add later).
When the user wants to improve a skill rather than build one from scratch, follow this flow instead of the full creation process:
Read the existing SKILL.md and all bundled files. Understand:
Look at these dimensions:
Present a concise improvement plan to the user before making changes. Group changes by impact:
Use the eval workflow (quick or full path, depending on complexity) to verify improvements. When improving an existing skill, the baseline should be the original version — snapshot it before editing (cp -r <skill-path> <workspace>/skill-snapshot/).
Not every skill needs the full benchmark treatment. Choose based on complexity:
Quick eval path — For simple skills (formatters, templates, single-step workflows):
Full eval path — For complex skills (multi-step workflows, skills with objective criteria):
When in doubt, start with the quick path. You can always escalate to the full path if the quick path isn't giving enough signal.
The full eval path follows this sequence — don't stop partway through. Do NOT use /skill-test or any other testing skill.
Put results in <skill-name>-workspace/ as a sibling to the skill directory. Within the workspace, organize results by iteration (iteration-1/, iteration-2/, etc.) and within that, each test case gets a directory (eval-0/, eval-1/, etc.). Don't create all of this upfront — just create directories as you go.
For each test case, spawn two subagents in the same turn — one with the skill, one without. This is important: don't spawn the with-skill runs first and then come back for baselines later. Launch everything at once so it all finishes around the same time.
With-skill run:
Execute this task:
- Skill path: <path-to-skill>
- Task: <eval prompt>
- Input files: <eval files if any, or "none">
- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- Outputs to save: <what the user cares about — e.g., "the .docx file", "the final CSV">
Baseline run (same prompt, but the baseline depends on context):
without_skill/outputs/.cp -r <skill-path> <workspace>/skill-snapshot/), then point the baseline subagent at the snapshot. Save to old_skill/outputs/.Write an eval_metadata.json for each test case (assertions can be empty for now). Give each eval a descriptive name based on what it's testing — not just "eval-0". Use this name for the directory too. If this iteration uses new or modified eval prompts, create these files for each new eval directory — don't assume they carry over from previous iterations.
{
"eval_id": 0,
"eval_name": "descriptive-name-here",
"prompt": "The user's task prompt",
"assertions": []
}
Don't just wait for the runs to finish — you can use this time productively. Draft quantitative assertions for each test case and explain them to the user. If assertions already exist in evals/evals.json, review them and explain what they check.
Good assertions are objectively verifiable and have descriptive names — they should read clearly in the benchmark report so someone glancing at the results immediately understands what each one checks. Subjective skills (writing style, design quality) are better evaluated qualitatively — don't force assertions onto things that need human judgment.
Update eval_metadata.json and evals/evals.json with assertions. Explain to the user what they'll see — both the qualitative outputs and the quantitative benchmark.
When each subagent task completes, you receive a notification containing total_tokens and duration_ms. Save this data immediately to timing.json in the run directory:
{
"total_tokens": 84852,
"duration_ms": 23332,
"total_duration_seconds": 23.3
}
This is the only opportunity to capture this data — it comes through the task notification and isn't persisted elsewhere. Process each notification as it arrives rather than trying to batch them.
Before grading and presenting results to the human, perform a quick automated check on each output. Read references/iteration-automation.md for the full protocol. In brief:
self_assessment.json in each test case directoryOnce all runs are done:
Grade each run — spawn a grader subagent (or grade inline) that reads agents/grader.md and evaluates each assertion against the outputs. Save results to grading.json in each run directory. The grading.json expectations array must use the fields text, passed, and evidence (not name/met/details or other variants). For assertions that can be checked programmatically, write and run a script rather than eyeballing it — scripts are faster, more reliable, and can be reused across iterations.
Check for regressions (iteration 2+) — After grading, compare results against the previous iteration. Read references/iteration-automation.md for the full protocol. Lead with any regressions when reporting to the user.
Aggregate into benchmark — run the aggregation script from the skill-creator directory:
python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>
This produces benchmark.json and benchmark.md with pass_rate, time, and tokens for each configuration, with mean +/- stddev and the delta. If generating benchmark.json manually, see references/schemas.md for the exact schema.
Put each with_skill version before its baseline counterpart.
Do an analyst pass — read the benchmark data and surface patterns the aggregate stats might hide. See agents/analyzer.md (the "Analyzing Benchmark Results" section) for what to look for — things like assertions that always pass regardless of skill (non-discriminating), high-variance evals (possibly flaky), and time/token tradeoffs.
Present results inline — For each test case, show the results directly in the conversation:
### Test Case: {eval_name}
**Prompt:** {the task prompt}
**Output:** {summary of key output files or inline content}
**Grades:** {assertion pass/fail results with evidence, if graded}
**Previous:** {what changed from last iteration, if iteration 2+}
After presenting all test cases, show the benchmark summary (pass rates, timing, token usage).
Save a markdown report to <workspace>/iteration-N/review.md containing all test case results and benchmark data. This persists the results for cross-iteration comparison.
Ask for feedback — After presenting results, ask the user for feedback on each test case. Focus on the cases where they have specific complaints; no comment means it looked fine.
This is the heart of the loop. You've run the test cases, the user has reviewed the results, and now you need to make the skill better based on their feedback.
Generalize from the feedback. You're trying to create skills that can be used a million times across many different prompts. You and the user are iterating on only a few examples because it helps move faster, but if the skill works only for those examples, it's useless. Rather than put in fiddly overfitty changes or oppressively constrictive MUSTs, if there's some stubborn issue, try branching out — use different metaphors, recommend different patterns of working. It's relatively cheap to try and maybe you'll land on something great.
Keep the prompt lean. Remove things that aren't pulling their weight. Make sure to read the transcripts, not just the final outputs — if it looks like the skill is making the model waste a bunch of time doing things that are unproductive, try getting rid of the parts of the skill that are causing that. The distinction matters: outputs tell you what happened, but transcripts tell you how it happened.
Explain the why. Try hard to explain the why behind everything you're asking the model to do. Today's LLMs are smart — they have good theory of mind and when given a good harness can go beyond rote instructions. Even if the feedback from the user is terse or frustrated, try to actually understand the task and why the user is writing what they wrote, and then transmit this understanding into the instructions. If you find yourself writing ALWAYS or NEVER in all caps, that's a yellow flag — reframe and explain the reasoning so that the model understands why it matters.
Look for repeated work across test cases. Read the transcripts from the test runs and notice if the subagents all independently wrote similar helper scripts or took the same multi-step approach. If all 3 test cases resulted in the subagent writing a create_docx.py or a build_chart.py, that's a strong signal the skill should bundle that script. Write it once, put it in scripts/, and tell the skill to use it.
This task is important and your thinking time is not the blocker; take your time and really mull things over. Write a draft revision and then look at it anew with fresh eyes. Really do your best to get into the head of the user and understand what they want and need.
After improving the skill:
iteration-<N+1>/ directory, including baseline runs. If you're creating a new skill, the baseline is always without_skill (no skill) — that stays the same across iterations. If you're improving an existing skill, use your judgment on what makes sense as the baseline: the original version the user came in with, or the previous iteration.review.md, noting changes from previous iterationKeep going until:
For situations where you want a more rigorous comparison between two versions of a skill (e.g., the user asks "is the new version actually better?"), there's a blind comparison system. Read agents/comparator.md and agents/analyzer.md for the details. The basic idea is: give two outputs to an independent agent without telling it which is which, and let it judge quality. Then analyze why the winner won.
This is optional, requires subagents, and most users won't need it. The human review loop is usually sufficient.
The description field in SKILL.md frontmatter is the primary mechanism that determines whether Claude invokes a skill. After creating or improving a skill, offer to optimize the description for better triggering accuracy.
Create 20 eval queries — a mix of should-trigger and should-not-trigger. Save as JSON:
[
{"query": "the user prompt", "should_trigger": true},
{"query": "another prompt", "should_trigger": false}
]
The queries must be realistic and something a Claude Code or Claude.ai user would actually type. Not abstract requests, but requests that are concrete and specific and have a good amount of detail. For instance, file paths, personal context about the user's job or situation, column names and values, company names, URLs. A little bit of backstory. Some might be in lowercase or contain abbreviations or typos or casual speech. Use a mix of different lengths, and focus on edge cases rather than making them clear-cut (the user will get a chance to sign off on them).
Bad: "Format this data", "Extract text from PDF", "Create a chart"
Good: "ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think"
For the should-trigger queries (8-10), think about coverage. You want different phrasings of the same intent — some formal, some casual. Include cases where the user doesn't explicitly name the skill or file type but clearly needs it. Throw in some uncommon use cases and cases where this skill competes with another but should win.
For the should-not-trigger queries (8-10), the most valuable ones are the near-misses — queries that share keywords or concepts with the skill but actually need something different. Think adjacent domains, ambiguous phrasing where a naive keyword match would trigger but shouldn't, and cases where the query touches on something the skill does but in a context where another tool is more appropriate.
The key thing to avoid: don't make should-not-trigger queries obviously irrelevant. "Write a fibonacci function" as a negative test for a PDF skill is too easy — it doesn't test anything. The negative cases should be genuinely tricky.
Present the eval set to the user inline for review. For each query, show:
| # | Query | Should Trigger? |
|---|-------|-----------------|
| 1 | "ok so my boss sent me this xlsx..." | ✅ Yes |
| 2 | "can you analyze the trends in..." | ❌ No |
Ask the user to confirm, edit, add, or remove queries before proceeding. Save the final eval set to <workspace>/trigger-eval.json.
This step matters — bad eval queries lead to bad descriptions.
Tell the user: "This will take some time — I'll run the optimization loop in the background and check on it periodically."
Save the eval set to the workspace, then run in the background:
python -m scripts.run_loop \
--eval-set <path-to-trigger-eval.json> \
--skill-path <path-to-skill> \
--model <model-id-powering-this-session> \
--max-iterations 5 \
--verbose
Use the model ID from your system prompt (the one powering the current session) so the triggering test matches what the user actually experiences.
While it runs, periodically tail the output to give the user updates on which iteration it's on and what the scores look like.
This handles the full optimization loop automatically. It splits the eval set into 60% train and 40% held-out test, evaluates the current description (running each query 3 times to get a reliable trigger rate), then calls Claude to propose improvements based on what failed. It re-evaluates each new description on both train and test, iterating up to 5 times. When it's done, it opens an HTML report in the browser showing the results per iteration and returns JSON with best_description — selected by test score rather than train score to avoid overfitting.
Understanding the triggering mechanism helps design better eval queries. Skills appear in Claude's available_skills list with their name + description, and Claude decides whether to consult a skill based on that description. The important thing to know is that Claude only consults skills for tasks it can't easily handle on its own — simple, one-step queries like "read this PDF" may not trigger a skill even if the description matches perfectly, because Claude can handle them directly with basic tools. Complex, multi-step, or specialized queries reliably trigger skills when the description matches.
This means your eval queries should be substantive enough that Claude would actually benefit from consulting a skill. Simple queries like "read file X" are poor test cases — they won't trigger skills regardless of description quality.
Take best_description from the JSON output and update the skill's SKILL.md frontmatter. Show the user before/after and report the scores.
After the skill is complete, package it for distribution:
python -m scripts.package_skill <path/to/skill-folder>
This creates a .skill file that can be shared and installed.
The instructions above assume Claude Code. If you're running in Claude.ai or Cowork, some mechanics change (no subagents, no browser, etc.). Read references/platform-adaptations.md for the platform-specific adjustments.
The agents/ directory contains instructions for specialized subagents. Read them when you need to spawn the relevant subagent.
agents/grader.md — How to evaluate assertions against outputsagents/comparator.md — How to do blind A/B comparison between two outputsagents/analyzer.md — How to analyze why one version beat anotherThe references/ directory has additional documentation:
references/schemas.md — JSON structures for evals.json, grading.json, etc.references/plugin-conventions.md — Plugin ecosystem conventions, directory structures, and slash command formatreferences/iteration-automation.md — Self-assessment and auto-regression detection protocolsreferences/eval-methodology.md — Eval methodology principles: why the eval workflow is designed this way (optional)references/platform-adaptations.md — Claude.ai and Cowork platform-specific adjustmentsreferences/mermaid-usage-guidelines.md — When to use Mermaid diagrams vs prose in skill authoring (decision trees / state machines / routing), syntax conventions, cost-benefit frameworkCore loop reminder: Draft → Test → Evaluate (inline review + evals) → Improve → Repeat → Package. Good luck!
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub kouko/monkey-skills --plugin dev-workflow