# How to Create and Use Custom Skills in Kimi Code: A Complete Guide

> Learn to create and use custom skills in Kimi Code. This guide shows you how to define reusable prompt templates for efficient coding workflows.

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

---

**Custom skills in Kimi Code are reusable Markdown-based prompt templates defined in [`.skill.md`](https://github.com/MoonshotAI/kimi-code/blob/main/.skill.md) files that you can invoke via slash commands or the Node SDK, stored in project-specific `skills/` directories or global user paths.**

The Kimi Code framework from MoonshotAI extends LLM capabilities through customizable skills—modular prompt logic that automates repetitive coding tasks. Understanding how to create and use custom skills in Kimi Code allows you to tailor the AI's behavior to your specific project workflows, from linting commands to code generation templates.

## What Are Skills in Kimi Code?

A **skill** is a reusable piece of prompting logic that the engine can invoke either manually by the user or automatically by the model. According to the source code in [[`packages/agent-core/src/skill/types.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/types.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/types.ts), each skill is defined by a structured interface:

```ts
export interface SkillDefinition {
  readonly name: string;               // "write-goal", "lint-code", etc.
  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, etc.)
  readonly source: SkillSource;        // project | user | extra | builtin
  readonly plugin?: SkillPluginContext; // If supplied by a plugin
}

```

The `content` field contains the actual prompt template, while `metadata` controls when and how the skill can be invoked.

## Where to Place Custom Skill Files

Kimi Code discovers skills from four distinct sources, defined in [[`packages/agent-core/src/skill/registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/registry.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/registry.ts):

| Source | Directory | Typical Path |
|--------|-----------|--------------|
| **Project** | `<repo-root>/skills` or paths in `extra_skill_dirs` config | [`skills/my-custom.skill.md`](https://github.com/MoonshotAI/kimi-code/blob/main/skills/my-custom.skill.md) |
| **User** | `~/.kimi-code/skills` or path set in `KIMI_CODE_USER_SKILLS` | `~/.kimi-code/skills/quick-fix.skill.md` |
| **Extra** | Directories passed via `extra_skill_dirs` config option | [`/opt/kimi/extra-skills/audit.skill.md`](https://github.com/MoonshotAI/kimi-code/blob/main//opt/kimi/extra-skills/audit.skill.md) |
| **Built-in** | `packages/agent-core/src/skill/builtin` | Provided by the engine itself |

**Tip:** Use the built-in skills in `packages/agent-core/src/skill/builtin/` as templates for your own definitions.

## Defining a Custom Skill (Markdown Format)

Each skill is a Markdown file with a YAML front-matter block. The [`SkillMetadata`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/types.ts) interface defines the available fields:

```markdown
---
name: run-linter
description: Execute ESLint on changed TypeScript files.
type: prompt          # "prompt" or "inline"

disableModelInvocation: false   # true makes it user-only

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

# Lint Task

Run the following command in the project root:

```bash
npx eslint {{changedFiles}}

```

Report any errors found.

```

**Key front-matter fields:**

- **`name`**: The identifier used in slash commands (`/run-linter`) and API calls. Must be unique.
- **`description`**: Displayed in the skill picker UI.
- **`type`**: Set to `prompt` (default) for user-invoked skills, or `inline` to allow automatic model invocation.
- **`disableModelInvocation`**: When `true`, the model will never auto-call this skill; only users can trigger it.
- **`whenToUse`**: Human-readable context hint shown in the available skills list.

## How Kimi Code Discovers Skills

When a session initializes, the **`SessionSkillRegistry.loadRoots()`** method in [[`registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/registry.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/registry.ts#L41-L58) receives a list of skill roots. It delegates discovery to the **skill scanner** (`discoverSkills` in [[`scanner.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/scanner.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/scanner.ts)), which:

1. Walks the configured directories recursively
2. Parses any `*.skill.md` or `*.md` files containing valid front-matter
3. Builds a `SkillDefinition` for each valid file
4. Indexes the skill by its normalized name using `normalizeSkillName`

```ts
// From registry.ts - indexing logic
for (const skill of skills) {
  this.byName.set(normalizeSkillName(skill.name), skill);
}

```

The registry also handles plugin-specific skills via `indexPluginSkill()`.

## Activating and Using Skills

### Using Slash Commands in the CLI

Type the forward-slash followed by the skill name and optional arguments:

```text
/run-linter src/**/*.ts

```

The TUI parses this as a **skill activation event** (defined in [[`packages/protocol/src/events.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/events.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/events.ts)), resolves the name against the registry, and injects the rendered prompt into the LLM turn.

### Programmatic Activation via Node SDK

Use the official SDK to activate skills within your Node.js applications:

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

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

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

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

```

The SDK sends requests to the **`/v1/sessions/{id}/skills/{skill_name}:activate`** REST endpoint, which emits a `skill.activated` event (see `skillActivatedEventSchema` in [[`events.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/events.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/protocol/src/events.ts#L1459-L1465)).

### From a Plugin (Advanced)

When defining skills within plugins, add an `instructions` field to your plugin manifest. During rendering, **`SessionSkillRegistry.renderSkillPrompt`** (lines 100-106 of [[`registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/registry.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/registry.ts#L100-L106)) wraps these instructions in a `<kimi-plugin-instructions>` XML block:

```xml
<kimi-plugin-instructions>
  {{plugin.instructions}}
</kimi-plugin-instructions>

```

The model receives this context alongside the skill's main prompt body.

## Parameter Expansion and Dynamic Content

Skills support dynamic parameter substitution using the `{{variable}}` syntax. When a skill activates, the engine calls **`expandSkillParameters`** in [[`packages/agent-core/src/skill/parser.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/parser.ts)](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/skill/parser.ts) to replace placeholders with runtime values (such as file paths or user arguments passed via the slash command).

## End-to-End Workflow Example

Follow this sequence to implement a custom skill:

1. **Create the file**: [`skills/security-audit.skill.md`](https://github.com/MoonshotAI/kimi-code/blob/main/skills/security-audit.skill.md) in your project root with valid front-matter and prompt content.
2. **Refresh the session**: Restart the server or create a new session to trigger `SessionSkillRegistry.loadRoots()`.
3. **Verify discovery**: Query the REST API or use the TUI to confirm the skill appears in the available list.
4. **Invoke**: Type `/security-audit --target=src/auth` or use the SDK activation method.
5. **Iterate**: Edit the Markdown file and repeat steps 2-4 to refine the behavior.

## Summary

- **Skills** are Markdown files with YAML front-matter defining reusable prompt templates, structured according to the `SkillDefinition` interface in [`types.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/types.ts).
- **Placement**: Store project-specific skills in `./skills/`, user-wide skills in `~/.kimi-code/skills/`, or system-wide via `extra_skill_dirs`.
- **Discovery**: The `SessionSkillRegistry` scans directories via `discoverSkills` and indexes them by normalized name.
- **Activation**: Use slash commands (`/skill-name`) or the Node SDK endpoint `/v1/sessions/{id}/skills/{name}:activate`.
- **Parameters**: Dynamic values use `{{variable}}` syntax processed by `expandSkillParameters` in [`parser.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/parser.ts).

## Frequently Asked Questions

### What file extension should I use for Kimi Code skills?

Use the [`.skill.md`](https://github.com/MoonshotAI/kimi-code/blob/main/.skill.md) extension for clarity, though the scanner also accepts any `.md` file containing valid front-matter with `name` and `description` fields. The parser validates the front-matter during the discovery phase in [`scanner.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/scanner.ts).

### Can I prevent the model from automatically invoking a skill?

Yes. Set `disableModelInvocation: true` in the front-matter. This restricts activation to explicit user commands only, preventing the LLM from auto-triggering the skill based on conversation context.

### How do I share skills across multiple projects?

Place skills in the **User** directory (`~/.kimi-code/skills/` or the path specified by `KIMI_CODE_USER_SKILLS`). Skills in this location are automatically available to all sessions for that user, regardless of which project is open.

### What is the difference between 'prompt' and 'inline' skill types?

The `type` field controls auto-invocation eligibility. **`prompt`** skills (default) are typically user-triggered via slash commands. **`inline`** skills can be automatically invoked by the model during conversation when the context matches the `whenToUse` description, unless `disableModelInvocation` is set to `true`.