Pure data struct representing a registered skill in SkillKit.
SkillKit.Skill is a plain Elixir struct that carries all identity,
execution, and hook configuration for a skill. When :tool names a module,
that module executes the skill and is exposed to the model when the skill is
activated. :tool defaults to nil — a knowledge-only skill whose body is
injected on activation but which exposes NO executable tool. A tool (e.g.
SkillKit.Tools.Shell) is opt-in, never a silent default: set it explicitly
via the SkillKit.Kit macro (use SkillKit.Kit, which patches :tool to the
kit module) or by constructing the struct directly.
Struct Fields
| Field | Type | Default | Description |
|---|
:name | `String.t() | nil` | nil | Fully-qualified "namespace:skill_name" |
:namespace | `String.t() | nil` | nil | Namespace segment extracted from name |
:description | `String.t() | nil` | nil | Human-readable description |
:body | `String.t() | nil` | nil | Skill body / prompt template |
:location | `String.t() | nil` | nil | File path or source location for this skill |
| :required_scope | [String.t()] | [] | Scopes required to call this skill |
| :tool | module() | nil | nil | Module that executes the skill, or nil for a knowledge-only skill (no tool exposed) |
| :hooks | [SkillKit.Hook.t()] | [] | Lifecycle hooks attached to this skill |
| :metadata | %{String.t() => term()} | %{} | Arbitrary key-value metadata from frontmatter |
Naming Convention
Skill names follow the format "namespace:skill_name", where:
- Both segments are lowercase, starting with a letter
- Segments may contain letters, digits, underscores, and hyphens
- Exactly one colon separates the namespace from the skill name
Examples: "files:read", "tools:web-search", "my-org:analyze_data"
Reserved Metadata Keys
Most :metadata is opaque and passed through untouched. One key is
reserved by the framework:
"model"— runs the skill's activation sub-loop on a specific model instead of the parent agent's. The value is a provider-URI string in the same form asAGENT.md'smodel:(e.g."anthropic://claude-sonnet-4-6","openinfer://...", or a bare model name resolving to the default provider;?max_tokens=...-style query params ride along to the provider). When unset, blank, or naming a provider that isn't configured, the activation falls back to the parent agent's model (the fallback is logged). Declared inSKILL.mdfrontmatter undermetadata::--- name: design description: Authors the OG template Liquid. metadata: model: "anthropic://claude-sonnet-4-6?max_tokens=8000" ---
Summary
Functions
Renders the skill body by substituting template tokens with values from args.
Types
Functions
Renders the skill body by substituting template tokens with values from args.
Supported tokens:
$ARGUMENTS— all arguments as a single string (fromargs["arguments"])$ARGUMENTS[N]— positional argument by 0-based index (space-split)$N— shorthand for$ARGUMENTS[N](e.g.,$0,$1)$SKILL_DIR/${SKILL_DIR}— directory of the skill (derived from:location)$SESSION_ID/${SESSION_ID}— session ID (fromargs["session_id"])- Legacy
${CLAUDE_SKILL_DIR}and${CLAUDE_SESSION_ID}are still supported.
When a scope implementing SkillKit.Scope is provided, any remaining
$VAR / ${VAR} tokens are resolved via Scope.resolve/3 as a final
fallback. Unresolved scope variables are left as-is.
If $ARGUMENTS (or $N) is NOT present in the body but arguments are provided,
appends \n\nARGUMENTS: <value> to the end.
Returns {:ok, ""} when body is nil.