Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/kimi_cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ class Config(BaseModel):
default="dark",
description="Terminal color theme. Use 'light' for light terminal backgrounds.",
)
prompt_text_color: str = Field(
default="",
description="Rich style for the user prompt text (e.g. 'dim', 'cyan').",
)
show_thinking_stream: bool = Field(
default=True,
description=(
Expand Down
6 changes: 6 additions & 0 deletions src/kimi_cli/ui/shell/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,12 @@ def __init__(
}
"""Shell-level slash commands + soul-level slash commands. Name to command mapping."""

# Sync user prompt color from runtime config so echo rendering picks it up.
if isinstance(soul, KimiSoul):
from kimi_cli.ui.theme import set_user_prompt_color

set_user_prompt_color(soul.runtime.config.prompt_text_color or None)

@property
def available_slash_commands(self) -> dict[str, SlashCommand[Any]]:
"""Get all available slash commands, including shell-level and soul-level commands."""
Expand Down
15 changes: 13 additions & 2 deletions src/kimi_cli/ui/shell/echo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@
from rich.text import Text

from kimi_cli.ui.shell.prompt import PROMPT_SYMBOL
from kimi_cli.ui.theme import get_user_prompt_color
from kimi_cli.utils.message import message_stringify


def render_user_echo(message: Message) -> Text:
"""Render a user message as literal shell transcript text."""
return Text(f"{PROMPT_SYMBOL} {message_stringify(message)}")
text_color = get_user_prompt_color()

text = Text()
text.append(f"{PROMPT_SYMBOL} ")
text.append(message_stringify(message), style=text_color or "")
return text


def render_user_echo_text(text: str) -> Text:
"""Render the local prompt text exactly as the user saw it in the buffer."""
return Text(f"{PROMPT_SYMBOL} {text}")
text_color = get_user_prompt_color()

result = Text()
result.append(f"{PROMPT_SYMBOL} ")
result.append(text, style=text_color or "")
return result
51 changes: 51 additions & 0 deletions src/kimi_cli/ui/shell/slash.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,57 @@ def theme(app: Shell, args: str):
raise Reload(session_id=soul.runtime.session.id)


@registry.command(name="prompt-color")
@shell_mode_registry.command(name="prompt-color")
def prompt_color(app: Shell, args: str):
"""Set custom color for user prompt text. Usage: /prompt-color [<style>|reset]"""
from rich.style import Style

from kimi_cli.ui.theme import get_user_prompt_color, set_user_prompt_color

soul = ensure_kimi_soul(app)
if soul is None:
return

raw = args.strip()
if not raw:
txt = get_user_prompt_color()
console.print(f"Text color: [bold]{txt or 'default'}[/bold]")
console.print("[grey50]Usage: /prompt-color <style> | /prompt-color reset[/grey50]")
return

if raw.lower() == "reset":
new_color = ""
else:
try:
Style.parse(raw)
except Exception:
console.print(f"[red]Invalid style: {raw}[/red]")
return
new_color = raw

config = soul.runtime.config
config_file = config.source_file
if config_file is None:
console.print(
"[yellow]Prompt color switching requires a config file; "
"restart without --config to persist this setting.[/yellow]"
)
return

try:
config_for_save = load_config(config_file)
config_for_save.prompt_text_color = new_color
save_config(config_for_save, config_file)
except (ConfigError, OSError) as exc:
console.print(f"[red]Failed to save config: {exc}[/red]")
return

config.prompt_text_color = new_color
set_user_prompt_color(config.prompt_text_color or None)
console.print("[green]Prompt color updated.[/green]")


@registry.command
def web(app: Shell, args: str):
"""Open Kimi Code Web UI in browser"""
Expand Down
18 changes: 18 additions & 0 deletions src/kimi_cli/ui/theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,21 @@ def get_toolbar_colors() -> ToolbarColors:

def get_mcp_prompt_colors() -> MCPPromptColors:
return _MCP_PROMPT_LIGHT if _active_theme == "light" else _MCP_PROMPT_DARK


# ---------------------------------------------------------------------------
# User prompt echo colors (overrides terminal default when set)
# ---------------------------------------------------------------------------

_prompt_text_color: str | None = None


def set_user_prompt_color(text: str | None) -> None:
"""Set custom color for user prompt echo rendering."""
global _prompt_text_color
_prompt_text_color = text


def get_user_prompt_color() -> str | None:
"""Return the active text color or None for terminal default."""
return _prompt_text_color
2 changes: 1 addition & 1 deletion tests/core/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_default_config_dump():
"default_plan_mode": False,
"default_editor": "",
"theme": "dark",
"show_thinking_stream": True,
"show_thinking_stream": True, "prompt_text_color": "",
"models": {},
"providers": {},
"loop_control": {
Expand Down