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.md file with YAML front‑matter containing name and description
  • The system validates names against strict regex rules and checks description length via validateName and validateDescription in packages/coding-agent/src/core/skills.ts
  • Skills are automatically discovered by loadSkillsFromDir and injected into the LLM prompt as XML via formatSkillsForPrompt
  • Use disable-model-invocation: true to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →