klaude-code 2.1.1__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- klaude_code/app/__init__.py +1 -2
- klaude_code/app/runtime.py +13 -41
- klaude_code/cli/list_model.py +27 -10
- klaude_code/cli/main.py +42 -159
- klaude_code/config/assets/builtin_config.yaml +36 -14
- klaude_code/config/config.py +144 -7
- klaude_code/config/select_model.py +38 -13
- klaude_code/config/sub_agent_model_helper.py +217 -0
- klaude_code/const.py +2 -2
- klaude_code/core/agent_profile.py +71 -5
- klaude_code/core/executor.py +75 -0
- klaude_code/core/manager/llm_clients_builder.py +18 -12
- klaude_code/core/prompts/prompt-nano-banana.md +1 -0
- klaude_code/core/tool/shell/command_safety.py +4 -189
- klaude_code/core/tool/sub_agent_tool.py +2 -1
- klaude_code/core/turn.py +1 -1
- klaude_code/llm/anthropic/client.py +8 -5
- klaude_code/llm/anthropic/input.py +54 -29
- klaude_code/llm/google/client.py +2 -2
- klaude_code/llm/google/input.py +23 -2
- klaude_code/llm/openai_compatible/input.py +22 -13
- klaude_code/llm/openai_compatible/stream.py +1 -1
- klaude_code/llm/openrouter/input.py +37 -25
- klaude_code/llm/responses/client.py +1 -1
- klaude_code/llm/responses/input.py +96 -57
- klaude_code/protocol/commands.py +1 -2
- klaude_code/protocol/events/system.py +4 -0
- klaude_code/protocol/message.py +2 -2
- klaude_code/protocol/op.py +17 -0
- klaude_code/protocol/op_handler.py +5 -0
- klaude_code/protocol/sub_agent/AGENTS.md +28 -0
- klaude_code/protocol/sub_agent/__init__.py +10 -14
- klaude_code/protocol/sub_agent/image_gen.py +2 -1
- klaude_code/session/codec.py +2 -6
- klaude_code/session/session.py +9 -1
- klaude_code/skill/assets/create-plan/SKILL.md +3 -5
- klaude_code/tui/command/__init__.py +7 -10
- klaude_code/tui/command/clear_cmd.py +1 -1
- klaude_code/tui/command/command_abc.py +1 -2
- klaude_code/tui/command/copy_cmd.py +1 -2
- klaude_code/tui/command/fork_session_cmd.py +4 -4
- klaude_code/tui/command/model_cmd.py +6 -43
- klaude_code/tui/command/model_select.py +75 -15
- klaude_code/tui/command/refresh_cmd.py +1 -2
- klaude_code/tui/command/resume_cmd.py +3 -4
- klaude_code/tui/command/status_cmd.py +1 -1
- klaude_code/tui/command/sub_agent_model_cmd.py +190 -0
- klaude_code/tui/components/bash_syntax.py +1 -1
- klaude_code/tui/components/common.py +1 -1
- klaude_code/tui/components/developer.py +10 -15
- klaude_code/tui/components/metadata.py +2 -64
- klaude_code/tui/components/rich/cjk_wrap.py +3 -2
- klaude_code/tui/components/rich/status.py +49 -3
- klaude_code/tui/components/rich/theme.py +4 -2
- klaude_code/tui/components/sub_agent.py +25 -46
- klaude_code/tui/components/user_input.py +9 -21
- klaude_code/tui/components/welcome.py +99 -0
- klaude_code/tui/input/prompt_toolkit.py +14 -1
- klaude_code/tui/renderer.py +2 -3
- klaude_code/tui/runner.py +2 -2
- klaude_code/tui/terminal/selector.py +8 -18
- klaude_code/ui/__init__.py +0 -24
- klaude_code/ui/common.py +3 -2
- klaude_code/ui/core/display.py +2 -2
- {klaude_code-2.1.1.dist-info → klaude_code-2.3.0.dist-info}/METADATA +16 -81
- {klaude_code-2.1.1.dist-info → klaude_code-2.3.0.dist-info}/RECORD +68 -67
- klaude_code/tui/command/help_cmd.py +0 -51
- klaude_code/tui/command/prompt-commit.md +0 -82
- klaude_code/tui/command/release_notes_cmd.py +0 -85
- klaude_code/ui/exec_mode.py +0 -60
- {klaude_code-2.1.1.dist-info → klaude_code-2.3.0.dist-info}/WHEEL +0 -0
- {klaude_code-2.1.1.dist-info → klaude_code-2.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
from rich.console import Group, RenderableType
|
|
4
|
+
from rich.text import Text
|
|
5
|
+
|
|
6
|
+
from klaude_code.log import is_debug_enabled
|
|
7
|
+
from klaude_code.protocol import events
|
|
8
|
+
from klaude_code.tui.components.rich.quote import Quote
|
|
9
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
10
|
+
from klaude_code.ui.common import format_model_params
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_version() -> str:
|
|
14
|
+
"""Get the current version of klaude-code."""
|
|
15
|
+
try:
|
|
16
|
+
return version("klaude-code")
|
|
17
|
+
except PackageNotFoundError:
|
|
18
|
+
return "unknown"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def render_welcome(e: events.WelcomeEvent) -> RenderableType:
|
|
22
|
+
"""Render the welcome panel with model info and settings.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
e: The welcome event.
|
|
26
|
+
"""
|
|
27
|
+
debug_mode = is_debug_enabled()
|
|
28
|
+
|
|
29
|
+
panel_content = Text()
|
|
30
|
+
|
|
31
|
+
if e.show_klaude_code_info:
|
|
32
|
+
# First line: Klaude Code version
|
|
33
|
+
klaude_code_style = ThemeKey.WELCOME_DEBUG_TITLE if debug_mode else ThemeKey.WELCOME_HIGHLIGHT_BOLD
|
|
34
|
+
panel_content.append_text(Text("Klaude Code", style=klaude_code_style))
|
|
35
|
+
panel_content.append_text(Text(f" v{_get_version()}", style=ThemeKey.WELCOME_INFO))
|
|
36
|
+
panel_content.append_text(Text("\n"))
|
|
37
|
+
|
|
38
|
+
# Model line: model @ provider · params...
|
|
39
|
+
panel_content.append_text(
|
|
40
|
+
Text.assemble(
|
|
41
|
+
(str(e.llm_config.model), ThemeKey.WELCOME_HIGHLIGHT),
|
|
42
|
+
(" @ ", ThemeKey.WELCOME_INFO),
|
|
43
|
+
(e.llm_config.provider_name, ThemeKey.WELCOME_INFO),
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Use format_model_params for consistent formatting
|
|
48
|
+
param_strings = format_model_params(e.llm_config)
|
|
49
|
+
|
|
50
|
+
# Check if we have sub-agent models to show
|
|
51
|
+
has_sub_agents = e.show_sub_agent_models and e.sub_agent_models
|
|
52
|
+
|
|
53
|
+
# Render config items with tree-style prefixes
|
|
54
|
+
for i, param_str in enumerate(param_strings):
|
|
55
|
+
is_last = i == len(param_strings) - 1 and not has_sub_agents
|
|
56
|
+
prefix = "└─ " if is_last else "├─ "
|
|
57
|
+
panel_content.append_text(
|
|
58
|
+
Text.assemble(
|
|
59
|
+
("\n", ThemeKey.WELCOME_INFO),
|
|
60
|
+
(prefix, ThemeKey.LINES),
|
|
61
|
+
(param_str, ThemeKey.WELCOME_INFO),
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Render sub-agent models
|
|
66
|
+
if has_sub_agents:
|
|
67
|
+
# Add sub-agents header with tree prefix
|
|
68
|
+
panel_content.append_text(
|
|
69
|
+
Text.assemble(
|
|
70
|
+
("\n", ThemeKey.WELCOME_INFO),
|
|
71
|
+
("└─ ", ThemeKey.LINES),
|
|
72
|
+
("sub-agents:", ThemeKey.WELCOME_INFO),
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
sub_agent_items = list(e.sub_agent_models.items())
|
|
76
|
+
max_type_len = max(len(t) for t in e.sub_agent_models)
|
|
77
|
+
for i, (sub_agent_type, sub_llm_config) in enumerate(sub_agent_items):
|
|
78
|
+
is_last = i == len(sub_agent_items) - 1
|
|
79
|
+
prefix = "└─ " if is_last else "├─ "
|
|
80
|
+
panel_content.append_text(
|
|
81
|
+
Text.assemble(
|
|
82
|
+
("\n", ThemeKey.WELCOME_INFO),
|
|
83
|
+
(" ", ThemeKey.WELCOME_INFO), # Indentation for sub-items
|
|
84
|
+
(prefix, ThemeKey.LINES),
|
|
85
|
+
(sub_agent_type.lower().ljust(max_type_len), ThemeKey.WELCOME_INFO),
|
|
86
|
+
(": ", ThemeKey.LINES),
|
|
87
|
+
(str(sub_llm_config.model), ThemeKey.WELCOME_HIGHLIGHT),
|
|
88
|
+
(" @ ", ThemeKey.WELCOME_INFO),
|
|
89
|
+
(sub_llm_config.provider_name, ThemeKey.WELCOME_INFO),
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
border_style = ThemeKey.WELCOME_DEBUG_BORDER if debug_mode else ThemeKey.LINES
|
|
94
|
+
|
|
95
|
+
if e.show_klaude_code_info:
|
|
96
|
+
groups = ["", Quote(panel_content, style=border_style, prefix="▌ "), ""]
|
|
97
|
+
else:
|
|
98
|
+
groups = [Quote(panel_content, style=border_style, prefix="▌ "), ""]
|
|
99
|
+
return Group(*groups)
|
|
@@ -455,7 +455,7 @@ class PromptToolkitInput(InputProviderABC):
|
|
|
455
455
|
config = load_config()
|
|
456
456
|
models: list[ModelEntry] = sorted(
|
|
457
457
|
config.iter_model_entries(only_available=True),
|
|
458
|
-
key=lambda m: m.model_name.lower(),
|
|
458
|
+
key=lambda m: (m.model_name.lower(), m.provider.lower()),
|
|
459
459
|
)
|
|
460
460
|
if not models:
|
|
461
461
|
return [], None
|
|
@@ -468,6 +468,15 @@ class PromptToolkitInput(InputProviderABC):
|
|
|
468
468
|
initial = self._get_current_model_config_name()
|
|
469
469
|
if initial is None:
|
|
470
470
|
initial = config.main_model
|
|
471
|
+
if isinstance(initial, str) and initial and "@" not in initial:
|
|
472
|
+
try:
|
|
473
|
+
resolved = config.resolve_model_location_prefer_available(initial) or config.resolve_model_location(
|
|
474
|
+
initial
|
|
475
|
+
)
|
|
476
|
+
except ValueError:
|
|
477
|
+
resolved = None
|
|
478
|
+
if resolved is not None:
|
|
479
|
+
initial = f"{resolved[0]}@{resolved[1]}"
|
|
471
480
|
return items, initial
|
|
472
481
|
|
|
473
482
|
def _open_model_picker(self) -> None:
|
|
@@ -608,6 +617,10 @@ class PromptToolkitInput(InputProviderABC):
|
|
|
608
617
|
(symbol_style, " ctrl-t "),
|
|
609
618
|
(text_style, " "),
|
|
610
619
|
(text_style, "think"),
|
|
620
|
+
(text_style, " "),
|
|
621
|
+
(symbol_style, " ctrl-v "),
|
|
622
|
+
(text_style, " "),
|
|
623
|
+
(text_style, "paste image"),
|
|
611
624
|
]
|
|
612
625
|
)
|
|
613
626
|
|
klaude_code/tui/renderer.py
CHANGED
|
@@ -61,6 +61,7 @@ from klaude_code.tui.components import sub_agent as c_sub_agent
|
|
|
61
61
|
from klaude_code.tui.components import thinking as c_thinking
|
|
62
62
|
from klaude_code.tui.components import tools as c_tools
|
|
63
63
|
from klaude_code.tui.components import user_input as c_user_input
|
|
64
|
+
from klaude_code.tui.components import welcome as c_welcome
|
|
64
65
|
from klaude_code.tui.components.common import truncate_head, truncate_middle
|
|
65
66
|
from klaude_code.tui.components.rich import status as r_status
|
|
66
67
|
from klaude_code.tui.components.rich.live import CropAboveLive, SingleLine
|
|
@@ -511,7 +512,7 @@ class TUICommandRenderer:
|
|
|
511
512
|
self.print()
|
|
512
513
|
|
|
513
514
|
def display_welcome(self, event: events.WelcomeEvent) -> None:
|
|
514
|
-
self.print(
|
|
515
|
+
self.print(c_welcome.render_welcome(event))
|
|
515
516
|
|
|
516
517
|
def display_user_message(self, event: events.UserMessageEvent) -> None:
|
|
517
518
|
self.print(c_user_input.render_user_input(event.content))
|
|
@@ -567,10 +568,8 @@ class TUICommandRenderer:
|
|
|
567
568
|
self.print(
|
|
568
569
|
c_sub_agent.render_sub_agent_result(
|
|
569
570
|
event.task_result,
|
|
570
|
-
code_theme=self.themes.code_theme,
|
|
571
571
|
has_structured_output=event.has_structured_output,
|
|
572
572
|
description=description,
|
|
573
|
-
style=ThemeKey.TOOL_RESULT,
|
|
574
573
|
)
|
|
575
574
|
)
|
|
576
575
|
|
klaude_code/tui/runner.py
CHANGED
|
@@ -77,12 +77,12 @@ async def submit_user_input_payload(
|
|
|
77
77
|
raise ValueError("Multiple RunAgentOperation results are not supported")
|
|
78
78
|
|
|
79
79
|
for run_op in run_ops:
|
|
80
|
-
run_op.persist_user_input = cmd_result.
|
|
80
|
+
run_op.persist_user_input = cmd_result.persist
|
|
81
81
|
run_op.emit_user_message_event = False
|
|
82
82
|
|
|
83
83
|
if cmd_result.events:
|
|
84
84
|
for evt in cmd_result.events:
|
|
85
|
-
if cmd_result.
|
|
85
|
+
if cmd_result.persist and isinstance(evt, events.DeveloperMessageEvent):
|
|
86
86
|
agent.session.append_history([evt.item])
|
|
87
87
|
await executor.context.emit_event(evt)
|
|
88
88
|
|
|
@@ -19,6 +19,8 @@ from prompt_toolkit.layout.containers import Container, ScrollOffsets
|
|
|
19
19
|
from prompt_toolkit.layout.controls import BufferControl, FormattedTextControl
|
|
20
20
|
from prompt_toolkit.styles import Style, merge_styles
|
|
21
21
|
|
|
22
|
+
from klaude_code.ui.common import format_model_params
|
|
23
|
+
|
|
22
24
|
|
|
23
25
|
@dataclass(frozen=True, slots=True)
|
|
24
26
|
class SelectItem[T]:
|
|
@@ -49,26 +51,14 @@ def build_model_select_items(models: list[Any]) -> list[SelectItem[str]]:
|
|
|
49
51
|
max_model_name_length = max(len(m.model_name) for m in models)
|
|
50
52
|
num_width = len(str(len(models)))
|
|
51
53
|
|
|
52
|
-
def _thinking_info(m: Any) -> str:
|
|
53
|
-
thinking = m.model_params.thinking
|
|
54
|
-
if not thinking:
|
|
55
|
-
return ""
|
|
56
|
-
if thinking.reasoning_effort:
|
|
57
|
-
return f"reasoning {thinking.reasoning_effort}"
|
|
58
|
-
if thinking.budget_tokens:
|
|
59
|
-
return f"thinking budget {thinking.budget_tokens}"
|
|
60
|
-
return "thinking (configured)"
|
|
61
|
-
|
|
62
54
|
items: list[SelectItem[str]] = []
|
|
63
55
|
for idx, m in enumerate(models, 1):
|
|
64
56
|
model_id = m.model_params.model or "N/A"
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
# Display the base model name only; provider stays in the meta section.
|
|
58
|
+
display_name = m.model_name
|
|
59
|
+
first_line_prefix = f"{display_name:<{max_model_name_length}} → "
|
|
67
60
|
meta_parts: list[str] = [m.provider]
|
|
68
|
-
|
|
69
|
-
meta_parts.append(thinking_info)
|
|
70
|
-
if m.model_params.verbosity:
|
|
71
|
-
meta_parts.append(f"verbosity {m.model_params.verbosity}")
|
|
61
|
+
meta_parts.extend(format_model_params(m.model_params))
|
|
72
62
|
meta_str = " · ".join(meta_parts)
|
|
73
63
|
title = [
|
|
74
64
|
("class:meta", f"{idx:>{num_width}}. "),
|
|
@@ -76,8 +66,8 @@ def build_model_select_items(models: list[Any]) -> list[SelectItem[str]]:
|
|
|
76
66
|
("class:msg bold", model_id),
|
|
77
67
|
("class:meta", f" {meta_str}\n"),
|
|
78
68
|
]
|
|
79
|
-
search_text = f"{m.model_name} {model_id} {m.provider}"
|
|
80
|
-
items.append(SelectItem(title=title, value=m.
|
|
69
|
+
search_text = f"{m.selector} {m.model_name} {model_id} {m.provider}"
|
|
70
|
+
items.append(SelectItem(title=title, value=m.selector, search_text=search_text))
|
|
81
71
|
|
|
82
72
|
return items
|
|
83
73
|
|
klaude_code/ui/__init__.py
CHANGED
|
@@ -10,33 +10,9 @@ Terminal (Rich/prompt-toolkit) UI lives in `klaude_code.tui`.
|
|
|
10
10
|
from .core.display import DisplayABC
|
|
11
11
|
from .core.input import InputProviderABC
|
|
12
12
|
from .debug_mode import DebugEventDisplay
|
|
13
|
-
from .exec_mode import ExecDisplay, StreamJsonDisplay
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def create_exec_display(debug: bool = False, stream_json: bool = False) -> DisplayABC:
|
|
17
|
-
"""
|
|
18
|
-
Create a display for exec (non-interactive) mode.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
debug: If True, wrap the display with DebugEventDisplay to log all events.
|
|
22
|
-
stream_json: If True, stream all events as JSON lines instead of normal output.
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
A DisplayABC implementation that only outputs task results.
|
|
26
|
-
"""
|
|
27
|
-
if stream_json:
|
|
28
|
-
return StreamJsonDisplay()
|
|
29
|
-
exec_display = ExecDisplay()
|
|
30
|
-
if debug:
|
|
31
|
-
return DebugEventDisplay(exec_display)
|
|
32
|
-
return exec_display
|
|
33
|
-
|
|
34
13
|
|
|
35
14
|
__all__ = [
|
|
36
15
|
"DebugEventDisplay",
|
|
37
16
|
"DisplayABC",
|
|
38
|
-
"ExecDisplay",
|
|
39
17
|
"InputProviderABC",
|
|
40
|
-
"StreamJsonDisplay",
|
|
41
|
-
"create_exec_display",
|
|
42
18
|
]
|
klaude_code/ui/common.py
CHANGED
|
@@ -101,6 +101,7 @@ def format_model_params(model_params: "LLMConfigModelParameter") -> list[str]:
|
|
|
101
101
|
- "reasoning medium"
|
|
102
102
|
- "thinking budget 10000"
|
|
103
103
|
- "verbosity 2"
|
|
104
|
+
- "image generation"
|
|
104
105
|
- "provider-routing: {…}"
|
|
105
106
|
"""
|
|
106
107
|
parts: list[str] = []
|
|
@@ -119,8 +120,8 @@ def format_model_params(model_params: "LLMConfigModelParameter") -> list[str]:
|
|
|
119
120
|
if model_params.provider_routing:
|
|
120
121
|
parts.append(f"provider routing {_format_provider_routing(model_params.provider_routing)}")
|
|
121
122
|
|
|
122
|
-
if model_params.modalities:
|
|
123
|
-
parts.append(
|
|
123
|
+
if model_params.modalities and any(m.casefold() == "image" for m in model_params.modalities):
|
|
124
|
+
parts.append("image generation")
|
|
124
125
|
|
|
125
126
|
if model_params.image_config:
|
|
126
127
|
if model_params.image_config.aspect_ratio:
|
klaude_code/ui/core/display.py
CHANGED
|
@@ -10,8 +10,8 @@ class DisplayABC(ABC):
|
|
|
10
10
|
Abstract base class for UI display implementations.
|
|
11
11
|
|
|
12
12
|
A Display is responsible for rendering events from the executor to the user.
|
|
13
|
-
Implementations can range from
|
|
14
|
-
|
|
13
|
+
Implementations can range from minimal text output to rich interactive
|
|
14
|
+
terminals (TUIDisplay) or debugging wrappers (DebugEventDisplay).
|
|
15
15
|
|
|
16
16
|
Lifecycle:
|
|
17
17
|
1. start() is called once before any events are consumed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: klaude-code
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Minimal code agent CLI
|
|
5
5
|
Requires-Dist: anthropic>=0.66.0
|
|
6
6
|
Requires-Dist: chardet>=5.2.0
|
|
@@ -25,21 +25,19 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
Minimal code agent CLI.
|
|
26
26
|
|
|
27
27
|
## Features
|
|
28
|
-
- **Multi-provider**: Anthropic, OpenAI Responses API, OpenRouter
|
|
28
|
+
- **Multi-provider**: Anthropic Message API, OpenAI Responses API, OpenRouter, Claude Max OAuth and ChatGPT Codex OAuth etc.
|
|
29
29
|
- **Keep reasoning item in context**: Interleaved thinking support
|
|
30
|
-
- **Model-aware tools**: Claude Code
|
|
31
|
-
- **
|
|
30
|
+
- **Model-aware tools**: Claude Code tool set for Opus, `apply_patch` for GPT-5/Codex
|
|
31
|
+
- **Reminders**: Cooldown-based todo tracking, instruction reinforcement and external file change reminder
|
|
32
|
+
- **Sub-agents**: Task, Explore, Web, ImageGen
|
|
33
|
+
- **Structured sub-agent output**: Main agent defines JSON schema and get schema-compliant responses via constrained decoding
|
|
32
34
|
- **Recursive `@file` mentions**: Circular dependency protection, relative path resolution
|
|
33
|
-
- **Reminders**: Cooldown-based todo tracking and instruction reinforcement
|
|
34
35
|
- **External file sync**: Monitoring for external edits (linter, manual)
|
|
35
36
|
- **Interrupt handling**: Ctrl+C preserves partial responses and synthesizes tool cancellation results
|
|
36
37
|
- **Output truncation**: Large outputs saved to file system with snapshot links
|
|
37
|
-
- **Skills**: Built-in + user + project Agent Skills (with implicit invocation by Skill tool or explicit invocation by typing `$`)
|
|
38
|
+
- **Agent Skills**: Built-in + user + project Agent Skills (with implicit invocation by Skill tool or explicit invocation by typing `$`)
|
|
38
39
|
- **Sessions**: Resumable with `--continue`
|
|
39
|
-
- **
|
|
40
|
-
- **Version update check**: Background PyPI version check with upgrade prompts
|
|
41
|
-
- **Terminal title**: Shows current directory and model name
|
|
42
|
-
- **Mermaid diagrams**: Interactive local HTML viewer with zoom, pan, and SVG export
|
|
40
|
+
- **Mermaid diagrams**: Terminal image preview and Interactive local HTML viewer with zoom, pan, and SVG export
|
|
43
41
|
- **Extras**: Slash commands, sub-agents, image paste, terminal notifications, auto-theming
|
|
44
42
|
|
|
45
43
|
## Installation
|
|
@@ -59,32 +57,23 @@ Or use the built-in alias command:
|
|
|
59
57
|
```bash
|
|
60
58
|
klaude update
|
|
61
59
|
klaude upgrade
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
To show version:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
60
|
klaude --version
|
|
68
|
-
|
|
69
|
-
klaude version
|
|
61
|
+
|
|
70
62
|
```
|
|
71
63
|
|
|
72
64
|
## Usage
|
|
73
65
|
|
|
74
|
-
### Interactive Mode
|
|
75
|
-
|
|
76
66
|
```bash
|
|
77
67
|
klaude [--model <name>] [--select-model]
|
|
78
68
|
```
|
|
79
69
|
|
|
80
70
|
**Options:**
|
|
81
|
-
- `--version`/`-V`/`-v`: Show version and exit.
|
|
82
71
|
- `--model`/`-m`: Preferred model name (exact match picks immediately; otherwise opens the interactive selector filtered by this value).
|
|
83
72
|
- `--select-model`/`-s`: Open the interactive model selector at startup (shows all models unless `--model` is also provided).
|
|
84
73
|
- `--continue`/`-c`: Resume the most recent session.
|
|
85
74
|
- `--resume`/`-r`: Select a session to resume for this project.
|
|
86
75
|
- `--resume-by-id <id>`: Resume a session by its ID directly.
|
|
87
|
-
- `--vanilla`: Minimal mode with only basic tools (Bash, Read, Edit) and no system prompts.
|
|
76
|
+
- `--vanilla`: Minimal mode with only basic tools (Bash, Read, Edit, Write) and no system prompts.
|
|
88
77
|
|
|
89
78
|
**Model selection behavior:**
|
|
90
79
|
- Default: uses `main_model` from config.
|
|
@@ -255,48 +244,16 @@ provider_list:
|
|
|
255
244
|
context_limit: 128000
|
|
256
245
|
```
|
|
257
246
|
|
|
258
|
-
##### Full Example
|
|
259
|
-
|
|
260
|
-
```yaml
|
|
261
|
-
# User configuration - merged with built-in config
|
|
262
|
-
main_model: opus
|
|
263
|
-
|
|
264
|
-
sub_agent_models:
|
|
265
|
-
explore: sonnet
|
|
266
|
-
task: opus
|
|
267
|
-
webagent: sonnet
|
|
268
|
-
|
|
269
|
-
provider_list:
|
|
270
|
-
# Add models to built-in openrouter
|
|
271
|
-
- provider_name: openrouter
|
|
272
|
-
model_list:
|
|
273
|
-
- model_name: qwen-coder
|
|
274
|
-
model_params:
|
|
275
|
-
model: qwen/qwen-2.5-coder-32b-instruct
|
|
276
|
-
context_limit: 131072
|
|
277
|
-
|
|
278
|
-
# Add a completely new provider
|
|
279
|
-
- provider_name: local-ollama
|
|
280
|
-
protocol: openai
|
|
281
|
-
base_url: http://localhost:11434/v1
|
|
282
|
-
api_key: ollama
|
|
283
|
-
model_list:
|
|
284
|
-
- model_name: local-llama
|
|
285
|
-
model_params:
|
|
286
|
-
model: llama3.2
|
|
287
|
-
context_limit: 8192
|
|
288
|
-
```
|
|
289
|
-
|
|
290
247
|
##### Supported Protocols
|
|
291
248
|
|
|
292
|
-
- `anthropic` - Anthropic
|
|
249
|
+
- `anthropic` - Anthropic Messages API
|
|
293
250
|
- `claude_oauth` - Claude OAuth (for Claude Pro/Max subscribers)
|
|
294
|
-
- `openai` - OpenAI
|
|
251
|
+
- `openai` - OpenAI Chat Completion API
|
|
295
252
|
- `responses` - OpenAI Responses API (for o-series, GPT-5, Codex)
|
|
296
|
-
- `openrouter` - OpenRouter API
|
|
297
|
-
- `google` - Google Gemini API
|
|
298
|
-
- `bedrock` - AWS Bedrock (uses AWS credentials instead of api_key)
|
|
299
253
|
- `codex_oauth` - OpenAI Codex CLI (OAuth-based, for ChatGPT Pro subscribers)
|
|
254
|
+
- `openrouter` - OpenRouter API (handling `reasoning_details` for interleaved thinking)
|
|
255
|
+
- `google` - Google Gemini API
|
|
256
|
+
- `bedrock` - AWS Bedrock for Claude(uses AWS credentials instead of api_key)
|
|
300
257
|
|
|
301
258
|
List configured providers and models:
|
|
302
259
|
|
|
@@ -338,6 +295,7 @@ Inside the interactive session (`klaude`), use these commands to streamline your
|
|
|
338
295
|
- `/model` - Switch the active LLM during the session.
|
|
339
296
|
- `/thinking` - Configure model thinking/reasoning level.
|
|
340
297
|
- `/clear` - Clear the current conversation context.
|
|
298
|
+
- `/copy` - Copy last assistant message.
|
|
341
299
|
- `/status` - Show session usage statistics (cost, tokens, model breakdown).
|
|
342
300
|
- `/resume` - Select and resume a previous session.
|
|
343
301
|
- `/fork-session` - Fork current session to a new session ID (supports interactive fork point selection).
|
|
@@ -364,29 +322,6 @@ Inside the interactive session (`klaude`), use these commands to streamline your
|
|
|
364
322
|
| `Backspace` | Delete character or selected text |
|
|
365
323
|
| `c` (with selection) | Copy selected text to clipboard |
|
|
366
324
|
|
|
367
|
-
### Non-Interactive Headless Mode (exec)
|
|
368
|
-
|
|
369
|
-
Execute a single command without starting the interactive REPL:
|
|
370
|
-
|
|
371
|
-
```bash
|
|
372
|
-
# Direct input
|
|
373
|
-
klaude exec "what is 2+2?"
|
|
374
|
-
|
|
375
|
-
# Pipe input
|
|
376
|
-
echo "hello world" | klaude exec
|
|
377
|
-
|
|
378
|
-
# With model selection
|
|
379
|
-
|
|
380
|
-
# Exact model name (non-interactive)
|
|
381
|
-
echo "generate quicksort in python" | klaude exec --model gpt-5.1
|
|
382
|
-
|
|
383
|
-
# Partial/ambiguous name opens the interactive selector (filtered)
|
|
384
|
-
echo "generate quicksort in python" | klaude exec --model gpt
|
|
385
|
-
|
|
386
|
-
# Stream all events as JSON lines (for programmatic processing)
|
|
387
|
-
klaude exec "what is 2+2?" --stream-json
|
|
388
|
-
```
|
|
389
|
-
|
|
390
325
|
### Sub-Agents
|
|
391
326
|
|
|
392
327
|
The main agent can spawn specialized sub-agents for specific tasks:
|