klaude-code 1.2.17__tar.gz → 1.2.19__tar.gz

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.
Files changed (200) hide show
  1. {klaude_code-1.2.17 → klaude_code-1.2.19}/PKG-INFO +32 -7
  2. {klaude_code-1.2.17 → klaude_code-1.2.19}/README.md +31 -6
  3. {klaude_code-1.2.17 → klaude_code-1.2.19}/pyproject.toml +5 -1
  4. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/config_cmd.py +1 -1
  5. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/debug.py +1 -1
  6. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/main.py +45 -31
  7. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/runtime.py +49 -13
  8. klaude_code-1.2.17/src/klaude_code/version.py → klaude_code-1.2.19/src/klaude_code/cli/self_update.py +110 -2
  9. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/__init__.py +4 -1
  10. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/clear_cmd.py +2 -7
  11. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/command_abc.py +33 -5
  12. klaude_code-1.2.19/src/klaude_code/command/debug_cmd.py +79 -0
  13. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/diff_cmd.py +2 -6
  14. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/export_cmd.py +7 -7
  15. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/export_online_cmd.py +9 -8
  16. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/help_cmd.py +4 -9
  17. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/model_cmd.py +10 -6
  18. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/prompt_command.py +2 -6
  19. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/refresh_cmd.py +2 -7
  20. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/registry.py +69 -26
  21. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/release_notes_cmd.py +2 -6
  22. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/status_cmd.py +2 -7
  23. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/terminal_setup_cmd.py +2 -6
  24. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/thinking_cmd.py +16 -10
  25. klaude_code-1.2.19/src/klaude_code/config/select_model.py +133 -0
  26. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/const/__init__.py +1 -1
  27. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/executor.py +257 -110
  28. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/manager/__init__.py +2 -4
  29. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-claude-code.md +1 -1
  30. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +14 -2
  31. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +8 -5
  32. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/reminders.py +9 -35
  33. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/task.py +9 -7
  34. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/read_tool.md +1 -1
  35. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/read_tool.py +41 -12
  36. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/memory/skill_loader.py +12 -10
  37. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/shell/bash_tool.py +22 -2
  38. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/tool_registry.py +1 -1
  39. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/tool_runner.py +26 -23
  40. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/truncation.py +23 -9
  41. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/web_fetch_tool.md +1 -1
  42. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/web_fetch_tool.py +36 -1
  43. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/turn.py +28 -0
  44. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/anthropic/client.py +25 -9
  45. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openai_compatible/client.py +5 -2
  46. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openrouter/client.py +7 -3
  47. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/responses/client.py +6 -1
  48. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/commands.py +1 -0
  49. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/sub_agent/web.py +3 -2
  50. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/session/session.py +35 -15
  51. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/session/templates/export_session.html +45 -32
  52. klaude_code-1.2.19/src/klaude_code/trace/__init__.py +21 -0
  53. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/completers.py +231 -73
  54. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/event_handler.py +8 -6
  55. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/input_prompt_toolkit.py +1 -1
  56. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/renderer.py +2 -2
  57. klaude_code-1.2.19/src/klaude_code/ui/renderers/common.py +62 -0
  58. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/developer.py +2 -3
  59. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/errors.py +1 -1
  60. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/metadata.py +12 -5
  61. klaude_code-1.2.19/src/klaude_code/ui/renderers/thinking.py +55 -0
  62. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/tools.py +82 -14
  63. klaude_code-1.2.19/src/klaude_code/ui/rich/code_panel.py +112 -0
  64. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/markdown.py +3 -4
  65. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/status.py +0 -2
  66. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/theme.py +10 -1
  67. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/utils/common.py +0 -18
  68. klaude_code-1.2.17/src/klaude_code/config/select_model.py +0 -57
  69. klaude_code-1.2.17/src/klaude_code/core/manager/agent_manager.py +0 -132
  70. klaude_code-1.2.17/src/klaude_code/trace/__init__.py +0 -3
  71. klaude_code-1.2.17/src/klaude_code/ui/renderers/common.py +0 -8
  72. klaude_code-1.2.17/src/klaude_code/ui/renderers/thinking.py +0 -39
  73. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/__init__.py +0 -0
  74. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/auth/__init__.py +0 -0
  75. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/auth/codex/__init__.py +0 -0
  76. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/auth/codex/exceptions.py +0 -0
  77. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  78. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/auth/codex/oauth.py +0 -0
  79. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/auth/codex/token_manager.py +0 -0
  80. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/__init__.py +0 -0
  81. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/auth_cmd.py +0 -0
  82. {klaude_code-1.2.17/src/klaude_code/config → klaude_code-1.2.19/src/klaude_code/cli}/list_model.py +0 -0
  83. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/cli/session_cmd.py +0 -0
  84. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/prompt-deslop.md +0 -0
  85. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/prompt-dev-docs-update.md +0 -0
  86. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/prompt-dev-docs.md +0 -0
  87. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/prompt-handoff.md +0 -0
  88. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/command/prompt-init.md +0 -0
  89. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/config/__init__.py +0 -0
  90. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/config/config.py +0 -0
  91. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/__init__.py +0 -0
  92. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/agent.py +0 -0
  93. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/manager/llm_clients.py +0 -0
  94. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
  95. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/manager/sub_agent_manager.py +0 -0
  96. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompt.py +0 -0
  97. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
  98. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1.md +0 -0
  99. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
  100. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
  101. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-sub-agent-oracle.md +0 -0
  102. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  103. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/__init__.py +0 -0
  104. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/__init__.py +0 -0
  105. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/_utils.py +0 -0
  106. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  107. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  108. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
  109. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  110. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
  111. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/multi_edit_tool.md +0 -0
  112. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/multi_edit_tool.py +0 -0
  113. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  114. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/file/write_tool.py +0 -0
  115. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/memory/__init__.py +0 -0
  116. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/memory/memory_tool.md +0 -0
  117. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/memory/memory_tool.py +0 -0
  118. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/memory/skill_tool.md +0 -0
  119. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/memory/skill_tool.py +0 -0
  120. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/report_back_tool.py +0 -0
  121. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  122. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  123. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  124. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/sub_agent_tool.py +0 -0
  125. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/todo/__init__.py +0 -0
  126. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  127. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
  128. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  129. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  130. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
  131. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/tool_abc.py +0 -0
  132. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/tool_context.py +0 -0
  133. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/__init__.py +0 -0
  134. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
  135. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
  136. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  137. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
  138. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/__init__.py +0 -0
  139. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  140. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/anthropic/input.py +0 -0
  141. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/client.py +0 -0
  142. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/codex/__init__.py +0 -0
  143. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/codex/client.py +0 -0
  144. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/input_common.py +0 -0
  145. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  146. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openai_compatible/input.py +0 -0
  147. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openai_compatible/stream_processor.py +0 -0
  148. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
  149. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  150. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openrouter/input.py +0 -0
  151. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/openrouter/reasoning_handler.py +0 -0
  152. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/registry.py +0 -0
  153. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/responses/__init__.py +0 -0
  154. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/responses/input.py +0 -0
  155. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/llm/usage.py +0 -0
  156. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/__init__.py +0 -0
  157. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/events.py +0 -0
  158. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/llm_param.py +0 -0
  159. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/model.py +0 -0
  160. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/op.py +0 -0
  161. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/op_handler.py +0 -0
  162. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
  163. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
  164. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/sub_agent/oracle.py +0 -0
  165. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/sub_agent/task.py +0 -0
  166. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/protocol/tools.py +0 -0
  167. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/session/__init__.py +0 -0
  168. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/session/export.py +0 -0
  169. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/session/selector.py +0 -0
  170. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/trace/log.py +0 -0
  171. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/__init__.py +0 -0
  172. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/core/__init__.py +0 -0
  173. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/core/display.py +0 -0
  174. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/core/input.py +0 -0
  175. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/core/stage_manager.py +0 -0
  176. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/__init__.py +0 -0
  177. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/debug/__init__.py +0 -0
  178. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/debug/display.py +0 -0
  179. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/exec/__init__.py +0 -0
  180. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/exec/display.py +0 -0
  181. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/__init__.py +0 -0
  182. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/clipboard.py +0 -0
  183. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/display.py +0 -0
  184. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/modes/repl/key_bindings.py +0 -0
  185. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/__init__.py +0 -0
  186. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/assistant.py +0 -0
  187. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/diffs.py +0 -0
  188. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/sub_agent.py +0 -0
  189. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/renderers/user_input.py +0 -0
  190. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/__init__.py +0 -0
  191. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/live.py +0 -0
  192. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/quote.py +0 -0
  193. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/rich/searchable_text.py +0 -0
  194. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/terminal/__init__.py +0 -0
  195. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/terminal/color.py +0 -0
  196. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/terminal/control.py +0 -0
  197. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/terminal/notifier.py +0 -0
  198. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/terminal/progress_bar.py +0 -0
  199. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/utils/__init__.py +0 -0
  200. {klaude_code-1.2.17 → klaude_code-1.2.19}/src/klaude_code/ui/utils/debouncer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 1.2.17
