Kimi-CLI Usage Examples: 4 Ways to Run and Extend the Moonshot AI Agent
Kimi-CLI provides four primary usage patterns: streaming JSON I/O for programmatic integration, custom tool plugins via Python scripts, runtime customization through the KimiCLI class, and deep extension by subclassing KimiSoul in the core loop.
The MoonshotAI/kimi-cli repository ships with a comprehensive examples/ directory demonstrating practical kimi-cli usage patterns. These implementations range from simple subprocess communication to advanced agent customization, enabling developers to embed the terminal AI agent into existing workflows or extend its capabilities with custom tools and modified execution loops.
Architecture Overview for Kimi-CLI Usage
Understanding the layered architecture helps clarify how the examples integrate with the system. The CLI entry point in src/kimi_cli/cli/__init__.py uses Typer to route sub-commands like kimi, kimi acp, and kimi mcp. The application layer in src/kimi_cli/app.py contains KimiCLI.create and KimiCLI.run, which load user configuration, select the LLM provider, and instantiate the agent. The core loop resides in src/kimi_cli/soul/kimisoul.py, managing context handling, LLM calls, and tool execution, while src/kimi_cli/soul/toolset.py handles tool registration. Wire protocol files in src/kimi_cli/wire/ manage serialization between the core and UI layers.
Streaming JSON I/O for Programmatic Control
The first usage pattern demonstrates how to drive Kimi-CLI as a subprocess using structured JSON streams. This approach in examples/kimi-cli-stream-json/main.py enables external applications to control the agent without importing the Python package directly.
# examples/kimi-cli-stream-json/main.py
import asyncio, json, os
KIMI_CLI_COMMAND = "uv run --project ../../ kimi"
async def main():
proc = await asyncio.create_subprocess_exec(
*KIMI_CLI_COMMAND.split(),
"--work-dir", os.getcwd(),
"--print",
"--input-format", "stream-json",
"--output-format", "stream-json",
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
)
user_message = {"role": "user", "content": "How many lines of code are there in the current working directory?"}
proc.stdin.write(json.dumps(user_message).encode() + b"\n")
await proc.stdin.drain()
while line := await proc.stdout.readline():
print("Received message:", json.loads(line))
if __name__ == "__main__":
asyncio.run(main())
This pattern uses --input-format stream-json and --output-format stream-json flags to establish bidirectional communication, making it ideal for integrating Kimi-CLI into IDE extensions or automated pipelines.
Building a Custom Tool Plugin
Tools in Kimi-CLI are Python scripts that read JSON parameters from STDIN and write results to STDOUT. The examples/sample-plugin/scripts/greet.py file demonstrates the minimal interface required:
# examples/sample-plugin/scripts/greet.py
import json, sys
GREETINGS = {"en": "Hello, {name}! Welcome!",
"zh": "你好,{name}!欢迎!",
"ja": "こんにちは、{name}さん!ようこそ!"}
params = json.loads(sys.stdin.read()) if not sys.stdin.isatty() else {}
name = params.get("name", "World")
lang = params.get("lang", "en")
print(GREETINGS.get(lang, GREETINGS["en"]).format(name=name))
When placed in a plugin directory and referenced in an agent specification (parsed by src/kimi_cli/agentspec.py), this script becomes available as a callable tool. The toolset module in src/kimi_cli/soul/toolset.py dynamically imports such scripts and wires them into the agent's execution context.
Launching from Python with Custom Agents
For deeper integration, examples/custom-tools/main.py shows how to instantiate Kimi-CLI directly within Python code, loading a custom YAML agent specification:
# examples/custom-tools/main.py
import asyncio
from pathlib import Path
from kaos.path import KaosPath
from kimi_cli.app import KimiCLI, enable_logging
from kimi_cli.session import Session
async def main():
enable_logging()
session = await Session.create(KaosPath.cwd())
myagent = Path(__file__).parent / "myagent.yaml"
instance = await KimiCLI.create(session, agent_file=myagent)
await instance.run_print(
input_format="text",
output_format="text",
command="What tools do you have?"
)
if __name__ == "__main__":
asyncio.run(main())
This approach leverages the Session management and KimiCLI factory methods defined in src/kimi_cli/app.py. Developers can specify custom agent files that extend base configurations located in src/kimi_cli/agents/.
Extending the Core Loop with KimiSoul
The most advanced usage pattern involves subclassing KimiSoul to modify the agent's core behavior. The examples/custom-kimi-soul/main.py example demonstrates intercepting tool calls:
# examples/custom-kimi-soul/main.py
import asyncio
from pathlib import Path
from kaos.path import KaosPath
from kimi_cli.soul.kimisoul import KimiSoul
from kimi_cli.session import Session
class MySoul(KimiSoul):
async def before_tool_call(self, tool_name, params):
print(f"[MySoul] About to call tool: {tool_name}")
return await super().before_tool_call(tool_name, params)
async def run():
session = await Session.create(KaosPath.cwd())
soul = await MySoul.create(session)
await soul.run_print(command="List the files in the current directory")
if __name__ == "__main__":
asyncio.run(run())
By overriding methods in src/kimi_cli/soul/kimisoul.py, developers can inject custom logic into the context compaction process, modify LLM invocation parameters, or implement custom tool execution hooks.
Key Implementation Files
src/kimi_cli/cli/__init__.py: Typer-based command-line interface routing sub-commands and flags.src/kimi_cli/app.py: ContainsKimiCLI.createand runtime initialization logic.src/kimi_cli/agentspec.py: Parses YAML agent specifications and resolves extension hierarchies.src/kimi_cli/soul/kimisoul.py: Core event loop implementing context management, LLM calls, and compaction.src/kimi_cli/soul/toolset.py: Registers built-in tools and loads external tool modules.src/kimi_cli/wire/protocol.py: Defines message schemas for JSON-RPC and stream-JSON formats.src/kimi_cli/mcp.py: Implements Model Context Protocol server capabilities for IDE integration.
Summary
- Streaming JSON I/O enables subprocess-based integration without Python dependencies, using flags in
src/kimi_cli/cli/__init__.pyto control input/output formats. - Custom tool plugins require only STDIN/STDOUT JSON handling, dynamically loaded by
src/kimi_cli/soul/toolset.py. - Python API usage through
KimiCLI.createinsrc/kimi_cli/app.pyallows custom agent specifications and programmatic control. - KimiSoul subclassing provides deep customization of the agent loop defined in
src/kimi_cli/soul/kimisoul.pyfor advanced use cases. - The Model Context Protocol implementation in
src/kimi_cli/mcp.pyenables standardized IDE integration.
Frequently Asked Questions
How do I run Kimi-CLI programmatically from Python?
You can launch Kimi-CLI as an async subprocess using the --input-format stream-json and --output-format stream-json flags, as demonstrated in examples/kimi-cli-stream-json/main.py. Alternatively, import KimiCLI from src/kimi_cli/app.py and call await KimiCLI.create(session) followed by run_print() for in-process execution.
Where is the core execution loop implemented in Kimi-CLI?
The core execution loop resides in src/kimi_cli/soul/kimisoul.py within the KimiSoul class. This module handles context management, LLM invocation, tool execution, and context compaction cycles. The loop consumes messages from the wire protocol and coordinates with src/kimi_cli/soul/toolset.py for tool dispatch.
Can I add custom tools to Kimi-CLI without modifying the source code?
Yes. Create a Python script that reads JSON from STDIN and writes to STDOUT, as shown in examples/sample-plugin/scripts/greet.py. Reference this script in a custom YAML agent specification, and src/kimi_cli/agentspec.py will resolve it through the extension mechanism without requiring changes to the core repository.
What is the Model Context Protocol (MCP) integration in Kimi-CLI?
The Model Context Protocol implementation in src/kimi_cli/mcp.py allows Kimi-CLI to function as an MCP server (via the kimi mcp sub-command) or client. This enables standardized communication with supported IDEs and external tools, using the wire protocol defined in src/kimi_cli/wire/protocol.py for message serialization.
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 →