skill creator
UnreviewedAuthors, tests, iterates on, and submits Claude Code skills (SKILL.md files) for the Adom ecosystem. Use when the user wants to create a new skill, write or update a SKILL.md, contribute a skill back
name: skill-creator
description: Authors, tests, iterates on, and submits Claude Code skills (SKILL.md files) for the Adom ecosystem. Use when the user wants to create a new skill, write or update a SKILL.md, contribute a skill back to Adom's gallia repo, or asks how skills work. Covers frontmatter conventions, writing effective descriptions, progressive disclosure with reference files, deploying to ~/.claude/skills/, iterating on failures, and PR submission.
Creating Adom Skills
Skills are Markdown documents that teach Claude Code how to perform specialized tasks. They live in the gallia repo and get distributed to all Adom users via node install.mjs, which copies every directory under skills/ that contains a SKILL.md into ~/.claude/skills/.
Only the name and description from each skill's frontmatter are pre-loaded at startup. SKILL.md is read when the description matches the user's task; reference files are read only when SKILL.md points to them. This progressive disclosure is why keeping SKILL.md concise matters — every token loaded competes with conversation history.
IMPORTANT — Always show the result to the user. After creating or updating a visual skill, you MUST open the output in front of the user (a Hydrogen webview panel tab) so they can see it immediately. Never tell the user to navigate there themselves — drive it for them.
Use
app-creatorfor any new visual skill. Adom Viewer (AV) is
deprecated and is no longer the canonical display surface. New
skills that render HTML, charts, 3D content, dashboards, or widgets
should ship as Hydrogen webview apps via theapp-creatorskill, not
asav_displaypushes. Theav-creatorskill is kept only for
maintaining un-ported legacy AV views.
Architecture
/home/adom/gallia/skills/my-skill/
SKILL.md # main instructions (under 500 lines)
reference.md # optional, loaded only when needed
examples.md # optional, loaded only when needed
scripts/ # optional, executed not loaded
preferences.json # optional, user-configurable defaults
# After `node install.mjs`:
~/.claude/skills/my-skill/SKILL.md
Workflow Checklist
Copy and track progress:
- [ ] Step 1: Scope and name the skill
- [ ] Step 2: Write SKILL.md frontmatter and body
- [ ] Step 3: Deploy to ~/.claude/skills/ and test real trigger phrases
- [ ] Step 4: Iterate — fix trigger misses and instruction failures
- [ ] Step 5: Submit to gallia (see submission.md)
Step 1: Scope and Name
One skill, one purpose. If the scope is growing, split it — a 50-line skill that solves one problem beats a 500-line skill covering everything.
Use kebab-case for the directory, matching the name field:
mkdir -p /home/adom/gallia/skills/my-skill-name
Before creating a new skill, check whether one already covers the need. Search /home/adom/gallia/skills/ and the Adom Wiki (adom-wiki skill) for overlapping triggers.
Step 2: Write SKILL.md
Frontmatter
---
name: my-skill-name
description: <third person, what + when, includes trigger phrases>
---
The Claude Code skill-frontmatter schema supports exactly these fields: name, description, argument-hint, compatibility, disable-model-invocation, license, metadata, user-invocable. Anything else (including author) is silently ignored at runtime but flagged as unsupported by the IDE's skill linter — don't set it.
| Field | Required | Convention |
|---|---|---|
name |
yes | Matches the skill directory name. Convention: kebab-case, short and descriptive. Avoid claude and anthropic even though the Claude Code loader accepts them. |
description |
yes | Must be a string scalar. Target ≤1024 chars — fits inside the 1,536-char listing cap. Empty descriptions get auto-synthesized from the body, so always set one explicitly. |
user-invocable |
no | true if the user can trigger it with /skill-name. Default: auto-trigger only. The gallia ecosystem commonly uses user-invokable (with k) — that's a misspelling; the supported field is user-invocable. |
argument-hint |
no | Short hint shown when the skill takes /skill-name <args>. String. |
compatibility |
no | Version-constraint metadata. Rare; see existing plugin skills. |
disable-model-invocation |
no | true to make a skill purely user-invocable (no auto-trigger). |
license |
no | SPDX-style license string. |
metadata |
no | Free-form map for tool-specific extensions (e.g., effort values). |
Constraints and caps
Hard runtime limits:
- Descriptions are capped at 1,536 chars in the skill listing the selector reads. Anything past that is invisible — the selector can't match text it never sees.
- Listing budget is 2% of the context window, shared across all skills.
descriptionmust be a string scalar; arrays and objects are rejected.- Empty
descriptionis silently auto-synthesized from the body's first heading/paragraph, which is usually worse than what you'd write — always set one. - Hooks and
metadata.effortare schema-validated when present. - The IDE linter warns on frontmatter fields outside the supported set.
Authoring targets — good practice, not enforced:
description≤ 1024 chars. Fits well inside the 1,536-char listing cap and keeps the skill from crowding the shared budget.- Name in kebab-case; avoid
claudeandanthropiceven though the loader accepts them. - SKILL.md body ≤ 500 lines; split into reference files past that.
- No XML tags in
nameordescription.
The loader does not check name length, name charset, reserved words, description length, tag content, or body size. These are style rules — useful to follow, but violations load without error. Rely on the IDE linter and review, not runtime feedback.
Long trigger lists belong in the body (a "Trigger phrases" section), not in the frontmatter description — once the skill is selected, the whole body loads. The frontmatter only needs enough signal for the selector to pick it.
Writing the description
The description is injected into the system prompt and is how Claude picks this skill from 100+ candidates. Write it in third person, stating both what the skill does and when to use it. Include quoted trigger phrases the user might say.
Good:
description: Creates KiCad footprints (.kicad_mod files) from datasheet dimensions, validates pad placement, and previews in a Hydrogen webview tab. Use when the user says "create a footprint", "make a .kicad_mod", or wants to visualize a footprint.
Bad:
description: A tool for making footprints. # vague
description: I can help you make footprints. # first person
description: You can use this to make footprints. # second person
Body: tone and structure
Write imperative, technical instructions for Claude, not for the user.
- Keep the body under 500 lines. Past that, move details into reference files (see "Progressive disclosure" below).
- Number steps when order matters. Use
##headers. - Always tag code blocks with the language.
- Use absolute file paths starting from
/home/adom/. Never relative paths. - Forward slashes only — never
\, even for Windows-hosted content. - MCP tools: reference as
ServerName:tool_nameso Claude can find them when multiple MCP servers are loaded. Example:GitHub:create_issue. - KiCad S-expression files (
.kicad_sym,.kicad_mod,.kicad_sch) reject;;and#comments — never add them to those files. - No time-sensitive info. "As of August 2025..." rots. Put deprecated patterns in a collapsed "Old patterns" section instead.
- Consistent terminology. Pick one term (e.g., "Adom Viewer", or consistently "AV" after first definition) and stick with it.
Matching specificity to task fragility
The guide distinguishes three levels of instruction freedom:
- High freedom (narrative steps) — when multiple approaches are valid and context determines the best one. Example: a code-review skill that lists what to look for but doesn't mandate an exact workflow.
- Medium freedom (templates or parameterized scripts) — when a preferred pattern exists but some variation is acceptable.
- Low freedom (one exact command, no flags) — when the operation is fragile, order-sensitive, or destructive. Example: database migrations, KiCad file edits, publish commands.
Favor low freedom for anything that touches user data, shared state, or the wiki.
Content patterns
Template pattern — for strict output formats. See examples.md → "Template Pattern".
Examples pattern — when output quality depends on seeing concrete input/output pairs. See examples.md → "Examples Pattern".
Workflow with feedback loop — validator → fix → retry, for quality-critical multi-step tasks. See examples.md → "Workflow with Feedback Loop".
Progressive disclosure
If SKILL.md approaches 500 lines, split content into reference files and link from SKILL.md.
Keep references one level deep. If SKILL.md points to reference.md, don't have reference.md point to deeper.md — Claude may partial-read deeply-chained files with head and miss content. Every reference file should link directly from SKILL.md.
my-skill/
├── SKILL.md # overview + pointers
├── reference.md # API or schema reference
└── examples.md # usage examples
In SKILL.md:
**Advanced features**: See [reference.md](reference.md)
**Examples**: See [examples.md](examples.md)
For any reference file over 100 lines, add a table of contents at the top so Claude sees the full scope even when previewing with head.
Step 3: Deploy for Testing
Copy the skill to ~/.claude/skills/ so Claude Code picks it up in the current session:
cp -r /home/adom/gallia/skills/my-skill-name /home/adom/.claude/skills/my-skill-name
Open a new Claude Code session and try a trigger phrase from the description. Verify:
- The skill appears in the session's skills list (check the system reminder)
- Claude invokes it on the expected phrase
- The instructions produce correct output on at least one real task
- Edge cases and errors are handled
Step 4: Iterate
Edit the source file in gallia, then re-copy to ~/.claude/skills/:
cp -r /home/adom/gallia/skills/my-skill-name /home/adom/.claude/skills/my-skill-name
Common failure modes:
| Symptom | Cause | Fix |
|---|---|---|
| Skill doesn't trigger | Description too vague or missing the user's phrasing | Add specific quoted trigger phrases; include file formats and key nouns |
| Claude ignores instructions | SKILL.md too long or too vague | Be specific and imperative; split into reference files |
| Wrong file paths | Relative paths confuse Claude across sessions | Use absolute paths starting from /home/adom/ |
| Reference file ignored | Linked from another reference, not SKILL.md | Flatten to one level — link from SKILL.md directly |
| Claude reads only the top of a long reference file | No table of contents | Add TOC to any reference file > 100 lines |
| Two skills fight over the same trigger | Overlapping descriptions | Narrow each description; the more specific wins |
Test with the models you plan to use. What works for Opus may need more detail for Haiku. Adom defaults to Opus/Sonnet but some users run Haiku for speed — aim for instructions that work with all three.
Test with real usage, not just contrived prompts. Watch what Claude actually reads, what it skips, and where it misinterprets. Adjust based on observed behavior, not assumed behavior.
Step 5: Submit to Gallia
Once the skill works, submit it so all Adom users benefit. The installer auto-discovers any skills/*/SKILL.md, so a merge is enough to deploy.
See submission.md for the complete submission workflow: pre-flight checklist, PR template, updating skills/README.md and skills/adom/SKILL.md routing, direct push, and publishing to the Adom Wiki. For skills with a visual surface, route to app-creator instead of adding AV explainer entries.
Skill Complexity Guidelines
| Type | Lines | Examples |
|---|---|---|
| Reference | 20-100 | use-cases, adom-molecules-catalog — static documentation, catalogs |
| Setup/Config | 100-300 | openclaw-setup — step-by-step install guides with troubleshooting |
| Infrastructure | 300-500 (split beyond) | adom, adom-wiki — MCP tool reference, API docs |
| Creator | 500+ (use reference files) | symbol-creator, footprint-creator — multi-step workflows with validation, preview, delivery |
Start small. Split into reference files before the body exceeds 500 lines.
Optional: Preferences File
If the skill has user-configurable settings, create preferences.json:
{
"default_library": "my-lib",
"verbose": true
}
Load it at the start of the workflow:
## Step 1: Load Preferences
Read `/home/adom/.claude/skills/my-skill-name/preferences.json`. If the file doesn't exist, ask the user for their preferences and write defaults.
Related Skills
When the scope of what you're building extends past authoring:
app-creator— Building a visual skill as a Hydrogen webview app (mini HTTP server with a webview panel UI). The canonical display surface for new skills.standalone-service— Skills backed by a dedicated container with a shared HTTP API (JLCPCB, Mouser, KiCad CLI patterns). Use when the skill needs a large shared dataset or persistent server.wiki-submission— Publishing the skill's page to the Adom Wiki: demo viewers, red-box calibration, screenshot galleries, asset uploads.av-creator(legacy) — Kept only for maintaining un-ported AV views. Do not use for new work.
Examples and Templates
See examples.md for:
- A minimal complete skill (copy as a starting point)
- Template, examples, and workflow patterns
- Script conventions — solve problems, not punt; justify constants
Anti-patterns
- Offering too many options. Pick one default approach and an escape hatch, not a menu of five libraries.
- Verbose framing. Don't explain what PDFs are or how libraries work — Claude knows.
- Scripts that re-raise to Claude. Handle expected errors in the script; don't rely on Claude inspecting stack traces.
- "Voodoo constants."
TIMEOUT = 47with no comment. If you don't know the right value, Claude can't either — justify it. - Nested references.
SKILL.md → a.md → b.md → c.mdloses content. Flatten to one level.
Troubleshooting
| Symptom | Fix |
|---|---|
install.mjs doesn't copy the skill |
The directory must contain SKILL.md (exact capitalization), not skill.md or SKILLS.md |
| Skill appears in the list but never triggers | Description is too generic or the match-worthy triggers are past ~240 chars and truncated — move them to the front |
| Skill listing shows the description cut off mid-sentence | Expected at ~250 chars (prompt.ts:29). Rewrite the description so the load-bearing triggers come first |
| Two skills claim the same triggers | Narrow each description; the more specific one wins in the model's selection |
| Frontmatter parse error | YAML requires --- on its own line. CRLF line endings (\r\n) break strict parsers — run sed -i 's/\r$//' SKILL.md if the file was created on Windows |
| Description comes out as unexpected text | If the YAML description is empty, the loader synthesizes one from the body's first heading/paragraph. Set an explicit description to control what the selector sees |