| name | overlay |
| description | Wrap a borrowed Anthropic SKILL.md under a governed runx overlay, with scope bounds, an allowed-tool set, and a pinned digest, so the open skill ecosystem can run under runx authority without editing the upstream skill. |
| runx | {"category":"authoring"} |
Overlay Generator
Make any borrowed skill safe to run by wrapping it in a governed overlay.
The open ecosystem is full of SKILL.md files. They carry capability and no
governance. An overlay is how runx adopts one without forking it: a same-schema
X.yaml that wraps the borrowed skill and adds the runx envelope, scope
bounds, an explicit allowed-tool set, and a pinned content digest. The upstream
skill is never edited; the overlay governs it. This skill authors that overlay
and reports the diagnostics that decide whether it is safe to run.
What this skill does
- Resolve the wrapped skill. Take a registry ref (
vendor/research@1.2.0)
or a local path (./vendor/research/SKILL.md) and confirm it resolves.
- Pin the content. Record a digest of the wrapped
SKILL.md so a later
upstream change is detected, not silently inherited.
- Bound the authority. Propose the narrowest scopes and the explicit
allowed-tool set the skill needs; an empty scope set is a diagnostic, not a
default-allow.
- Emit the overlay. Produce a canonical
skills-overlays/<vendor>/<skill>/X.yaml that wraps the skill and carries the
runx envelope, plus the diagnostics that gate it.
Core principles
- Wrap, never fork. The overlay references the upstream skill; it does not
copy or edit it.
- Most-restrictive-wins. Effective scopes are the intersection of any graph
step scopes and the overlay's runner scopes; the overlay can only narrow.
- Pin the digest. A borrowed skill is pinned by content digest so an
upstream edit raises
runx.overlay.digest.stale instead of running unseen
changes.
- No empty grant. An overlay with no scopes is
runx.overlay.scope.empty,
never an implicit allow-all.
- Wraps is governance, not inheritance. The overlay does not adopt the
upstream skill's behavior; it bounds it.
When to use this skill
- Adopting a third-party or Anthropic-standard skill into a governed runx graph.
- Pinning a borrowed skill so upstream drift is detected.
- Tightening the scopes a borrowed skill runs under.
When not to use this skill
- To author a first-party skill from scratch (use
skill-lab).
- To change the wrapped skill's behavior. Overlays bound; they do not patch.
The overlay model
The proposal fills a skills-overlays/<vendor>/<skill>/X.yaml:
skill: vendor/research
wraps: vendor/research@1.2.0
runners:
default:
type: agent
scopes:
- web.read
- repo.read
runx:
allowed_tools:
- web.search
- fs.read
Graphs must reference the overlay, never the raw SKILL.md. Direct raw
SKILL.md invocation is allowed only for interactive human CLI runs, with a
warning.
Diagnostics
runx.overlay.skill.missing (error): the wrapped ref or path does not resolve.
runx.overlay.digest.stale (warning): the local wrapped digest no longer
matches the pinned digest.
runx.overlay.scope.empty (error): the overlay declares no scopes.
runx.overlay.tools.unbounded (warning): scopes are declared but no explicit
allowed_tools set bounds them.
Procedure
- Resolve exactly one wrapped skill from
skill_ref or skill_path. With both
present, confirm they refer to the same skill or return needs_input.
- Read the wrapped
SKILL.md and compute its pinned digest. Never copy the
upstream skill into the overlay.
- Identify the tools, network access, filesystem access, credentials, and
mutation surfaces the wrapped skill actually needs.
- Translate that need into the narrowest runner scopes and
allowed_tools set.
If a needed capability cannot be bounded, return reject.
- Emit the canonical overlay path,
wraps reference, digest, runner type,
scopes, allowed tools, diagnostics, and reviewer rationale.
- Require graph users to reference the overlay path, not the raw upstream
SKILL.md.
Edge cases and stop conditions
- Wrapped skill missing: return
needs_input or reject; never create an
overlay for an unresolved ref.
- Digest mismatch: emit
runx.overlay.digest.stale; the operator must
re-review before trusting the upstream change.
- No declared scopes: emit
runx.overlay.scope.empty and block
decision: ready.
- Unbounded tool access: warn or reject depending on risk; mutation or secret
access without an explicit tool set is not ready.
- Scope intent exceeds the wrapped skill's real need: narrow the grant or
return
needs_input; do not use the overlay as an authority escalation path.
- Raw secret material in the wrapped skill instructions: reject unless the
overlay can keep the material out of prompts, outputs, and receipts.
Output schema (overlay_proposal)
decision: ready | needs_input | reject
wraps:
ref: string
path: string
digest: string
overlay_path: string
runner:
type: agent | agent-task
scopes: [string]
allowed_tools: [string]
diagnostics:
- id: string
severity: error | warning
message: string
rationale: string
blockers: [string]
needs_input: [string]
success_checkpoint:
milestone: string
description: string
A proposal with any error diagnostic must not be ready.
Worked example
Wrap the borrowed vendor/research@1.2.0 skill so a docs graph can call it. The
overlay pins the digest, binds type: agent with scopes web.read and
repo.read, and an allowed-tool set of web.search and fs.read. The wrapped
ref resolves and the scopes are non-empty, so the lint is clean and the decision
is ready. The graph then references
skills-overlays/vendor/research/X.yaml, never the raw SKILL.md.
Inputs
skill_ref (optional): a registry ref, e.g. vendor/research@1.2.0.
skill_path (optional): a local path to a borrowed SKILL.md.
scope_intent (optional): what the skill should be allowed to do, in prose.
objective (optional): operator intent that focuses the bound.
At least one of skill_ref or skill_path is required; with neither, the skill
returns needs_input.