3
+ Version: 1.2.19
4
4
  Summary: Add your description here
5
5
  Requires-Dist: anthropic>=0.66.0
6
6
  Requires-Dist: ddgs>=9.9.3
@@ -41,6 +41,21 @@ To update:
41
41
  uv tool upgrade klaude-code
42
42
  ```
43
43
 
44
+ Or use the built-in alias command:
45
+
46
+ ```bash
47
+ klaude update
48
+ klaude upgrade
49
+ ```
50
+
51
+ To show version:
52
+
53
+ ```bash
54
+ klaude --version
55
+ klaude -v
56
+ klaude version
57
+ ```
58
+
44
59
  ## Usage
45
60
 
46
61
  ### Interactive Mode
@@ -50,13 +65,18 @@ klaude [--model <name>] [--select-model]
50
65
  ```
51
66
 
52
67
  **Options:**
53
- - `--version`/`-V`: Show version and exit.
54
- - `--model`/`-m`: Select a model by logical name from config.
55
- - `--select-model`/`-s`: Interactively choose a model at startup.
68
+ - `--version`/`-V`/`-v`: Show version and exit.
69
+ - `--model`/`-m`: Preferred model name (exact match picks immediately; otherwise opens the interactive selector filtered by this value).
70
+ - `--select-model`/`-s`: Open the interactive model selector at startup (shows all models unless `--model` is also provided).
56
71
  - `--continue`/`-c`: Resume the most recent session.
