SkillKit.Skill (SkillKit v0.2.0)

Copy Markdown View Source

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

FieldTypeDefaultDescription
:name`String.t()nil`nilFully-qualified "namespace:skill_name"
:namespace`String.t()nil`nilNamespace segment extracted from name
:description`String.t()nil`nilHuman-readable description
:body`String.t()nil`nilSkill body / prompt template
:location`String.t()nil`nilFile 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"

Summary

Functions

Renders the skill body by substituting template tokens with values from args.

Types

t()

@type t() :: %SkillKit.Skill{
  body: String.t() | nil,
  description: String.t() | nil,
  hooks: [SkillKit.Hook.t()],
  location: String.t() | nil,
  metadata: %{optional(String.t()) => term()},
  name: String.t() | nil,
  namespace: String.t() | nil,
  required_scope: [String.t()],
  tool: module() | nil
}

Functions

render(skill, args, scope \\ nil, scope_context \\ nil)

@spec render(t(), map(), term(), map() | nil) :: {:ok, String.t()}

Renders the skill body by substituting template tokens with values from args.

Supported tokens:

  • $ARGUMENTS — all arguments as a single string (from args["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 (from args["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.