# How to Create Custom Skills for Kimi Code CLI: A Complete Guide

> Learn to create custom skills for Kimi Code CLI. This guide explains reusable prompt templates in Markdown with YAML front-matter. Discover how to invoke them easily.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Custom skills in Kimi Code CLI are reusable prompt templates defined in Markdown files with YAML front-matter, discovered automatically from configured directories, and invoked via slash commands or the Node SDK.**

Kimi Code CLI treats skills as modular units of prompting logic that can be triggered manually by developers or automatically by the language model. Each skill consists of a Markdown file containing metadata headers and a template body that defines the actual instructions sent to the LLM. Learning how to create custom skills allows you to extend the CLI with project-specific workflows, coding standards, and automation routines tailored to your repository.

## Understanding the Skill Structure

According to the Kimi Code source code, a skill is formally defined by the `SkillDefinition` interface in **[`packages/agent-core/src/skill/types.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/types.ts)**. This structure encapsulates everything the engine needs to identify, register, and execute a skill.

```typescript
export interface SkillDefinition {
  readonly name: string;               // "write-goal", "lint-code", ...
  readonly description: string;        // Human-readable summary
  readonly path: string;               // Full path on disk
  readonly dir: string;                // Directory containing the file
  readonly content: string;            // Prompt template (the Markdown body)
  readonly metadata: SkillMetadata;    // Optional settings (type, whenToUse, ...)
  readonly source: SkillSource;        // project | user | extra | builtin
  readonly plugin?: SkillPluginContext; // If supplied by a plugin
}

```

The **name** field becomes the slash command identifier (e.g., `/my-custom`), while the **content** field contains the prompt template that handles parameter substitution when invoked.

## Skill Discovery and Registry

The `SessionSkillRegistry` class in **[`packages/agent-core/src/skill/registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/registry.ts)** orchestrates skill loading. When a session initializes, the `loadRoots()` method receives a list of *skill roots* (directories) and calls the scanner to discover files.

```typescript
// From registry.ts – loading roots and indexing
await this.discoverImpl({
  roots,
  onWarning: this.onWarning,
  onSkippedByPolicy: (skill) => this.skipped.push(skill),
  onDiscoveredSkill: (skill) => {
    this.indexPluginSkill(skill);
  },
});
for (const skill of skills) {
  this.byName.set(normalizeSkillName(skill.name), skill);
}

```

