Discover existing community Claude skills and merge the best into one tailored, security-scanned set.
SaferSkills independently audited skillmeld (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.
This skill is the front-end that drives the bundled skillmeld Python engine. The engine is deterministic and makes no model calls; you supply the judgment and gate every side effect on the user's approval.
Turns a described use case (plus the user's repo) into a coherent skill set assembled from existing community skills: discover candidates, security-scan them, merge the best two or three, and install with the user's approval. Composes existing skills; never writes new instructions from scratch.
The deterministic engine is invoked from this skill via:
bash "${CLAUDE_SKILL_DIR}/scripts/run.sh" <command> [args...]
run.sh is a thin wrapper; equivalently, run uv run skillmeld <command> from the package root. The steps below use the run.sh form.
Each command prints JSON to stdout. This skill reads that JSON and supplies the judgment steps (grouping atoms, adjudicating conflicts, choosing among existing options) in-session. The engine itself makes no model calls.
run.sh intake "<use case>" normalizes the request and flags whether it is thin.Treat thin as a floor, not a ceiling: the engine only sees length and vague words, never domain ambiguity. Ask at most one or two scoping questions when EITHER the request is thin OR you recognize a material fork the engine cannot — a choice that changes which skills are relevant or what the output must cover (a target runtime, platform, or framework with incompatible variants is the usual case). Otherwise echo the understood goal and move on. Keep it to genuine forks; never interrogate.
run.sh ground <repo> collects deterministic evidence and a partial profile.Complete the profile yourself from the session: write summary (2-3 sentences) and tasks (3-6 representative tasks in the user's words), then save the completed profile JSON to a temp file.
run.sh discover --profile <profile.json> prefilters the synced catalog andprints scored candidates with per-match evidence (matched). Skills already blocked by the verdict index are dropped before anyone sees them.
description, tags, and matched evidence; ignore files. Answer with existing candidate ids only — never invent an id — best first, at most three. Then run.sh select --candidates <discover.json> --choose id1,id2 validates the pick and surfaces warnings (for example, two picks from the same source repo).
run.sh fetch --selection <select.json> downloads only the chosen bundles andverifies every file against the hash the signed catalog pinned; a mismatch refuses the bundle. Run this only after the user has seen the shortlist. Carry the exact path values fetch returns into scan and merge — the cache is content-addressed and shared across runs, so globbing the bundles directory will pull in other selections' skills. Map each path by the id fetch reports next to it, never by directory order.
run.sh scan <bundle> [--sources <discover.json>] for each: PASS proceeds,REVIEW is surfaced for a decision, BLOCK is refused. Pass --sources so a skill whose repo license the catalog already knows is not flagged license-unknown just because the LICENSE file stayed out of the bundle.
run.sh merge --bundles <dir>... --profile <profile.json> runs the eight-stepengine: parse, dedupe, group, conflict-detect, reconcile, prune, partition, and verify. You supply the judgment the engine asks for and nothing more:
--grouping <file.json> mapping each atom id to {group, kind} — ids only, drawn from the parsed atoms. A Python-detected directive can never be relabelled to a softer kind; the engine forces it back and tells you. Omit the flag to let the engine group by source.
or add a semantic one, pass --adjudication <file.json> (a list of conflicts). You can never make a flagged structural conflict disappear. The result carries a plan (what was kept, dropped, deduped, and why) and a problems list. problems MUST be empty — a non-empty list means the byte-traceability verifier rejected the merge; never install a rejected result. The merge also carries each source's tool and invocation frontmatter onto the children, reconciled (allowed-tools narrowed to the intersection, disallowed-tools unioned, disable-model-invocation honored); when that drops a pre-approved tool or leaves a child non-invocable, plan.frontmatter_verdict is review and plan.frontmatter_findings says why. Hold the consolidated review until the set is complete (after step 8).
description empty onpurpose (it never invents text), so each one must be authored before it can ship; a skill with no description never triggers in Claude Code. For each child, write a short, trigger- friendly description and gate it through run.sh eval improve --skill <index|orchestrator> --description "..." with the trigger queries and routing judgments — an edit is accepted only if structural quality holds, no held-out query leaks, and the held-out routing pass-rate does not regress — measured both from your reported routing and from an independent engine-side pass that routes the queries against the descriptions, so acceptance never rests on your self-report. Phrase each description with the literal words a user would say; the independent router keys on them. Keep it within the routing budget — Claude Code truncates the description at 1536 characters in its skill listing and the API surface caps it at 1024, so lead with the key use case. The orchestrator ships with a templated routing description already; refine it the same way (--skill orchestrator) only if needed. Then run.sh eval run must report passed: true over the set. With the set now complete, show the user the plan and the authored descriptions as one consolidated review before writing anything.
run.sh emit <surface> packages the result; install only after the user approves. Emitrefuses any skill (child or orchestrator) whose description is still empty, so a set can never ship dead even if this step was rushed. Each surface returns warnings to relay before install: emit claude-code and emit claudeai flag any description over the 1536-char Claude Code routing cap (truncated in the skill listing, so routing keywords are lost); emit api flags a description over the 1024-char /v1/skills cap (the upload is rejected), plus any tool or invocation frontmatter that surface does not enforce.
Every atom in the merged output traces byte-for-byte to a source skill; the engine invents no instruction text. Nothing is fetched, merged, or installed without showing the user what will happen and getting approval.
Two human stops on the happy path; everything else streams as narrated progress.
Found 11 -> 5 PASS, 2 REVIEW, 4 dropped (1 blocked) -> drafting merge.... A multi-turn run should never look hung.
single consolidated card, not per-skill or per-finding prompts:
templated), so the user sees what fires before it is installed;
line (pdf-helper reads ~/.aws/credentials, line 34), not boilerplate;
plan.frontmatter_findings (a source's pre-approved tool droppedin the intersection, or a child left non-invocable), named for the skill it affects;
Actions: Approve and install / Adjust / Dry-run / Cancel.
artifact (run.sh scan <merged-bundle>); a BLOCK here refuses the install. Write to .claude/skills/<name>/ with SKILL.md, supporting files, and PROVENANCE.md only after the user accepts.
BLOCK is refused and excluded before the user chooses. Keep BLOCK rare and high-precision so REVIEW prompts stay trusted.
skill was picked, the 2-3 bullet "what was merged and why" reflection, and a pointer to PROVENANCE.md and the sources. Everything deep (full findings, per-line evidence, raw scores) lives behind "show details".
A non-interactive escape (--yes / --all, when wired) may skip the REVIEW prompt for CI, but never bypasses a BLOCK.
The JSON shapes you author by hand, so you do not have to read the engine source:
ground prints a partial one; complete summary + tasks):{"summary": "...", "languages": ["Python"], "frameworks": ["Grasshopper"], "conventions": [], "tasks": ["..."]}. Discovery weights matches by inverse document frequency, so a precise term ("script component") pulls more than a broad one ("python") — phrase tasks with the specific words the use case turns on.
discover prints {"candidates": [...], ...}. Each candidateis {"score": N, "matched": [...], "entry": {...}} — the skill's fields are nested under entry: entry.id, entry.description, entry.source.license.spdx_id, entry.files. Rank by reading entry + matched. select --choose wants the exact entry.id, which for a monorepo skill is owner/repo:path/to/skill (bare owner/repo only for a single-skill repo).
eval run/improve --queries): a list of{"id": "q1", "text": "...", "kind": "trigger" | "near-miss", "expected_skill": "<name|null>"}. A trigger must route to expected_skill; a near-miss must route nowhere. The split is deterministic — every Nth id by sorted order is held out — and selection is on the held-out pass-rate, so an edit must improve genuine routing, not memorize the train queries.
--judgments, --baseline-judgments, --candidate-judgments): a list of{"query_id": "q1", "routed_skill": "<name|null>"} — your report of where the orchestrator sent each query, before and after the edit. The engine also routes the queries itself against the descriptions as a cross-check: eval run adds an independent_trigger score and any routing_disagreements, and eval improve rejects an edit whose independent held-out routing regresses even when your reported routing held.
merge --sources <discover.json> and emit --sources <discover.json>re-attach the per-source licenses discovery knew (matched by bundle hash), so the plan and PROVENANCE.md show the real license instead of "unknown". A merged set is only as licensed as its least-licensed part: one unlicensed source resolves the whole set to unknown — surface that.
merge prints {"result": ..., "problems": [...]}. Inside result,each child is skills[i].doc with frontmatter.{name, description} and body; the router is orchestrator.doc; plan carries kept/dropped/drop_reasons/conflicts_resolved/ license_resolution/warnings, plus frontmatter_verdict (pass/review) and frontmatter_findings for any carried-frontmatter REVIEW. A child may also carry frontmatter.{allowed-tools, disallowed-tools, disable-model-invocation, compatibility, metadata} reconciled from its sources. The description you author goes in frontmatter.description.
{"decision": ..., "result": ...} with the wholeupdated set. To author several descriptions, feed the returned result into the next improve so edits accumulate; author the children one at a time, then run eval run over the final result.
eval and emit take either the bare result object or the full {result, problems} (the loaders accept both). A "coarse confidence band" on the review card is your judgment to add, not a field the engine fills — plan.confidence stays null unless you set it.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.