57
72
  - `--resume`/`-r`: Select a session to resume for this project.
58
73
  - `--vanilla`: Minimal mode with only basic tools (Bash, Read, Edit) and no system prompts.
59
74
 
75
+ **Model selection behavior:**
76
+ - Default: uses `main_model` from config.
77
+ - `--select-model`: always prompts you to pick.
78
+ - `--model <value>`: tries to resolve `<value>` to a single model; if it can't, it prompts with a filtered list (and falls back to showing all models if there are no matches).
79
+
60
80
  **Debug Options:**
61
81
  - `--debug`/`-d`: Enable debug mode with verbose logging and LLM trace.
62
82
  - `--debug-filter`: Filter debug output by type (comma-separated).
@@ -64,7 +84,7 @@ klaude [--model <name>] [--select-model]
64
84
 
65
85
  ### Configuration
66
86
 
67
- An example config will be created in `~/.klaude/config.yaml` when first run.
87
+ An example config will be created in `~/.klaude/klaude-config.yaml` when first run.
68
88
 
69
89
  Open the configuration file in editor:
70
90
 
@@ -201,7 +221,7 @@ sub_agent_models:
201
221
  oracle: gpt-5.1
202
222
  explore: haiku
203
223
  task: opus
204
- webfetchagent: haiku
224
+ webagent: haiku
205
225
 
206
226
  ```
207
227
 
@@ -263,5 +283,10 @@ klaude exec "what is 2+2?"
263
283
  echo "hello world" | klaude exec
264
284
 
265
285
  # With model selection
286
+
287
+ # Exact model name (non-interactive)
266
288
  echo "generate quicksort in python" | klaude exec --model gpt-5.1
267
- ```
289
+
290
+ # Partial/ambiguous name opens the interactive selector (filtered)
291
+ echo "generate quicksort in python" | klaude exec --model gpt
292
+ ```
@@ -23,6 +23,21 @@ To update:
23
23
  uv tool upgrade klaude-code
24
24
  ```
25
25
 
26
+ Or use the built-in alias command:
27
+
28
+ ```bash
29
+ klaude update
30
+ klaude upgrade
31
+ ```
32
+
33
+ To show version:
34
+
35
+ ```bash
36
+ klaude --version
37
+ klaude -v
38
+ klaude version
39
+ ```
40
+
26
41
  ## Usage
27
42
 
28
43
  ### Interactive Mode
