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/skills and ~/.agents/skills
  • Project-level: Local workspace directories like .kimi/skills or .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.md file (canonical layout)
  • Flat file: A single <name>.md file (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 identifier
  • description: Help text shown in command listings
  • type: Either standard or flow
  • path: Absolute filesystem location
  • flow: A parsed Flow object (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:

  1. Load: Calls read_skill_text() (lines 392–426 in src/kimi_cli/skill/__init__.py) to read the SKILL.md file and inline any referenced external files.
  2. Compose: Optionally appends the user's specific request (extra parameter).
  3. 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:

  1. Parse: The Flow object is extracted from the first Mermaid or D2 fenced code block inside SKILL.md using parsers located in src/kimi_cli/skill/flow/.
  2. Traverse: The runner starts at the virtual BEGIN node and walks the graph, prompting the LLM at each task node.
  3. Decide: Edge selection is performed automatically using parse_choice on the LLM's reply, routing to the next node based on semantic intent.
  4. Terminate: Execution halts when the END node 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() and discover_skills_from_roots().
  • Structured indexing: Creates Skill objects 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) via KimiSoul.__init__.
  • Flexible execution: Standard skills inject SKILL.md content into the LLM context; flow skills parse Mermaid/D2 diagrams and execute via FlowRunner.
  • Deterministic workflows: Flow skills traverse nodes from BEGIN to END, automatically routing based on LLM responses parsed through parse_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:

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 →