How Slash Commands Work in Kimi CLI at the Soul and Shell Levels
Kimi CLI routes user slash commands through a shared parser into two distinct registries—soul-level commands that manipulate the agent runtime in src/kimi_cli/soul/slash.py and shell-level commands that control the interactive UI in src/kimi_cli/ui/shell/slash.py—allowing both layers to expose a unified /command interface.
The MoonshotAI/kimi-cli repository implements a dual-layer slash command architecture that separates agent runtime logic from terminal UI interactions. When a user types a command beginning with /, the system handles it through shared parsing utilities but dispatches to one of two specialized registries depending on whether the operation affects the core agent or the shell interface. Understanding how slash commands work in Kimi CLI reveals a clean boundary between the conversational engine and the user-facing terminal.
Shared Parsing Foundation in utils/slashcmd.py
All slash commands, regardless of layer, pass through the same low-level parser in src/kimi_cli/utils/slashcmd.py. The parse_slash_command_call function extracts the command name and raw arguments using a strict regular expression.
# src/kimi_cli/utils/slashcmd.py
def parse_slash_command_call(user_input: str) -> SlashCommandCall | None:
...
name_match = re.match(r"^\/([a-zA-Z0-9_-]+(?::[a-zA-Z0-9_-]+)*)", user_input)
...
return SlashCommandCall(name=command_name, args=raw_args, raw_input=user_input)
The parser returns None if the input does not match the slash command pattern, causing the UI to treat the line as ordinary chat text. When parsing succeeds, the resulting SlashCommandCall object carries the command name, raw argument string, and original input for downstream dispatch.
Soul-Level Slash Commands in Kimi CLI
Soul-level commands operate on the core agent runtime. Defined in src/kimi_cli/soul/slash.py, these handlers receive a KimiSoul instance and directly manipulate context, planning state, and session data.
The Soul Registry
The soul layer instantiates a dedicated registry for typed command functions:
# src/kimi_cli/soul/slash.py (lines 34-35)
registry = SlashCommandRegistry[SoulSlashCmdFunc]()
Developers register commands with the @registry.command decorator. Each decorated function accepts soul: KimiSoul and args: str:
@registry.command
async def clear(soul: KimiSoul, args: str):
"""Clear the context"""
...
Runtime Control Examples
/clearwipes the conversation context and rewrites the system prompt. The implementation lives insrc/kimi_cli/soul/slash.pyaround lines 80-86./plan onenables plan mode, writes a persistentplan.mdfile, and disables tool calls. This is implemented around lines 60-99 of the same file.
These commands never concern themselves with terminal rendering. They modify the agent's internal state and rely on the soul's event system to propagate changes.
Shell-Level Slash Commands in Kimi CLI
Shell-level commands manage the interactive UI experience. Located in src/kimi_cli/ui/shell/slash.py, they interact with the terminal, launch editors, and handle model selection.
Dual Registry System
The shell maintains two registries to support both normal and agent-shell modes:
# src/kimi_cli/ui/shell/slash.py (lines 35-36)
registry = SlashCommandRegistry[ShellSlashCmdFunc]()
shell_mode_registry = SlashCommandRegistry[ShellSlashCmdFunc]()
Commands available in every mode attach to registry, while commands needed only when the UI acts as a raw shell attach to shell_mode_registry. Some commands, such as version, register to both:
@registry.command
@shell_mode_registry.command
def version(app: Shell, args: str):
"""Show version information"""
...
Handlers at this layer receive app: Shell and perform console I/O or external process launches. They do not mutate the agent runtime directly.
UI-Focused Operations
Notable shell-level slash commands in Kimi CLI include:
/modelopens an interactive selector to switch the LLM model and thinking mode, implemented insrc/kimi_cli/ui/shell/slash.pyaround lines 84-129./helprenders a rich help screen with shortcuts and skill listings, found around lines 91-119./newstarts a fresh session by calling_do_new_session, defined around lines 64-68. It acts as a shell alias for clearing state./btwsends a side-question without interrupting the main conversation. This shell command requires soul cooperation and is implemented around lines 60-73.
Execution Flow from Input to Handler
The dispatch pipeline follows a strict precedence that prioritizes shell-level UI actions before forwarding to the soul agent.
- User input enters the UI loop managed in
src/kimi_cli/ui/shell/__init__.py. The input string is passed toparse_slash_command_call. - At the parsing gate, if the parser returns
None, the text is submitted as normal chat. Otherwise, aSlashCommandCallproceeds to registry lookup. - The shell queries
registry.find_command(name)andshell_mode_registryif applicable. If a match exists, the shell invokes the handler with the currentShellinstance. - When the shell cannot resolve the command, or when the command is explicitly intended for the runtime layer, the input reaches
KimiSoul.runinsrc/kimi_cli/soul/kimisoul.py. The soul repeats the lookup against its ownregistry. - The matched soul handler receives the
KimiSoulinstance and may updateContext, emit messages viawire_send, or write session state. Shell handlers may redraw the terminal or spawn subprocesses.
This ordered resolution ensures UI concerns like /help or /model never pollute the agent's reasoning loop, while still allowing the shell to surface agent operations such as /clear when appropriate.
Summary
- Kimi CLI slash commands share a unified parser in
src/kimi_cli/utils/slashcmd.pythat produces aSlashCommandCallobject. - Soul-level commands live in
src/kimi_cli/soul/slash.pyand affect the agent runtime through aSlashCommandRegistry[SoulSlashCmdFunc]. - Shell-level commands live in
src/kimi_cli/ui/shell/slash.pyand manage the terminal UI through one or both ofregistryandshell_mode_registry. - The execution flow checks the shell registry first, then falls back to the soul registry, maintaining a clean separation between interface logic and core agent behavior.
Frequently Asked Questions
What is the difference between soul and shell slash commands in Kimi CLI?
Soul-level commands manipulate the core agent runtime, such as clearing conversation context or toggling plan mode, and are defined in src/kimi_cli/soul/slash.py. Shell-level commands control the interactive terminal experience, such as displaying help or switching models, and are defined in src/kimi_cli/ui/shell/slash.py. The soul registry receives KimiSoul instances, while the shell registry receives Shell instances.
How does Kimi CLI parse a slash command from user input?
All slash commands are parsed by parse_slash_command_call in src/kimi_cli/utils/slashcmd.py. This function applies a regex starting with / followed by alphanumeric names and optional colon-namespaced segments. It returns a SlashCommandCall containing the command name, raw arguments, and original input string. If parsing fails, the line is treated as normal chat text.
Can a shell-level command modify the agent's internal state?
Shell-level commands do not mutate the agent runtime directly. However, commands like /new trigger UI-side routines that may start a fresh session, and /btw sends side-questions by interacting with the soul layer. Direct context changes remain the responsibility of soul-level handlers.
What happens if a command is not found in either registry?
If the parser identifies a slash command but neither the shell nor the soul registry contains a matching handler, the input does not enter the chat context as a user message. Instead, the system typically notifies the user that the command is unknown. The unified parsing layer guarantees that malformed or unrecognized commands are handled distinctly from ordinary conversational text.
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 →