How to Create and Use Custom Skills in Kimi Code: A Complete Guide
Custom skills in Kimi Code are reusable Markdown-based prompt templates defined in .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), each skill is defined by a structured interface:
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):
| Source | Directory | Typical Path |
|---|---|---|
| Project | <repo-root>/skills or paths in extra_skill_dirs config |
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 |
| 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 interface defines the available fields:
---
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:
/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)), 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:
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/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/packages/agent-core/src/skill/registry.ts#L100-L106)) wraps these instructions in a <kimi-plugin-instructions> XML block:
<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) 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:
- Create the file:
skills/security-audit.skill.mdin your project root with valid front-matter and prompt content. - Refresh the session: Restart the server or create a new session to trigger
SessionSkillRegistry.loadRoots(). - Verify discovery: Query the REST API or use the TUI to confirm the skill appears in the available list.
- Invoke: Type
/security-audit --target=src/author use the SDK activation method. - 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
SkillDefinitioninterface intypes.ts. - Placement: Store project-specific skills in
./skills/, user-wide skills in~/.kimi-code/skills/, or system-wide viaextra_skill_dirs. - Discovery: The
SessionSkillRegistryscans directories viadiscoverSkillsand 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 byexpandSkillParametersinparser.ts.
Frequently Asked Questions
What file extension should I use for Kimi Code skills?
Use the .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.
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.
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 →