The scanner (in **[`packages/agent-core/src/skill/scanner.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/scanner.ts)**) walks these directories, parsing any `*.skill.md` or `*.md` files containing valid front-matter, and builds a `SkillDefinition` for each. The registry indexes these by normalized name and, if applicable, by plugin ID.

## Where to Place Your Custom Skills

Kimi Code supports four distinct skill sources, each with specific directory conventions:

| Source | Directory | Explanation |
|--------|-----------|-------------|
| **Project** | `<repo-root>/skills` or paths in `extra_skill_dirs` config | Visible only to the current project. |
| **User** | `~/.kimi-code/skills` or `$KIMI_CODE_USER_SKILLS` | Shared across all projects for the current user. |
| **Extra** | Directories passed via `extra_skill_dirs` config | Allows administrators to ship additional skill bundles. |
| **Built-in** | `packages/agent-core/src/skill/builtin` | Provided by the engine itself; use these as templates. |

Place your custom files in one of the first three locations depending on whether the skill should be project-specific or shared across your development environment.

## Writing a Custom Skill Markdown File

A skill file is a Markdown document with a YAML front-matter block followed by the prompt template body. The front-matter must include at least `name` and `description` fields.

```markdown
---
name: my-custom
description: Run a quick lint check on the changed files.
type: prompt          # "prompt" or "inline" → model can invoke automatically

disableModelInvocation: false   # `true` makes it user-only

whenToUse: "When the repo has new TypeScript files"
---

# Lint changed TypeScript files

Run the following command in the project root and capture its output:

```bash
npx eslint {{changedFiles}}

```

If the command exits with a non-zero code, report the errors back to the user.

```

**Key front-matter fields:**

- **name**: Identifier used in slash commands (`/my-custom`) and API calls.
- **description**: Shown in the skill picker UI.
- **type**: Set to `prompt` (default) or `inline`; only *inline* skills can be auto-invoked by the model.
- **disableModelInvocation**: When `true`, restricts the skill to manual invocation only.
- **whenToUse**: Human-readable hint displayed when listing available skills.

The body supports parameter substitution using `{{variable}}` syntax, processed by the parser in **[`packages/agent-core/src/skill/parser.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/parser.ts)**.

## Activating Custom Skills

### Via Slash Commands

In the TUI, type the slash command followed by optional arguments:

```

/my-custom src/**/*.ts

```

The `skill_activation` event (defined in **[`packages/protocol/src/events.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/events.ts)**) triggers the registry to resolve the name, expand parameters, and inject the prompt into the LLM turn.

### Via the Node SDK

You can programmatically activate skills using the `@moonshot-ai/kimi-code-sdk` package:

```typescript
import { KimiHarness } from '@moonshot-ai/kimi-code-sdk';

async function runSkill() {
  // 1. Create a session
  const harness = await KimiHarness.create({ /* config */ });
  const session = await harness.session('my-session-id');

  // 2. List available skills
  const { skills } = await session.get('/v1/sessions/my-session-id/skills');
  console.log('Available skills:', skills.map(s => s.name));

  // 3. Activate the skill with arguments
  await session.post(
    `/v1/sessions/my-session-id/skills/${encodeURIComponent('my-custom')}:activate`,
    { args: 'src/**/*.ts' }
  );
}

runSkill();

```

This POST request targets **`/v1/sessions/{id}/skills/{skill_name}:activate`**, which the server translates into a `skill.activated` event handled by `skillActivatedEventSchema` in **[`packages/protocol/src/events.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/events.ts)**.

### From Within a Plugin

If your skill belongs to a plugin, include an `instructions` field in the plugin manifest. When the skill is rendered (via `SessionSkillRegistry.renderSkillPrompt` in **[`registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/registry.ts)**), those instructions are wrapped in a `<kimi-plugin-instructions>` XML block (lines 100-106), providing context to the model.

## Complete Workflow Example

Follow this end-to-end process to create and test a custom skill:

1. **Create the file** at `~/.kimi-code/skills/quick-todo.skill.md`:

```markdown
---
name: quick-todo
description: Add a TODO comment to a file.
type: prompt
disableModelInvocation: true
---
Add the following comment to the top of {{file}}:

```ts
// TODO: {{comment}}

```

```

2. **Restart or refresh** your Kimi Code session to trigger `SessionSkillRegistry.loadRoots()` and discover the new skill.

3. **Verify registration** by listing skills via the SDK or checking the TUI skill picker.

4. **Invoke the skill** in the TUI with `/quick-todo src/app.ts|Refactor this function` (the pipe character separates arguments based on your template logic).

5. **Iterate** by modifying the Markdown content, adjusting front-matter metadata, and repeating steps 2-4.

## Summary

- **Skills are Markdown files** with YAML front-matter containing `name`, `description`, and optional behavior controls like `type` and `disableModelInvocation`.
- **Store skills** in `~/.kimi-code/skills` for user-wide access or `<repo>/skills` for project-specific workflows.
- **Discovery happens automatically** via `SessionSkillRegistry.loadRoots()` and the scanner in **[`packages/agent-core/src/skill/scanner.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/scanner.ts)**.
- **Activation works three ways**: slash commands in the TUI, REST API calls to the activation endpoint, or automatic model invocation (for `type: inline` skills).
- **Parameter expansion** uses `{{variable}}` syntax handled by the parser in **[`packages/agent-core/src/skill/parser.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/parser.ts)**.

## Frequently Asked Questions

### What file extension should I use for custom skills?

Use [`.skill.md`](https://github.com/MoonshotAI/kimi-code/blob/main/.skill.md) for explicit identification, or standard `.md` files containing valid YAML front-matter with `name` and `description` fields. The scanner in **[`packages/agent-core/src/skill/scanner.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/scanner.ts)** discovers both patterns during the `loadRoots()` initialization.

### How do I prevent the model from automatically invoking my skill?

Set `disableModelInvocation: true` in the front-matter block. This restricts the skill to manual activation only, preventing the LLM from calling it automatically during conversation turns.

### Can skills accept dynamic parameters when activated programmatically?

Yes. Pass an `args` string in the POST request body when calling the activation endpoint (`/v1/sessions/{id}/skills/{name}:activate`). The engine uses `expandSkillParameters` from **[`packages/agent-core/src/skill/parser.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/parser.ts)** to substitute `{{placeholders}}` in your template with the provided arguments.

### Where can I find reference examples of built-in skills?

Examine the files in **`packages/agent-core/src/skill/builtin/`**, such as [`write-goal.md`](https://github.com/MoonshotAI/kimi-code/blob/main/write-goal.md) or [`update-config.md`](https://github.com/MoonshotAI/kimi-code/blob/main/update-config.md). These are production-grade templates that demonstrate proper front-matter structure and prompt engineering patterns used by the Kimi Code engine itself.