How to Create Skills for pi‑ai: A Complete Developer Guide
Creating skills for pi‑ai involves defining a directory with a SKILL.md metadata file and executable scripts, which the Mom Slack‑bot automatically discovers, validates, and exposes to the LLM via XML in the system prompt.
The pi‑ai framework, part of the badlogic/pi‑mono repository, powers Mom, a Slack‑bot that extends its capabilities through modular skills. These skills are small CLI tools that live inside the workspace and are automatically integrated into the LLM's context. Understanding how to create skills for pi‑ai allows developers to add custom functionality without modifying the core codebase.
What Are pi‑ai Skills?
Skills in pi‑ai are reusable CLI tools that function as extensions to the Mom Slack‑bot. Each skill resides in its own directory and contains a SKILL.md file describing its purpose, along with executable scripts that perform the actual work. The system automatically discovers these skills, validates their metadata, and includes them in the LLM's system prompt as XML definitions, allowing the model to understand and invoke available tools dynamically.
Skill Directory Structure and Location
The pi‑ai system recognizes skills based on their location within the workspace directory tree. According to packages/mom/src/agent.ts (lines 5‑8), skills can exist at two distinct scopes.
Global vs Channel‑Specific Skills
Global skills reside under <workspace>/skills/<name>/ and are available across all channels in the workspace. Channel‑specific skills live under <workspace>/<channel>/skills/<name>/ and are only exposed to the LLM when processing conversations in that specific Slack channel. This dual structure allows developers to deploy organization‑wide utilities alongside specialized tools for individual teams.
Creating the SKILL.md Metadata File
Every skill must contain a SKILL.md file at its root. This file serves as both documentation and configuration, using YAML front‑matter to declare metadata that the validation system consumes.
Required Front‑Matter Fields
The front‑matter must define two keys: name and description. The name field becomes the skill's identifier and must match the directory name, while the description explains the tool's purpose to the LLM. As shown in packages/mom/src/agent.ts (lines 21‑28), the system uses this metadata to build the skill registry.
Optional Configuration Flags
Developers can add disable-model-invocation: true to prevent the LLM from automatically calling the skill. When this flag is present, the skill is excluded from the system prompt's XML list, but remains accessible via explicit /skill:<name> commands.
Skill Validation and Discovery Process
The pi‑ai framework validates every skill before exposing it to the LLM. The core logic resides in packages/coding-agent/src/core/skills.ts, where loadSkillsFromDir orchestrates the discovery and validation pipeline.
Name and Description Validation
The validateName function (lines 91‑114) enforces strict naming conventions: names must be 1‑64 characters, contain only lowercase letters, numbers, and hyphens, cannot start or end with hyphens, and must match the directory name. The validateDescription function (lines 120‑128) ensures the description exists and falls within acceptable length limits.
Loading and Path Translation
The loadSkillsFromDirInternal function (lines 46‑84) recursively walks the skill directory, respects .gitignore‑style ignore patterns, and constructs Skill objects. In packages/mom/src/agent.ts, loadMomSkills (lines 21‑38) translates host filesystem paths to container paths before injecting skills into the prompt, ensuring the LLM receives correct absolute paths like /workspace/skills/<name>/SKILL.md.
Implementing Skill Logic
Beyond metadata, skills require executable components that perform actual work. These can be shell scripts, Python files, or any CLI‑compatible binary.
Executable Scripts and Tools
Place executable scripts in the skill directory alongside SKILL.md. The LLM learns about these tools by reading the SKILL.md file via the read tool (e.g., read /workspace/skills/note/SKILL.md). After reviewing the instructions, the model may request Mom to run any script inside the skill’s directory (e.g., note.sh). Mom executes the script and returns the output to the conversation.
Complete Todo Skill Example
Below is a fully functional todo list skill demonstrating the required structure:
# Directory structure
/workspace/skills/todo/
├── SKILL.md
└── todo.sh
SKILL.md contains the metadata and usage instructions:
---
name: todo
description: Simple TODO list manager
---
# Todo Skill
Run `todo.sh add <item>` to add a task, `todo.sh list` to show all tasks, and `todo.sh clear` to empty the list.
todo.sh implements the logic:
#!/usr/bin/env bash
case "$1" in
add) echo "$2" >> "$HOME/.pi/todo.txt" ;;
list) cat "$HOME/.pi/todo.txt" ;;
clear) > "$HOME/.pi/todo.txt" ;;
*) echo "Usage: $0 {add|list|clear} [args]" ;;
esac
Once deployed, Mom automatically discovers this skill and includes it in the system prompt:
<available_skills>
<skill>
<name>todo</name>
<description>Simple TODO list manager</description>
<location>/workspace/skills/todo/SKILL.md</location>
</skill>
</available_skills>
When a user asks "Add a reminder to buy milk," the LLM reads the skill file and Mom executes /bin/bash /workspace/skills/todo/todo.sh add "buy milk".
How Skills Appear in the LLM Prompt
Skills are communicated to the language model through structured XML injected into the system prompt. This mechanism allows the LLM to understand available tools without hardcoding them.
XML Formatting with formatSkillsForPrompt
The formatSkillsForPrompt function (lines 90‑103 in packages/coding-agent/src/core/skills.ts) renders each skill as XML tags containing the name, description, and absolute path to the SKILL.md file. Only skills without the disable-model-invocation flag are included in this output.
Disabling Automatic Model Invocation
To prevent the LLM from automatically using a sensitive skill, add disable-model-invocation: true to the YAML front‑matter. Such skills remain functional but require explicit user commands to activate, keeping them hidden from the model's automatic tool selection.
Invoking Skills in Conversations
Once discovered and loaded, skills can be triggered through natural language or explicit commands, depending on their configuration.
Automatic Invocation Flow
During a conversation, the LLM can request the skill's documentation using the read tool (e.g., read /workspace/skills/note/SKILL.md). After reviewing the instructions, the model may request Mom to run any script inside the skill’s directory (e.g., note.sh). Mom executes the script and returns the output to the conversation.
Explicit Command Invocation
For skills marked with disable-model-invocation: true, or when users prefer direct control, skills can be invoked via the /skill:<name> command followed by arguments. This bypasses the LLM's decision‑making and immediately executes the skill's entry point.
Summary
Creating skills for pi‑ai requires understanding the directory structure, metadata format, and validation pipeline:
- Skills reside in
<workspace>/skills/<name>/(global) or<workspace>/<channel>/skills/<name>/(channel‑specific) - Each skill requires a
SKILL.mdfile with YAML front‑matter containingnameanddescription - The system validates names against strict regex rules and checks description length via
validateNameandvalidateDescriptioninpackages/coding-agent/src/core/skills.ts - Skills are automatically discovered by
loadSkillsFromDirand injected into the LLM prompt as XML viaformatSkillsForPrompt - Use
disable-model-invocation: trueto hide skills from automatic LLM usage while keeping them available via explicit commands
Frequently Asked Questions
What file naming conventions must pi‑ai skills follow?
Skill names must be 1‑64 characters, contain only lowercase alphanumeric characters and hyphens, cannot start or end with hyphens, and must exactly match the directory name. The validateName function in packages/coding-agent/src/core/skills.ts (lines 91‑114) enforces these rules during the discovery phase.
How does pi‑ai handle skill security and permissions?
Skills operate within the containerized environment's permissions. While the LLM can only invoke skills that appear in its system prompt, sensitive operations should set disable-model-invocation: true to prevent automatic execution, requiring explicit user consent via the /skill:<name> command.
Can I create channel‑specific skills in pi‑ai?
Yes. Place skills under <workspace>/<channel>/skills/<name>/ instead of the global <workspace>/skills/<name>/ location. The loadMomSkills function in packages/mom/src/agent.ts (lines 21‑38) loads both global and channel‑specific skills, making them available only within their respective Slack channels.
Why is my pi‑ai skill not appearing in the system prompt?
First, verify that SKILL.md contains valid YAML front‑matter with both name and description fields. Check that the skill passes validation by reviewing logs for errors from validateName or validateDescription. Finally, ensure the skill does not have disable-model-invocation: true set, as this flag excludes it from the automatic prompt injection performed by formatSkillsForPrompt.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →