How Kimi CLI Implements Skill Loading and Execution for Workflow Automation
Kimi CLI discovers automation skills by scanning built-in, user, and project directories for SKILL.md files, registers them as slash commands (/skill:<name> and /flow:<name>), and executes them by either injecting the skill instructions into the LLM context or by parsing and running automated flowcharts.
The Kimi CLI (MoonshotAI/kimi-cli) treats skills as self-contained automation units that extend the assistant's capabilities. When the interactive shell starts, it executes a discovery pipeline that resolves skill roots, indexes available capabilities, and registers them as first-class slash commands, enabling both manual invocation and deterministic workflow automation.
Skill Discovery from Multiple Roots
The discovery process begins inside resolve_skills_roots() in src/kimi_cli/soul/agent.py (lines 229–236), which aggregates skill directories from three distinct scopes:
- Built-in: Packaged skills located at
src/kimi_cli/skills - User-level: Global user directories such as
~/.kimi/skillsand~/.agents/skills - Project-level: Local workspace directories like
.kimi/skillsor.agents/skills
Additional paths supplied via --skills-dir CLI arguments or the extra_skill_dirs parameter are appended to this list.
Once roots are resolved, discover_skills_from_roots() in src/kimi_cli/skill/__init__.py (lines 229–238) walks each directory tree. It identifies skills using two layout conventions:
- Directory-based: A subfolder containing a mandatory
SKILL.mdfile (canonical layout) - Flat file: A single
<name>.mdfile (supported since v0.69)
The Skill Model and Indexing
For every discovered skill, the CLI instantiates a Skill model defined at lines 405–425 in src/kimi_cli/skill/__init__.py. This dataclass captures:
name: The invocation identifierdescription: Help text shown in command listingstype: Eitherstandardorflowpath: Absolute filesystem locationflow: A parsedFlowobject (present only for flow-type skills)
The index_skills() function builds a dictionary mapping name → Skill for O(1) lookups during execution. Separately, format_skills_for_prompt() renders a concise catalog that is injected into the system prompt, allowing the LLM to reason about available tools without loading their full content.
Registering Skills as Slash Commands
Inside KimiSoul.__init__ at src/kimi_cli/soul/kimisoul.py (lines 858–891), each indexed skill is exposed as a slash command. The registration logic prepends SKILL_COMMAND_PREFIX (typically /skill:) to the skill name:
name = f"{SKILL_COMMAND_PREFIX}{skill.name}"
self._runtime.register_slash_command(
name,
func=self._make_skill_runner(skill),
description=skill.description or ""
)
Flow skills receive an additional registration: a /flow:<name> command that instantiates a FlowRunner rather than the standard text injector. This dual registration allows users to choose between manual LLM-guided execution (via /skill:) or automated graph traversal (via /flow:).
Executing Standard Skills
When a user invokes /skill:<name>, the _make_skill_runner() method returns an async function that executes three steps:
- Load: Calls
read_skill_text()(lines 392–426 insrc/kimi_cli/skill/__init__.py) to read theSKILL.mdfile and inline any referenced external files. - Compose: Optionally appends the user's specific request (
extraparameter). - Inject: Creates a new user message containing the combined text and passes it to
soul._turn(), effectively prepending the skill instructions to the conversation context.
This causes the LLM to continue reasoning while adhering to the skill's embedded guidelines.
Flow-Based Workflow Automation
Flow skills enable deterministic automation by encoding workflow logic as diagrams. When invoked via /flow:<name>, the system creates a FlowRunner instance (lines 1787–1825 in src/kimi_cli/soul/kimisoul.py).
The execution pipeline proceeds as follows:
- Parse: The
Flowobject is extracted from the first Mermaid or D2 fenced code block insideSKILL.mdusing parsers located insrc/kimi_cli/skill/flow/. - Traverse: The runner starts at the virtual
BEGINnode and walks the graph, prompting the LLM at each task node. - Decide: Edge selection is performed automatically using
parse_choiceon the LLM's reply, routing to the next node based on semantic intent. - Terminate: Execution halts when the
ENDnode is reached or an error boundary is encountered.
# Example flow skill execution
>>> /flow:release
BEGIN → "Run unit tests" → "Build package" → "Deploy to production" → END
Runtime Integration
The skill subsystem integrates with the UI layer through the runtime object in src/kimi_cli/soul/agent.py. This runtime passes the skills dictionary and allowed skills_dirs to the interactive shell frontend. In src/kimi_cli/ui/shell/slash.py, the UI renders visible slash commands, handles tab-completion, and expands placeholders before dispatching to the registered runner functions.
Summary
- Multi-root discovery: Scans built-in, user, and project directories via
resolve_skills_roots()anddiscover_skills_from_roots(). - Structured indexing: Creates
Skillobjects and builds a fast lookup index while formatting a lightweight catalog for the system prompt. - Dual command registration: Exposes skills as
/skill:<name>(text injection) and/flow:<name>(automated execution) viaKimiSoul.__init__. - Flexible execution: Standard skills inject
SKILL.mdcontent into the LLM context; flow skills parse Mermaid/D2 diagrams and execute viaFlowRunner. - Deterministic workflows: Flow skills traverse nodes from
BEGINtoEND, automatically routing based on LLM responses parsed throughparse_choice.
Frequently Asked Questions
What file structure defines a valid Kimi CLI skill?
A valid skill requires either a directory containing a SKILL.md file (canonical layout) or a standalone <name>.md file (flat layout, supported since v0.69). The SKILL.md file must include a YAML frontmatter block specifying at minimum the name and description fields, followed by the skill instructions or a flowchart definition.
How does Kimi CLI prioritize skill directories when duplicates exist?
The CLI resolves skills in the order: built-in → user-level → project-level → extra directories. Later registrations overwrite earlier ones in the internal index, allowing project-level and user-level skills to override built-in defaults with the same name.
What is the difference between /skill: and /flow: commands?
The /skill:<name> command loads the skill's text via read_skill_text() and injects it as a user message, allowing the LLM to interpret the instructions organically. The /flow:<name> command instantiates a FlowRunner that parses the embedded diagram and automatically executes the workflow graph, moving between nodes deterministically until reaching the END state.
Can skills reference external files beyond SKILL.md?
Yes. The read_skill_text() function in src/kimi_cli/skill/__init__.py resolves relative file references within the skill directory and inlines their contents into the final prompt text. This allows skills to modularize large instruction sets or include template files without bloating the main SKILL.md.
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 →