Skills System¶
Skills extend Keen Code's capabilities through specialized instruction sets that can be activated during a conversation.
Skill Structure¶
Each skill is a directory containing a SKILL.md file:
skills/
└── my-skill/
└── SKILL.md
SKILL.md Format¶
Skills use YAML frontmatter followed by markdown content:
---
name: my-skill
description: Does something useful
---
Instructions for the skill...
Reference arguments with $ARGUMENTS, $1, $2, etc.
Required frontmatter:
- name: Unique identifier for the skill
- description: Brief description shown in the catalog
Skill Discovery¶
Skills are discovered from multiple locations (internal/skills/discover.go):
func discoveryRoots(workingDir, bundledDir string) []string {
roots := []string{
filepath.Join(workingDir, ".agents", "skills"),
filepath.Join(workingDir, ".keen", "skills"),
filepath.Join(home, ".agents", "skills"),
filepath.Join(home, ".keen", "skills"),
}
if bundledDir != "" {
roots = append(roots, bundledDir)
}
return roots
}
Priority order:
1. <working-dir>/.agents/skills/
2. <working-dir>/.keen/skills/
3. ~/.agents/skills/
4. ~/.keen/skills/
5. Bundled skills directory
Skill Metadata Parsing¶
// internal/skills/parse.go
type Skill struct {
Name string
Description string
Location string
}
func ParseSkillMetadata(path string, data []byte) (Skill, error)
The parser:
1. Splits frontmatter from content (delimited by ---)
2. Parses YAML frontmatter
3. Validates required fields
4. Returns absolute path for the skill
Skill Configuration¶
// internal/skills/config.go
type Config struct {
IsEnabled map[string]bool `json:"is_enabled"`
}
Config file: ~/.keen/skills/config.json
- Skills are enabled by default if not in the config
- Use
Config.Enabled(name)to check if a skill is enabled - Use
Config.SetEnabled(name, enabled)to modify enabled state
Bundled Skills¶
Bundled skills are embedded in the binary using Go's embed directive:
//go:embed all:bundled
var bundledFS embed.FS
EnsureBundled() extracts them to ~/.keen/skills/bundled/ on each startup to ensure the binary's version is always available.
Skill Catalog¶
The Catalog() function generates a markdown catalog for the system prompt:
func Catalog(all []Skill, cfg Config) string
Output format:
## Available Skills
You have access to specialized skills. To activate a skill, use the read_file tool
to read the skill's SKILL.md file at one of these paths, then follow the instructions
within...
- skill-name: Description → /path/to/SKILL.md
IMPORTANT: If any user message in this conversation begins with
`[Activate skill: <name>]`, the SKILL.md body for that skill has already been
provided inline in that message — do not call read_file on its path.
Skill Activation¶
To activate a skill, the LLM reads the SKILL.md file. The content is injected as a user message prefixed with:
[Activate skill: <name>]
<SKILL.md content>
Argument Substitution¶
Arguments passed during activation are substituted into the skill body:
$ARGUMENTS→ all arguments joined by space$1,$2, etc. → individual arguments
// internal/skills/discover.go
var argPlaceholder = regexp.MustCompile(`\$ARGUMENTS\b|\$([1-9])\b`)
func substituteArgs(body string, args []string) string {
return argPlaceholder.ReplaceAllStringFunc(body, func(match string) string {
if match == "$ARGUMENTS" {
return strings.Join(args, " ")
}
idx := int(match[1]-'0') - 1
if idx < len(args) {
return args[idx]
}
return ""
})
}
Discovery and Loading¶
The discovery process:
func Discover(workingDir, bundledDir string) Discovery
func LoadMetadata(discovery Discovery) Discovery
Discover()finds allSKILL.mdfiles across discovery rootsLoadMetadata()reads and parses each skill's frontmatter- Duplicate names are reported as warnings
type Discovery struct {
Skills []Skill
Warnings []string
}
Finding Skills¶
func Find(skills []Skill, name string) (Skill, bool)
Look up a skill by name from the discovered list.
Example Skill Structure¶
~/.keen/skills/
├── git-helper/
│ └── SKILL.md
├── code-review/
│ └── SKILL.md
└── test-generator/
└── SKILL.md
With content:
---
name: git-helper
description: Assists with git operations
---
You are a git assistant. When the user asks about git, help them with:
- Creating commits (but prompt before executing dangerous ops)
- Viewing history
- Managing branches
Use the bash tool for git operations.