make-skill — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited make-skill (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Author Agent Skills against the agentskills.io specification. A skill is a self-contained directory of instructions, scripts, and resources that turns a general-purpose agent into a specialist for one focused domain.
Context is shared. Your skill's tokens compete with the system prompt, conversation history, other skills, and the user's request. Once SKILL.md loads it stays in context for the rest of the turn. Every line must earn its place.
The agent is already smart. Add only context it lacks. Cut explanations of well-known concepts (PDFs, for-loops, HTTP, JSON) and any sentence whose absence would not confuse a competent agent.
Reason over command. Prefer "Use pdfplumber because it handles multi-column layouts and rotated text better than alternatives" to "ALWAYS use pdfplumber". The reasoning becomes the rubric for cases the skill did not anticipate.
Write for the agent, not the human reader. The audience is an LLM ingesting tokens, not a person browsing a wiki page. Optimize for density and clarity, not visual aesthetics. Visual decoration — hard wraps that imply meaningful line breaks, blockquotes around examples, redundant "why this works" paragraphs after every code block, three-deep ladders of indented bullets, decorative Tip:/Note: wrappers around single sentences — costs tokens and earns nothing. See references/writing-patterns.md § Density for dense-vs-decorative examples.
skill-name/
├── SKILL.md # required: YAML frontmatter + markdown body
├── scripts/ # optional: executable code; output enters context
├── references/ # optional: docs loaded on demand
└── assets/ # optional: templates, schemas, imagesOnly SKILL.md is required. Drop empty directories.
Script paths are resolved relative to this SKILL.md, not the agent's CWD. If a relative command fails, prefix it with the directory the platform loaded SKILL.md from.
Fallback. If python3 is missing or a script cannot be located, every procedure here ships a manual alternative — follow that instead.
Before writing, answer all of:
/skill-name or $skill-name), or both? Determines how the description should be written and which fields you set — see § Invocation model below and Phase 3.If the user is converting an existing workflow ("turn this into a skill"), extract: steps, tools, corrections, I/O formats. Confirm the four answers above before scaffolding.
python3 scripts/init_skill.py <skill-name> --path <output-directory>Fallback. Create the directory manually with the skill name; add a SKILL.md from the template in Phase 3 plus only the subdirectories you actually need.
---
name: skill-name
description: "What this skill does AND when to use it. Max 1024 chars."
---`name` rules (must match the parent directory):
anthropic, claude)processing-pdfs, analyzing-data, testing-code#### Description by invocation model
The description's purpose changes depending on who invokes the skill. Get this wrong and the description is either dead tokens or a missed trigger.
| Invocation | What the description is for | Style |
|---|---|---|
| Model-invoked | The model scans descriptions of every installed skill at startup to decide which to load. | What it does + explicit triggers ("Use when ..."). Edge cases. Slightly pushy. Negative triggers if it over-fires. |
| User-invoked only | The slash-command picker / $skill autocomplete shows it to the user. The model never sees it. | Terse, accurate label of what the skill does. No "Use when ..." triggers. No marketing copy. The user already knows what they typed. |
| Both | The model decides whether to auto-load; the user can also force-invoke. | Triggers for the model, kept concise so the user-facing label is still readable. |
Invocation is a frontmatter decision, not a guess:
disable-model-invocation: true removes the description from the model's context entirely. Triggers in it are dead tokens. user-invocable: false does the inverse — only the model invokes; users do not see it.policy.allow_implicit_invocation: false in agents/openai.yaml makes the skill explicit-only ($skill-name); triggers in the description are equally dead.Always third person. Descriptions are injected into the system prompt. "Processes PDFs", not "I can help you process PDFs".
No XML tags, no `[TODO`, ≤ 1024 characters.
Negative triggers for model-invoked skills that fire too broadly:
description: "Advanced statistical analysis for CSV files. Use for regression, clustering, hypothesis testing. Do NOT use for basic data exploration, formatting, or simple aggregation."Debug a model-invoked description by asking the agent: "When would you use the [skill] skill?" Compare the agent's quoted understanding with your intent.
For the full optional-field reference (license, compatibility, metadata, allowed-tools, plus Claude Code and Codex extensions), see references/frontmatter-fields.md.
The body loads when the skill activates and stays in context for the rest of the turn. Keep it under 500 lines; split surplus into reference files.
Pick a structure:
| Pattern | Best for | Key feature |
|---|---|---|
| Workflow | Sequential processes | Step-by-step with checklist |
| Task-based | Tool collections | Grouped by operation type |
| Reference | Standards/specs | Organized by domain |
| Conditional | Branching logic | Decision tree pointing to references |
See references/writing-patterns.md for examples, freedom calibration, multishot prompting, checklists, script integration, and progressive disclosure.
Match freedom to fragility:
Writing principles:
Feedback-loop pattern for quality-critical operations:
1. Make the change
2. Validate: <command>
3. On failure: read error, fix, re-validate
4. Proceed only when validation passesWhen a script is unavailable, give the agent a manual checklist with the same checks.
scripts/ — executable code for deterministic operations. Output enters context; the source does not. Handle errors with helpful messages; document inputs, outputs, exit codes; test before bundling.
references/ — markdown loaded on demand. Keep one level deep from SKILL.md (chained references read as head -100 previews and lose information). Files over 100 lines need a table of contents. Split by domain, not by size.
assets/ — templates, images, schemas used in output generation. Not loaded for reasoning.
python3 scripts/validate_skill.py <path-to-skill>The validator is invocation-aware: it skips trigger-keyword warnings when disable-model-invocation: true is set, and warns if a user-invoked-only description still contains Use when ... triggers.
Fallback. Manual check:
name and description validname matches directory; ≤ 64 chars; lowercase + hyphens; no reserved wordsA skill is not done until tested with real prompts.
For automated runs, place evals in evals/evals.json:
{
"skill_name": "my-skill",
"evals": [
{"id": 1, "prompt": "...", "expected_output": "...", "assertions": ["Output includes X"]}
]
}Skills load in three tiers:
name + description for every installed skill at startupA model-invoked description fights at ~100 tokens. A user-invoked-only description fights for slash-menu legibility. The body should be comprehensive but lean.
Three modes, controlled by frontmatter:
| Mode | Set | Effect |
|---|---|---|
| Model + user | nothing (default) | Description in model context; appears in slash menu; both can invoke. |
| User-only | disable-model-invocation: true (Claude Code) / policy.allow_implicit_invocation: false (Codex) | Description not in model context; appears in slash menu; only user invokes. |
| Model-only | user-invocable: false (Claude Code) | Description in model context; hidden from slash menu; only the model invokes. |
Pair invocation control with the right neighboring fields:
/commit, /deploy, /send-slack-message) often want argument-hint for autocomplete UX, allowed-tools to skip permission prompts, and arguments for positional args.legacy-system-conventions) want a strong description with triggers — that is the only thing the model will see at startup.The agentskills.io spec is intentionally minimal: required name and description; optional license, compatibility, metadata, and experimental allowed-tools. Every vendor ships extensions on top.
Decide once, up front: cross-platform or single-vendor?
| Choice | When | What to use |
|---|---|---|
| Cross-platform | Public distribution; team uses multiple platforms; portability is the goal. | Spec frontmatter only; no vendor-only fields; forward slashes; bundle deps; document target in compatibility if narrow. |
| Single-vendor | The skill exists for one platform and will not be used elsewhere. | Use vendor extensions where they help; declare the target in compatibility; ignore other platforms. |
Single-vendor is not a smell. A commit skill that lives only in ~/.claude/skills/ should use disable-model-invocation: true, argument-hint: "[scope]", allowed-tools: Bash(git:*), and context: fork if those make the skill correct on its target. Refusing those features to "stay portable" produces a worse Claude Code skill that nobody else runs anyway. The cross-platform default applies when portability is an actual goal — not as a moral rule.
Platform-specific extensions (full reference in references/frontmatter-fields.md):
disable-model-invocation, user-invocable, argument-hint, arguments, when_to_use, model, effort, context, agent, hooks, paths, shell. Slash-command invocation /skill-name. Live change detection on ~/.claude/skills/ and .claude/skills/.agents/openai.yaml for UI metadata and policy.allow_implicit_invocation. Invocation $skill-name. Scans .agents/skills/ from CWD upward, then ~/.agents/skills/..cursor/skills/; spec-compliant frontmatter only..agents/skills/ over .gemini/skills/ when both exist..github/skills/; spec-compliant frontmatter only.Storage matrix:
| Platform | Project | User |
|---|---|---|
| Claude Code | .claude/skills/ | ~/.claude/skills/ |
| Cursor | .cursor/skills/ | ~/.cursor/skills/ |
| Gemini CLI | .gemini/skills/ | ~/.gemini/skills/ |
| OpenAI Codex | .agents/skills/ | ~/.agents/skills/ |
| VS Code / Copilot | .github/skills/ | VS Code profile |
| Cross-platform fallback | .agents/skills/ | n/a |
.agents/ is the emerging cross-platform convention. Codex uses it natively; Gemini reads it preferentially; Antigravity and OpenCode adopt it.
Precedence: project > personal > extension/plugin. (Codex shows colliding skills in the selector instead of merging.)
npx skills add <owner>/<repo> or ... --skill "<name>" for a multi-skill repo. Publish to GitHub in standard layout..skill extension; upload via Settings → Features./plugin marketplace add <owner>/<repo>.When the user asks to review or improve a skill, run all of these in addition to mechanical validation. Each step has a fix path, not just a diagnosis.
disable-model-invocation, user-invocable, and (for Codex) agents/openai.yaml policy.allow_implicit_invocation. The intended invocation model determines what counts as a problem in the description and elsewhere.commit skill without disable-model-invocation or argument-hint)? Propose adding them.Tip:/Note: wrappers, decorative external-spec citations, intra-document anchor links (use plain "see § X below" instead), bare citation URLs that the agent will never fetch. Flag and propose tighter alternatives. Lead by example: do not write the review report itself in the style being criticized.scripts/validate_skill.py for body length, reference depth, forward slashes, frontmatter validity.The order matters. Step 1 reframes Step 2; without it, you will give bad advice about the description.
Critical (skill never activates correctly):
"Analyzes git diff, identifies the change type, generates a commit message". Good: "Use when generating commit messages. Handles conventional commits, scope detection, breaking changes."High impact (degrade performance):
assets/<name>.md, referenced from SKILL.md. Inlining a per-type catalog loads every variant on every invocation and obscures the skill's structural shape. Inline only when the block is small and used unconditionally.disable-model-invocation, allowed-tools, or argument-hint on a skill that lives only in ~/.claude/skills/ is missed value. Portability is a goal, not a moral rule.disable-model-invocation: true (Claude Code) or allow_implicit_invocation: false (Codex), the model never reads the description. The triggers consume the user-facing label budget for nothing.Medium impact (token bloat, lower quality):
Tip:/Note:/Important: wrappers around single sentences. The reader is a model; visual decoration costs tokens with no benefit. See references/writing-patterns.md § Density.[agentskills.io spec](https://agentskills.io/specification), [Platform targeting](#platform-targeting), bare citation URLs at the end of a sentence — these are documentation aesthetics. The agent does not click during normal execution; the whole SKILL.md is already in context. Anchor links break on heading rename and add nothing the model could not get from "see § Platform targeting below". External URLs are noise unless the agent is genuinely expected to WebFetch them as part of the procedure (rare). Functional links to bundled files — [references/foo.md](references/foo.md) — are different: the path is the operand the agent passes to Read/bash, the link text gives loading context. Keep those.MUSTs without reasoning.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.