ExternalConfigs.Skill (fnord v0.9.34)

View Source

A parsed Agent Skill from a SKILL.md file.

The SKILL.md format is shared between Claude Code and Cursor: a directory containing a required SKILL.md with YAML frontmatter (name + description at minimum) and a markdown body. The flavor field distinguishes which ecosystem the skill came from (:claude or :cursor) so we can present them under separate headings to the coordinator.

Self-delegation opt-out

External skills frequently exist as shims that delegate Claude Code or Cursor invocations back to fnord (fnord ask -W . -q ...). When fnord itself loads such a skill, the directionality is reversed and the agent shells out to a fresh fnord process - infinite recursion.

Two fields mark a skill as "do not expose to fnord agents":

  • :fnord_skip - boolean; true iff the skill should be filtered before being offered to fnord's coordinator.
  • :fnord_skip_reason - :frontmatter (explicit opt-out via the fnord_skip: true frontmatter key) or :body_invokes_fnord (fallback body scan for fnord ask / fnord-dev ask), or nil when not skipped.

An explicit fnord_skip: false in the frontmatter overrides the body scan. This lets a skill author opt back in if their SKILL.md legitimately references fnord ask in passing.

Summary

Functions

Load a skill from a directory containing SKILL.md.

Types

flavor()

@type flavor() :: :claude | :cursor

skip_reason()

@type skip_reason() :: :frontmatter | :body_invokes_fnord | nil

source()

@type source() :: :global | :project

t()

@type t() :: %ExternalConfigs.Skill{
  body: String.t(),
  description: String.t() | nil,
  flavor: flavor(),
  fnord_skip: boolean(),
  fnord_skip_reason: skip_reason(),
  name: String.t(),
  path: String.t(),
  source: source(),
  when_to_use: String.t() | nil
}

Functions

from_dir(dir, flavor, source)

@spec from_dir(String.t(), flavor(), source()) :: {:ok, t()} | {:error, term()}

Load a skill from a directory containing SKILL.md.