@@ -32,13 +47,18 @@ klaude [--model <name>] [--select-model]
32
47
  ```
33
48
 
34
49
  **Options:**
35
- - `--version`/`-V`: Show version and exit.
36
- - `--model`/`-m`: Select a model by logical name from config.
37
- - `--select-model`/`-s`: Interactively choose a model at startup.
50
+ - `--version`/`-V`/`-v`: Show version and exit.
51
+ - `--model`/`-m`: Preferred model name (exact match picks immediately; otherwise opens the interactive selector filtered by this value).
52
+ - `--select-model`/`-s`: Open the interactive model selector at startup (shows all models unless `--model` is also provided).
38
53
  - `--continue`/`-c`: Resume the most recent session.
39
54
  - `--resume`/`-r`: Select a session to resume for this project.
40
55
  - `--vanilla`: Minimal mode with only basic tools (Bash, Read, Edit) and no system prompts.
41
56
 
57
+ **Model selection behavior:**
58
+ - Default: uses `main_model` from config.
59
+ - `--select-model`: always prompts you to pick.
60
+ - `--model <value>`: tries to resolve `<value>` to a single model; if it can't, it prompts with a filtered list (and falls back to showing all models if there are no matches).
61
+
42
62
  **Debug Options:**
43
63
  - `--debug`/`-d`: Enable debug mode with verbose logging and LLM trace.
44
64
  - `--debug-filter`: Filter debug output by type (comma-separated).
@@ -46,7 +66,7 @@ klaude [--model <name>] [--select-model]
46
66
 
47
67
  ### Configuration
48
68
 
49
- An example config will be created in `~/.klaude/config.yaml` when first run.
69
+ An example config will be created in `~/.klaude/klaude-config.yaml` when first run.
50
70
 
51
71
  Open the configuration file in editor:
52
72
 
@@ -183,7 +203,7 @@ sub_agent_models:
183
203
  oracle: gpt-5.1
184
204
  explore: haiku
185
205
  task: opus
186
- webfetchagent: haiku
206
+ webagent: haiku
187
207
 
188
208
  ```
189
209
 
@@ -245,5 +265,10 @@ klaude exec "what is 2+2?"
245
265
  echo "hello world" | klaude exec
246
266
 
247
267
  # With model selection
268
+
269
+ # Exact model name (non-interactive)
248
270
  echo "generate quicksort in python" | klaude exec --model gpt-5.1
249
- ```
271
+
272
+ # Partial/ambiguous name opens the interactive selector (filtered)
273
+ echo "generate quicksort in python" | klaude exec --model gpt
274
+ ```
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "klaude-code"
7
- version = "1.2.17"
7
+ version = "1.2.19"
8
8
  description = "Add your description here"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -77,10 +77,14 @@ name = "Layered architecture"
77
77
  type = "layers"
78
78
  layers = [
79
79
  "klaude_code.cli",
80
+ "klaude_code.ui",
80
81
  "klaude_code.core",
82
+ "klaude_code.command",
81
83
  "klaude_code.session",
82
84
  "klaude_code.config",
83
85
  "klaude_code.llm",
84
86
  "klaude_code.protocol",
87
+ "klaude_code.trace",
88
+ "klaude_code.auth",
85
89
  "klaude_code.const",
86
90
  ]
@@ -12,7 +12,7 @@ from klaude_code.trace import log
12
12
 
13
13
  def list_models() -> None:
14
14
  """List all models and providers configuration"""
15
- from klaude_code.config.list_model import display_models_and_providers
15
+ from klaude_code.cli.list_model import display_models_and_providers
16
16
  from klaude_code.ui.terminal.color import is_light_terminal_background
17
17
 
18
18
  config = load_config()
@@ -48,7 +48,7 @@ def open_log_file_in_editor(path: Path) -> None:
48
48
  editor = os.environ.get("EDITOR")
49
49
 
50
50
  if not editor:
51
- for cmd in ["open", "xdg-open", "code", "nvim", "vim", "nano"]:
51
+ for cmd in ["open", "xdg-open", "code", "TextEdit", "notepad"]:
52
52
  try:
53
53
  subprocess.run(["which", cmd], check=True, capture_output=True)
54
54
  editor = cmd
@@ -1,8 +1,6 @@
1
1
  import asyncio
2
2
  import os
3
3
  import sys
4
- from importlib.metadata import PackageNotFoundError
5
- from importlib.metadata import version as pkg_version
6
4
  from pathlib import Path
7
5
 
8
6
  import typer
@@ -10,8 +8,8 @@ import typer
10
8
  from klaude_code.cli.auth_cmd import register_auth_commands
11
9
  from klaude_code.cli.config_cmd import register_config_commands
12
10
  from klaude_code.cli.debug import DEBUG_FILTER_HELP, open_log_file_in_editor, resolve_debug_settings
11
+ from klaude_code.cli.self_update import register_self_update_commands, version_option_callback
13
12
  from klaude_code.cli.session_cmd import register_session_commands
14
- from klaude_code.config import load_config
15
13
  from klaude_code.session import Session, resume_select_session
