SkillKit uses the Agent Skills open standard for defining skills. This guide covers the file format, frontmatter fields, and template tokens available when writing skill files.

For how skills are loaded and registered, see the Providers guide.

The SKILL.md file

Each skill is defined in a SKILL.md file inside a named directory, following the Agent Skills and Claude Code plugin conventions. The file combines YAML frontmatter with a markdown prompt body:

---
name: "files:read"
description: Read the contents of a file at the given path.
---
Read the file at $ARGUMENTS and return its full contents.

The frontmatter section (between --- delimiters) contains metadata. Everything below the closing --- is the skill body — the prompt template that gets rendered when the skill is activated.

Frontmatter fields

Required

FieldTypeConstraints
namestringMust follow "namespace:skill_name" format. Both segments must be lowercase, start with a letter, and match ^[a-z][a-z0-9_-]*$.
descriptionstringNon-empty. Describes what the skill does and when to use it.

Optional

FieldTypeDefaultNotes
required_scopelist or string[]Scope strings required for authorization. A single string is coerced to a one-element list.
metadatamap%{}Arbitrary key-value pairs for custom metadata.
hooksmap%{}Lifecycle hooks scoped to this skill. See Hooks and Execution.

Example with all fields

---
name: "admin:purge"
description: Purge stale records from the database.
required_scope:
  - "admin:write"
  - "audit:log"
metadata:
  author: platform-team
  version: "1.2"
hooks:
  PreToolUse:
    - matcher: "bash"
      hooks:
        - type: command
          command: "check-policy $TOOL_NAME"
  PostToolUse:
    - matcher: ".*"
      hooks:
        - type: http
          url: "https://audit.example.com/log"
  PreSubagent:
    - matcher: ".*"
      hooks:
        - type: command
          command: "echo delegating to subagent"
---
Purge all records older than $ARGUMENTS days.

Template tokens

The skill body supports token substitution at activation time. These tokens are replaced with runtime values before the rendered body is returned.

Argument tokens

TokenDescription
$ARGUMENTSAll arguments as a single string.
$ARGUMENTS[N]Positional argument by 0-based index (space-split).
$NShorthand for $ARGUMENTS[N] (e.g. $0, $1).

If $ARGUMENTS (or any $N token) is not present in the body but arguments are provided, \n\nARGUMENTS: <value> is appended automatically.

Context tokens

TokenDescription
$SKILL_DIRDirectory containing the skill file.
$SESSION_IDCurrent session identifier.
${CLAUDE_SKILL_DIR}Alias for $SKILL_DIR (Claude Code compatibility).
${CLAUDE_SESSION_ID}Alias for $SESSION_ID (Claude Code compatibility).

Scope variables

When a scope struct implementing SkillKit.Scope is provided, any remaining $VAR or ${VAR} tokens are resolved via Scope.resolve/3. Unresolved variables are left as-is.

---
name: "team:greeting"
description: Greet the current user.
---
Hello $USERNAME, welcome to $TENANT.

If the scope's resolve/3 returns {:ok, "alice"} for "USERNAME" and {:ok, "acme"} for "TENANT", the rendered body becomes Hello alice, welcome to acme.

Dynamic commands

The !`<command>` syntax executes a shell command during rendering and replaces the token with the command's output. This is preprocessing — the LLM receives the final output, not the command.

---
name: "git:context"
description: Gather git context for the current branch.
---
Current branch: !`git branch --show-current`
Recent commits: !`git log --oneline -5`

Naming conventions

SkillKit uses a "namespace:skill_name" naming scheme:

  • namespace — groups related skills (e.g. files, admin, tools)
  • skill_name — identifies the specific skill within the namespace

Both segments must start with a lowercase letter and contain only lowercase letters, digits, hyphens, and underscores.

When using the Local provider, the namespace comes from the kit (directory) name and the skill name from the frontmatter name field. The fully-qualified name is "<kit_name>:<skill_name>".

Authorization and permissions

Different platforms handle skill authorization differently:

  • Agent Skills spec (agentskills.io): Defines allowed-tools for pre-approving tool access. Authorization is left to the host agent.
  • Claude Code (code.claude.com): Uses allowed-tools, disable-model-invocation, and user-invocable frontmatter fields to control who can invoke a skill and what tools it can access. Permission rules like Skill(name) restrict Claude's access.

SkillKit uses required_scope for authorization. Scopes are checked against the caller's permissions (provided via a struct implementing SkillKit.Scope) at both discovery and activation time. See Authorization for the full model.

Relationship to the Agent Skills standard

SkillKit's skill format is compatible with the Agent Skills specification. Key differences:

  • Authorization: Agent Skills uses allowed-tools. SkillKit uses required_scope for scope-based access control.
  • Template tokens: $ARGUMENTS, $N, $SKILL_DIR, and $SESSION_ID are shared with Claude Code. SkillKit adds scope variable resolution.
  • Progressive disclosure: Both follow the same three-tier model — metadata at discovery, full body at activation, supporting files on demand.