16
14
  from klaude_code.trace import DebugType, prepare_debug_log_file
17
15
 
@@ -22,10 +20,13 @@ def set_terminal_title(title: str) -> None:
22
20
  sys.stdout.flush()
23
21
 
24
22
 
25
- def setup_terminal_title() -> None:
26
- """Set terminal title to current folder name."""
23
+ def update_terminal_title(model_name: str | None = None) -> None:
24
+ """Update terminal title with folder name and optional model name."""
27
25
  folder_name = os.path.basename(os.getcwd())
28
- set_terminal_title(f"{folder_name}: klaude")
26
+ if model_name:
27
+ set_terminal_title(f"{folder_name}: klaude ✳ {model_name}")
28
+ else:
29
+ set_terminal_title(f"{folder_name}: klaude")
29
30
 
30
31
 
31
32
  def prepare_debug_logging(debug: bool, debug_filter: str | None) -> tuple[bool, set[DebugType] | None, Path | None]:
@@ -79,20 +80,6 @@ def read_input_content(cli_argument: str) -> str | None:
79
80
  return content
80
81
 
81
82
 
82
- def _version_callback(value: bool) -> None:
83
- """Show version and exit."""
84
- if value:
85
- try:
86
- ver = pkg_version("klaude-code")
87
- except PackageNotFoundError:
88
- # Package is not installed or has no metadata; show a generic version string.
89
- ver = "unknown"
90
- except Exception:
91
- ver = "unknown"
92
- print(f"klaude-code {ver}")
93
- raise typer.Exit(0)
94
-
95
-
96
83
  app = typer.Typer(
97
84
  add_completion=False,
98
85
  pretty_exceptions_enable=False,
@@ -104,6 +91,8 @@ register_session_commands(app)
104
91
  register_auth_commands(app)
105
92
  register_config_commands(app)
106
93
 
94
+ register_self_update_commands(app)
95
+
107
96
 
108
97
  @app.command("exec")
109
98
  def exec_command(
@@ -147,7 +136,7 @@ def exec_command(
147
136
  ),
148
137
  ) -> None:
149
138
  """Execute non-interactively with provided input."""
150
- setup_terminal_title()
139
+ update_terminal_title()
151
140
 
152
141
  merged_input = read_input_content(input_content)
153
142
  if merged_input is None:
@@ -157,13 +146,8 @@ def exec_command(
157
146
  from klaude_code.config.select_model import select_model_from_config
158
147
 
159
148
  chosen_model = model
160
- if select_model:
161
- # Prefer the explicitly provided model as default; otherwise main model
162
- config = load_config()
163
- if config is None:
164
- raise typer.Exit(1)
165
- default_name = model or config.main_model
166
- chosen_model = select_model_from_config(preferred=default_name)
149
+ if model or select_model:
150
+ chosen_model = select_model_from_config(preferred=model)
167
151
  if chosen_model is None:
168
152
  return
169
153
 
@@ -196,8 +180,9 @@ def main_callback(
196
180
  False,
197
181
  "--version",
198
182
  "-V",
183
+ "-v",
199
184
  help="Show version and exit",
200
- callback=_version_callback,
185
+ callback=version_option_callback,
201
186
  is_eager=True,
202
187
  ),
203
188
  model: str | None = typer.Option(
@@ -240,10 +225,10 @@ def main_callback(
240
225
  from klaude_code.cli.runtime import AppInitConfig, run_interactive
241
226
  from klaude_code.config.select_model import select_model_from_config
242
227
 
243
- setup_terminal_title()
228
+ update_terminal_title()
244
229
 
245
230
  chosen_model = model
246
- if select_model:
231
+ if model or select_model:
247
232
  chosen_model = select_model_from_config(preferred=model)
248
233
  if chosen_model is None:
249
234
  return
@@ -260,6 +245,35 @@ def main_callback(
260
245
  session_id = Session.most_recent_session_id()
261
246
  # If still no session_id, leave as None to create a new session
262
247
 
248
+ if session_id is not None and chosen_model is None:
249
+ from klaude_code.config import load_config
250
+ from klaude_code.trace import log
251
+
252
+ session_meta = Session.load_meta(session_id)
253
+ cfg = load_config()
254
+
255
+ if cfg is not None and session_meta.model_config_name:
256
+ if any(m.model_name == session_meta.model_config_name for m in cfg.model_list):
257
+ chosen_model = session_meta.model_config_name
258
+ else:
259
+ log(
260
+ (
261
+ f"Warning: session model '{session_meta.model_config_name}' is not defined in config; falling back to default",
262
+ "yellow",
263
+ )
264
+ )
265
+
266
+ if cfg is not None and chosen_model is None and session_meta.model_name:
267
+ raw_model = session_meta.model_name.strip()
268
+ if raw_model:
269
+ matches = [
270
+ m.model_name
271
+ for m in cfg.model_list
272
+ if (m.model_params.model or "").strip().lower() == raw_model.lower()
273
+ ]
274
+ if len(matches) == 1:
275
+ chosen_model = matches[0]
276
+
263
277
  debug_enabled, debug_filters, log_path = prepare_debug_logging(debug, debug_filter)
264
278
 
265
279
  init_config = AppInitConfig(
@@ -8,6 +8,8 @@ import typer
8
8
  from rich.text import Text
9
9
 
10
10
  from klaude_code import ui
11
+ from klaude_code.cli.main import update_terminal_title
12
+ from klaude_code.cli.self_update import get_update_message
11
13
  from klaude_code.command import has_interactive_command
12
14
  from klaude_code.config import Config, load_config
13
15
  from klaude_code.core.agent import Agent, DefaultModelProfileProvider, VanillaModelProfileProvider
@@ -21,7 +23,6 @@ from klaude_code.ui.modes.repl.input_prompt_toolkit import REPLStatusSnapshot
21
23
  from klaude_code.ui.terminal.color import is_light_terminal_background
22
24
  from klaude_code.ui.terminal.control import install_sigint_double_press_exit, start_esc_interrupt_monitor
23
25
  from klaude_code.ui.terminal.progress_bar import OSC94States, emit_osc94
24
- from klaude_code.version import get_update_message
25
26
 
26
27
 
27
28
  class PrintCapable(Protocol):
@@ -92,14 +93,20 @@ async def initialize_app_components(init_config: AppInitConfig) -> AppComponents
92
93
  event_queue,
93
94
  llm_clients,
94
95
  model_profile_provider=model_profile_provider,
96
+ on_model_change=update_terminal_title,
95
97
  )
96
98
 
99
+ # Update terminal title with initial model name
100
+ update_terminal_title(llm_clients.main.model_name)
101
+
97
102
  # Start executor in background
98
103
  executor_task = asyncio.create_task(executor.start())
99
104
 
100
105
  theme: str | None = config.theme
101
- if theme is None:
106
+ if theme is None and not init_config.is_exec_mode:
102
107
  # Auto-detect theme from terminal background when config does not specify a theme.
108
+ # Skip detection in exec mode to avoid TTY race conditions with parent process's
109
+ # ESC monitor when running as a subprocess.
103
110
  detected = is_light_terminal_background()
104
111
  if detected is True:
105
112
  theme = "light"
@@ -145,8 +152,30 @@ async def initialize_session(
145
152
  await executor.submit_and_wait(op.InitAgentOperation(session_id=session_id))
146
153
  await event_queue.join()
147
154
 
148
- active_session_ids = executor.context.agent_manager.active_session_ids()
149
- return active_session_ids[0] if active_session_ids else session_id
155
+ active_session_id = executor.context.current_session_id()
156
+ return active_session_id or session_id
157
+
158
+
159
+ def _backfill_session_model_config(
160
+ agent: Agent | None,
161
+ model_override: str | None,
162
+ default_model: str,
163
+ is_new_session: bool,
164
+ ) -> None:
165
+ """Backfill model_config_name and model_thinking on newly created sessions."""
166
+ if agent is None or agent.session.model_config_name is not None:
167
+ return
168
+
169
+ if model_override is not None:
170
+ agent.session.model_config_name = model_override
171
+ elif is_new_session:
172
+ agent.session.model_config_name = default_model
173
+ else:
174
+ return
175
+
176
+ if agent.session.model_thinking is None and agent.profile:
177
+ agent.session.model_thinking = agent.profile.llm_client.get_llm_config().thinking
178
+ # Don't save here - session will be saved when first message is sent via append_history()
150
179
 
151
180
 
152
181
  async def cleanup_app_components(components: AppComponents) -> None:
@@ -190,6 +219,12 @@ async def run_exec(init_config: AppInitConfig, input_content: str) -> None:
190
219
 
191
220
  try:
192
221
  session_id = await initialize_session(components.executor, components.event_queue)
222
+ _backfill_session_model_config(
223
+ components.executor.context.current_agent,
224
+ init_config.model,
225
+ components.config.main_model,
226
+ is_new_session=True,
227
+ )
193
228
 
194
229
  # Submit the input content directly
195
230
  await components.executor.submit_and_wait(
@@ -214,16 +249,12 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
214
249
 
215
250
  # Create status provider for bottom toolbar
216
251
  def _status_provider() -> REPLStatusSnapshot:
217
- agent: Agent | None = None
218
- # Get the first active agent (there should only be one in interactive mode)
219
- active_agents = components.executor.context.active_agents
220
- if active_agents:
221
- agent = next(iter(active_agents.values()), None)
222
-
223
252
  # Check for updates (returns None if uv not available)
224
253
  update_message = get_update_message()
225
254
 
226
- return build_repl_status_snapshot(agent=agent, update_message=update_message)
255
+ return build_repl_status_snapshot(
256
+ agent=components.executor.context.current_agent, update_message=update_message
257
+ )
227
258
 
228
259
  # Set up input provider for interactive mode
229
260
  input_provider: ui.InputProviderABC = ui.PromptToolkitInput(status_provider=_status_provider)
@@ -262,14 +293,19 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
262
293
 
263
294
  try:
264
295
  await initialize_session(components.executor, components.event_queue, session_id=session_id)
296
+ _backfill_session_model_config(
297
+ components.executor.context.current_agent,
298
+ init_config.model,
299
+ components.config.main_model,
300
+ is_new_session=session_id is None,
301
+ )
265
302
 
266
303
  def _get_active_session_id() -> str | None:
267
304
  """Get the current active session ID dynamically.
268
305
 
269
306
  This is necessary because /clear command creates a new session with a different ID.
270
307
  """
271
- active_ids = components.executor.context.agent_manager.active_session_ids()
272
- return active_ids[0] if active_ids else None
308
+ return components.executor.context.current_session_id()
273
309
 
274
310
  # Input
275
311
  await input_provider.start()
@@ -1,4 +1,4 @@
1
- """Version checking utilities for klaude-code."""
1
+ """Self-update and version utilities for klaude-code."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -8,8 +8,14 @@ import subprocess
8
8
  import threading
9
9
  import time
10
10
  import urllib.request
11
+ from importlib.metadata import PackageNotFoundError
12
+ from importlib.metadata import version as pkg_version
11
13
  from typing import NamedTuple
12
14
 
15
+ import typer
16
+
17
+ from klaude_code.trace import log
18
+
13
19
  PACKAGE_NAME = "klaude-code"
14
20
  PYPI_URL = f"https://pypi.org/pypi/{PACKAGE_NAME}/json"
15
21
  CHECK_INTERVAL_SECONDS = 3600 # Check at most once per hour
@@ -160,4 +166,106 @@ def get_update_message() -> str | None:
160
166
  info = check_for_updates()
161
167
  if info is None or not info.update_available:
162
168
  return None
163
- return f"New version available: {info.latest}. Please run `uv tool upgrade {PACKAGE_NAME}` to upgrade."
169
+ return f"New version available: {info.latest}. Please run `klaude upgrade` to upgrade."
170
+
171
+
172
+ def _print_version() -> None:
173
+ try:
174
+ ver = pkg_version(PACKAGE_NAME)
175
+ except PackageNotFoundError:
176
+ ver = "unknown"
177
+ except Exception:
178
+ ver = "unknown"
179
+ print(f"{PACKAGE_NAME} {ver}")
180
+
181
+
182
+ def version_option_callback(value: bool) -> None:
183
+ """Show version and exit."""
184
+ if value:
185
+ _print_version()
186
+ raise typer.Exit(0)
187
+
188
+
189
+ def version_command() -> None:
190
+ """Show version and exit."""
191
+
192
+ _print_version()
193
+
194
+
195
+ def update_command(
196
+ check: bool = typer.Option(
197
+ False,
198
+ "--check",
199
+ help="Check for updates and exit without upgrading",
200
+ ),
201
+ ) -> None:
202
+ """Upgrade klaude-code when installed via `uv tool`."""
203
+
204
+ info = check_for_updates_blocking()
205
+
206
+ if check:
207
+ if info is None:
208
+ log(("Error: `uv` is not available; cannot check for updates.", "red"))
209
+ log(f"Install uv, then run `uv tool upgrade {PACKAGE_NAME}`.")
210
+ raise typer.Exit(1)
211
+
212
+ installed_display = info.installed or "unknown"
213
+ latest_display = info.latest or "unknown"
214
+ status = "update available" if info.update_available else "up to date"
215
+
216
+ log(f"{PACKAGE_NAME} installed: {installed_display}")
217
+ log(f"{PACKAGE_NAME} latest: {latest_display}")
218
+ log(f"Status: {status}")
219
+
220
+ if info.update_available:
221
+ log("Run `klaude upgrade` to upgrade.")
222
+
223
+ return
224
+
225
+ if shutil.which("uv") is None:
226
+ log(("Error: `uv` not found in PATH.", "red"))
227
+ log(f"To update, install uv and run `uv tool upgrade {PACKAGE_NAME}`.")
228
+ raise typer.Exit(1)
229
+
230
+ log(f"Running `uv tool upgrade {PACKAGE_NAME}`...")
231
+ result = subprocess.run(["uv", "tool", "upgrade", PACKAGE_NAME], check=False)
232
+ if result.returncode != 0:
233
+ log((f"Error: update failed (exit code {result.returncode}).", "red"))
234
+ raise typer.Exit(result.returncode or 1)
235
+
236
+ log("Update complete. Please re-run `klaude` to use the new version.")
237
+
238
+
239
+ def register_self_update_commands(app: typer.Typer) -> None:
240
+ """Register self-update and version subcommands to the given Typer app."""
241
+
242
+ app.command("update")(update_command)
243
+ app.command("upgrade", help="Alias for `klaude update`.")(update_command)
244
+ app.command("version", help="Alias for `klaude --version`.")(version_command)
245
+
246
+
247
+ def check_for_updates_blocking() -> VersionInfo | None:
248
+ """Check for updates to klaude-code synchronously.
249
+
250
+ This is intended for CLI commands (e.g. `klaude update --check`) that need
251
+ a deterministic result instead of the async cached behavior.
252
+
253
+ Returns:
254
+ VersionInfo if uv is available, otherwise None.
255
+ """
256
+
257
+ if not _has_uv():
258
+ return None
259
+
260
+ installed = _get_installed_version()
261
+ latest = _get_latest_version()
262
+
263
+ update_available = False
264
+ if installed and latest:
265
+ update_available = _compare_versions(installed, latest)
266
+
267
+ return VersionInfo(
268
+ installed=installed,
269
+ latest=latest,
270
+ update_available=update_available,
271
+ )
@@ -28,6 +28,7 @@ def ensure_commands_loaded() -> None:
28
28
 
29
29
  # Import and register commands in display order
30
30
  from .clear_cmd import ClearCommand
31
+ from .debug_cmd import DebugCommand
31
32
  from .diff_cmd import DiffCommand
32
33
  from .export_cmd import ExportCommand
33
34
  from .export_online_cmd import ExportOnlineCommand
@@ -46,12 +47,13 @@ def ensure_commands_loaded() -> None:
46
47
  register(ThinkingCommand())
47
48
  register(ModelCommand())
48
49
  load_prompt_commands()
49
- register(ClearCommand())
50
50
  register(StatusCommand())
51
51
  register(DiffCommand())
52
52
  register(HelpCommand())
53
53
  register(ReleaseNotesCommand())
54
54
  register(TerminalSetupCommand())
55
+ register(DebugCommand())
56
+ register(ClearCommand())
55
57
 
56
58
  # Load prompt-based commands (appended after built-in commands)
57
59
 
@@ -60,6 +62,7 @@ def ensure_commands_loaded() -> None:
60
62
  def __getattr__(name: str) -> object:
61
63
  _commands_map = {
62
64
  "ClearCommand": "clear_cmd",
65
+ "DebugCommand": "debug_cmd",
63
66
  "DiffCommand": "diff_cmd",
64
67
  "ExportCommand": "export_cmd",
65
68
  "ExportOnlineCommand": "export_online_cmd",
@@ -1,11 +1,6 @@
1
- from typing import TYPE_CHECKING
2
-
3
- from klaude_code.command.command_abc import CommandABC, CommandResult, InputAction
1
+ from klaude_code.command.command_abc import Agent, CommandABC, CommandResult, InputAction
4
2
  from klaude_code.protocol import commands
5
3
 
6
- if TYPE_CHECKING:
7
- from klaude_code.core.agent import Agent
8
-
9
4
 
10
5
  class ClearCommand(CommandABC):
11
6
  """Clear current session and start a new conversation"""
@@ -18,5 +13,5 @@ class ClearCommand(CommandABC):
18
13
  def summary(self) -> str:
19
14
  return "Clear conversation history and free up context"
20
15
 
21
- async def run(self, raw: str, agent: "Agent") -> CommandResult:
16
+ async def run(self, raw: str, agent: Agent) -> CommandResult:
22
17
  return CommandResult(actions=[InputAction.clear()])