klaude-code 1.2.22__tar.gz → 1.2.23__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 (204) hide show
  1. {klaude_code-1.2.22 → klaude_code-1.2.23}/PKG-INFO +18 -13
  2. {klaude_code-1.2.22 → klaude_code-1.2.23}/README.md +17 -12
  3. {klaude_code-1.2.22 → klaude_code-1.2.23}/pyproject.toml +2 -1
  4. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/status_cmd.py +1 -1
  5. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/const/__init__.py +8 -2
  6. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/manager/sub_agent_manager.py +1 -1
  7. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/reminders.py +51 -0
  8. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/task.py +37 -18
  9. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/__init__.py +1 -4
  10. {klaude_code-1.2.22/src/klaude_code/core/tool/memory → klaude_code-1.2.23/src/klaude_code/core/tool/skill}/skill_tool.py +16 -39
  11. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/model.py +2 -1
  12. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/export.py +1 -1
  13. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/store.py +4 -2
  14. klaude_code-1.2.23/src/klaude_code/skill/__init__.py +27 -0
  15. klaude_code-1.2.23/src/klaude_code/skill/assets/deslop/SKILL.md +17 -0
  16. klaude_code-1.2.23/src/klaude_code/skill/assets/dev-docs/SKILL.md +108 -0
  17. klaude_code-1.2.23/src/klaude_code/skill/assets/handoff/SKILL.md +39 -0
  18. klaude_code-1.2.23/src/klaude_code/skill/assets/jj-workspace/SKILL.md +20 -0
  19. klaude_code-1.2.23/src/klaude_code/skill/assets/skill-creator/SKILL.md +139 -0
  20. klaude_code-1.2.22/src/klaude_code/core/tool/memory/skill_loader.py → klaude_code-1.2.23/src/klaude_code/skill/loader.py +60 -24
  21. klaude_code-1.2.23/src/klaude_code/skill/manager.py +70 -0
  22. klaude_code-1.2.23/src/klaude_code/skill/system_skills.py +192 -0
  23. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/completers.py +103 -3
  24. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/event_handler.py +7 -3
  25. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/input_prompt_toolkit.py +42 -3
  26. klaude_code-1.2.23/src/klaude_code/ui/renderers/__init__.py +0 -0
  27. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/assistant.py +7 -2
  28. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/developer.py +12 -0
  29. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/diffs.py +1 -1
  30. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/metadata.py +4 -2
  31. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/thinking.py +1 -1
  32. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/tools.py +57 -32
  33. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/user_input.py +32 -2
  34. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/markdown.py +22 -17
  35. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/status.py +1 -13
  36. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/theme.py +7 -5
  37. klaude_code-1.2.22/src/klaude_code/command/prompt-deslop.md +0 -14
  38. klaude_code-1.2.22/src/klaude_code/command/prompt-dev-docs-update.md +0 -56
  39. klaude_code-1.2.22/src/klaude_code/command/prompt-dev-docs.md +0 -46
  40. klaude_code-1.2.22/src/klaude_code/command/prompt-handoff.md +0 -33
  41. klaude_code-1.2.22/src/klaude_code/command/prompt-jj-workspace.md +0 -18
  42. klaude_code-1.2.22/src/klaude_code/core/tool/memory/__init__.py +0 -5
  43. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/__init__.py +0 -0
  44. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/auth/__init__.py +0 -0
  45. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/auth/codex/__init__.py +0 -0
  46. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/auth/codex/exceptions.py +0 -0
  47. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  48. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/auth/codex/oauth.py +0 -0
  49. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/auth/codex/token_manager.py +0 -0
  50. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/__init__.py +0 -0
  51. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/auth_cmd.py +0 -0
  52. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/config_cmd.py +0 -0
  53. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/debug.py +0 -0
  54. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/list_model.py +0 -0
  55. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/main.py +0 -0
  56. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/runtime.py +0 -0
  57. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/self_update.py +0 -0
  58. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/cli/session_cmd.py +0 -0
  59. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/__init__.py +0 -0
  60. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/clear_cmd.py +0 -0
  61. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/command_abc.py +0 -0
  62. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/debug_cmd.py +0 -0
  63. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/export_cmd.py +0 -0
  64. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/export_online_cmd.py +0 -0
  65. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/help_cmd.py +0 -0
  66. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/model_cmd.py +0 -0
  67. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/prompt-init.md +0 -0
  68. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/prompt_command.py +0 -0
  69. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/refresh_cmd.py +0 -0
  70. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/registry.py +0 -0
  71. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/release_notes_cmd.py +0 -0
  72. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/terminal_setup_cmd.py +0 -0
  73. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/command/thinking_cmd.py +0 -0
  74. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/config/__init__.py +0 -0
  75. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/config/config.py +0 -0
  76. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/config/select_model.py +0 -0
  77. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/__init__.py +0 -0
  78. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/agent.py +0 -0
  79. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/executor.py +0 -0
  80. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/manager/__init__.py +0 -0
  81. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/manager/llm_clients.py +0 -0
  82. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
  83. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompt.py +0 -0
  84. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
  85. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
  86. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
  87. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
  88. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
  89. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
  90. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
  91. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-sub-agent-oracle.md +0 -0
  92. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +0 -0
  93. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  94. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/__init__.py +0 -0
  95. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/_utils.py +0 -0
  96. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  97. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  98. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
  99. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/diff_builder.py +0 -0
  100. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  101. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
  102. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/read_tool.md +0 -0
  103. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/read_tool.py +0 -0
  104. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  105. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/file/write_tool.py +0 -0
  106. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/report_back_tool.py +0 -0
  107. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  108. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  109. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
  110. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  111. {klaude_code-1.2.22/src/klaude_code/core/tool/todo → klaude_code-1.2.23/src/klaude_code/core/tool/skill}/__init__.py +0 -0
  112. {klaude_code-1.2.22/src/klaude_code/core/tool/memory → klaude_code-1.2.23/src/klaude_code/core/tool/skill}/skill_tool.md +0 -0
  113. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/sub_agent_tool.py +0 -0
  114. {klaude_code-1.2.22/src/klaude_code/core/tool/web → klaude_code-1.2.23/src/klaude_code/core/tool/todo}/__init__.py +0 -0
  115. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  116. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
  117. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  118. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  119. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
  120. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/tool_abc.py +0 -0
  121. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/tool_context.py +0 -0
  122. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/tool_registry.py +0 -0
  123. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/tool_runner.py +0 -0
  124. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/truncation.py +0 -0
  125. {klaude_code-1.2.22/src/klaude_code/ui/renderers → klaude_code-1.2.23/src/klaude_code/core/tool/web}/__init__.py +0 -0
  126. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
  127. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
  128. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
  129. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/web/web_fetch_tool.py +0 -0
  130. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  131. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
  132. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/core/turn.py +0 -0
  133. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/__init__.py +0 -0
  134. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  135. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/anthropic/client.py +0 -0
  136. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/anthropic/input.py +0 -0
  137. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/client.py +0 -0
  138. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/codex/__init__.py +0 -0
  139. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/codex/client.py +0 -0
  140. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/input_common.py +0 -0
  141. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  142. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openai_compatible/client.py +0 -0
  143. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openai_compatible/input.py +0 -0
  144. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openai_compatible/stream_processor.py +0 -0
  145. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
  146. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  147. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openrouter/client.py +0 -0
  148. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openrouter/input.py +0 -0
  149. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/openrouter/reasoning_handler.py +0 -0
  150. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/registry.py +0 -0
  151. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/responses/__init__.py +0 -0
  152. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/responses/client.py +0 -0
  153. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/responses/input.py +0 -0
  154. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/llm/usage.py +0 -0
  155. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/__init__.py +0 -0
  156. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/commands.py +0 -0
  157. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/events.py +0 -0
  158. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/llm_param.py +0 -0
  159. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/op.py +0 -0
  160. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/op_handler.py +0 -0
  161. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
  162. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
  163. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/sub_agent/oracle.py +0 -0
  164. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/sub_agent/task.py +0 -0
  165. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/sub_agent/web.py +0 -0
  166. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/protocol/tools.py +0 -0
  167. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/__init__.py +0 -0
  168. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/codec.py +0 -0
  169. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/selector.py +0 -0
  170. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/session.py +0 -0
  171. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/session/templates/export_session.html +0 -0
  172. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/trace/__init__.py +0 -0
  173. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/trace/log.py +0 -0
  174. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/__init__.py +0 -0
  175. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/core/__init__.py +0 -0
  176. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/core/display.py +0 -0
  177. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/core/input.py +0 -0
  178. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/core/stage_manager.py +0 -0
  179. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/__init__.py +0 -0
  180. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/debug/__init__.py +0 -0
  181. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/debug/display.py +0 -0
  182. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/exec/__init__.py +0 -0
  183. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/exec/display.py +0 -0
  184. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/__init__.py +0 -0
  185. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/clipboard.py +0 -0
  186. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/display.py +0 -0
  187. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/key_bindings.py +0 -0
  188. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/modes/repl/renderer.py +0 -0
  189. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/common.py +0 -0
  190. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/errors.py +0 -0
  191. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/renderers/sub_agent.py +0 -0
  192. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/__init__.py +0 -0
  193. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/cjk_wrap.py +0 -0
  194. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/code_panel.py +0 -0
  195. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/live.py +0 -0
  196. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/quote.py +0 -0
  197. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/rich/searchable_text.py +0 -0
  198. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/terminal/__init__.py +0 -0
  199. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/terminal/color.py +0 -0
  200. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/terminal/control.py +0 -0
  201. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/terminal/notifier.py +0 -0
  202. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/terminal/progress_bar.py +0 -0
  203. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/utils/__init__.py +0 -0
  204. {klaude_code-1.2.22 → klaude_code-1.2.23}/src/klaude_code/ui/utils/common.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 1.2.22
3
+ Version: 1.2.23
4
4
  Summary: Add your description here
5
5
  Requires-Dist: anthropic>=0.66.0
6
6
  Requires-Dist: chardet>=5.2.0
@@ -18,18 +18,23 @@ Requires-Dist: typer>=0.17.3
18
18
  Requires-Python: >=3.13
19
19
  Description-Content-Type: text/markdown
20
20
 
21
- # Minimal Code Agent CLI (Klaude Code)
22
-
23
- An minimal and opinionated code agent with multi-model support.
24
-
25
- ## Key Features
26
- - **Adaptive Tooling**: Model-aware toolsets (Claude Code tools for Sonnet, Codex `apply_patch` for GPT-5.1/Codex).
27
- - **Multi-Provider Support**: Compatible with `anthropic-messages-api`,`openai-responses-api`, and `openai-compatible-api`(`openrouter-api`), featuring interleaved thinking, OpenRouter's provider sorting etc.
28
- - **Structured Sub-Agent Output**: Main agent defines output JSON schema for sub-agents; sub-agents use `report_back` tool with constrained decoding to return schema-compliant structured data.
29
- - **Skill System**: Extensible support for loading Claude Skills.
30
- - **Session Management**: Robust context preservation with resumable sessions (`--continue`).
31
- - **Simple TUI**: Clean interface offering full visibility into model responses, reasoning and actions.
32
- - **Core Utilities**: Slash commands, sub-agents, image pasting, terminal notifications, file mentioning, and auto-theming.
21
+ # Klaude Code
22
+
23
+ Multi-model code agent CLI.
24
+
25
+ ## Features
26
+ - **Multi-provider**: Anthropic, OpenAI Responses API, OpenRouter
27
+ - **Keep reasoning item in context**: Interleaved thinking support
28
+ - **Model-aware tools**: Claude Code tools for Sonnet, `apply_patch` for GPT-5/Codex
29
+ - **Structured sub-agent output**: Define JSON schema, get schema-compliant responses via constrained decoding
30
+ - **Recursive `@file` mentions**: Circular dependency protection, relative path resolution
31
+ - **Reminders**: Cooldown-based todo tracking and instruction reinforcement
32
+ - **External file sync**: Monitoring for external edits (linter, manual)
33
+ - **Interrupt handling**: Ctrl+C preserves partial responses and synthesizes tool cancellation results
34
+ - **Output truncation**: Large outputs saved to file system with snapshot links
35
+ - **Skills**: Built-in + user + project Agent Skills (with implicit invocation by Skill tool or explicit invocation by typing `$`)
36
+ - **Sessions**: Resumable with `--continue`
37
+ - **Extras**: Slash commands, sub-agents, image paste, terminal notifications, auto-theming
33
38
 
34
39
  ## Installation
35
40
 
@@ -1,15 +1,20 @@
1
- # Minimal Code Agent CLI (Klaude Code)
2
-
3
- An minimal and opinionated code agent with multi-model support.
4
-
5
- ## Key Features
6
- - **Adaptive Tooling**: Model-aware toolsets (Claude Code tools for Sonnet, Codex `apply_patch` for GPT-5.1/Codex).
7
- - **Multi-Provider Support**: Compatible with `anthropic-messages-api`,`openai-responses-api`, and `openai-compatible-api`(`openrouter-api`), featuring interleaved thinking, OpenRouter's provider sorting etc.
8
- - **Structured Sub-Agent Output**: Main agent defines output JSON schema for sub-agents; sub-agents use `report_back` tool with constrained decoding to return schema-compliant structured data.
9
- - **Skill System**: Extensible support for loading Claude Skills.
10
- - **Session Management**: Robust context preservation with resumable sessions (`--continue`).
11
- - **Simple TUI**: Clean interface offering full visibility into model responses, reasoning and actions.
12
- - **Core Utilities**: Slash commands, sub-agents, image pasting, terminal notifications, file mentioning, and auto-theming.
1
+ # Klaude Code
2
+
3
+ Multi-model code agent CLI.
4
+
5
+ ## Features
6
+ - **Multi-provider**: Anthropic, OpenAI Responses API, OpenRouter
7
+ - **Keep reasoning item in context**: Interleaved thinking support
8
+ - **Model-aware tools**: Claude Code tools for Sonnet, `apply_patch` for GPT-5/Codex
9
+ - **Structured sub-agent output**: Define JSON schema, get schema-compliant responses via constrained decoding
10
+ - **Recursive `@file` mentions**: Circular dependency protection, relative path resolution
11
+ - **Reminders**: Cooldown-based todo tracking and instruction reinforcement
12
+ - **External file sync**: Monitoring for external edits (linter, manual)
13
+ - **Interrupt handling**: Ctrl+C preserves partial responses and synthesizes tool cancellation results
14
+ - **Output truncation**: Large outputs saved to file system with snapshot links
15
+ - **Skills**: Built-in + user + project Agent Skills (with implicit invocation by Skill tool or explicit invocation by typing `$`)
16
+ - **Sessions**: Resumable with `--continue`
17
+ - **Extras**: Slash commands, sub-agents, image paste, terminal notifications, auto-theming
13
18
 
14
19
  ## Installation
15
20
 
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "klaude-code"
7
- version = "1.2.22"
7
+ version = "1.2.23"
8
8
  description = "Add your description here"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -81,6 +81,7 @@ layers = [
81
81
  "klaude_code.cli",
82
82
  "klaude_code.ui",
83
83
  "klaude_code.core",
84
+ "klaude_code.skill",
84
85
  "klaude_code.command",
85
86
  "klaude_code.session",
86
87
  "klaude_code.config",
@@ -22,7 +22,7 @@ def accumulate_session_usage(session: Session) -> AggregatedUsage:
22
22
  for item in session.conversation_history:
23
23
  if isinstance(item, model.TaskMetadataItem):
24
24
  task_count += 1
25
- all_metadata.append(item.main)
25
+ all_metadata.append(item.main_agent)
26
26
  all_metadata.extend(item.sub_agent_task_metadata)
27
27
 
28
28
  # Aggregate by model+provider
@@ -90,10 +90,10 @@ INVALID_TOOL_CALL_MAX_LENGTH = 500
90
90
  TRUNCATE_DISPLAY_MAX_LINE_LENGTH = 1000
91
91
 
92
92
  # Maximum lines for truncated display output
93
- TRUNCATE_DISPLAY_MAX_LINES = 20
93
+ TRUNCATE_DISPLAY_MAX_LINES = 8
94
94
 
95
95
  # Maximum lines for sub-agent result display
96
- SUB_AGENT_RESULT_MAX_LINES = 12
96
+ SUB_AGENT_RESULT_MAX_LINES = 20
97
97
 
98
98
 
99
99
  # UI refresh rate (frames per second) for debounced content streaming
@@ -102,6 +102,12 @@ UI_REFRESH_RATE_FPS = 20
102
102
  # Number of lines to keep visible at bottom of markdown streaming window
103
103
  MARKDOWN_STREAM_LIVE_WINDOW = 6
104
104
 
105
+ # Left margin (columns) to reserve when rendering markdown
106
+ MARKDOWN_LEFT_MARGIN = 2
107
+
108
+ # Right margin (columns) to reserve when rendering markdown
109
+ MARKDOWN_RIGHT_MARGIN = 2
110
+
105
111
  # Status hint text shown after spinner status
106
112
  STATUS_HINT_TEXT = " (esc to interrupt)"
107
113
 
@@ -89,7 +89,7 @@ Only the content passed to `report_back` will be returned to user.\
89
89
  result = event.task_result
90
90
  # Capture TaskMetadataEvent for metadata propagation
91
91
  elif isinstance(event, events.TaskMetadataEvent):
92
- task_metadata = event.metadata.main
92
+ task_metadata = event.metadata.main_agent
93
93
  await self.emit_event(event)
94
94
  return SubAgentResult(
95
95
  task_result=result,
@@ -12,6 +12,7 @@ from klaude_code.core.tool import BashTool, ReadTool, reset_tool_context, set_to
12
12
  from klaude_code.core.tool.file._utils import hash_text_sha256
13
13
  from klaude_code.protocol import model, tools
14
14
  from klaude_code.session import Session
15
+ from klaude_code.skill import get_skill
15
16
 
16
17
  type Reminder = Callable[[Session], Awaitable[model.DeveloperMessageItem | None]]
17
18
 
@@ -19,6 +20,9 @@ type Reminder = Callable[[Session], Awaitable[model.DeveloperMessageItem | None]
19
20
  # Match @ preceded by whitespace, start of line, or → (ReadTool line number arrow)
20
21
  AT_FILE_PATTERN = re.compile(r'(?:(?<!\S)|(?<=\u2192))@("(?P<quoted>[^\"]+)"|(?P<plain>\S+))')
21
22
 
23
+ # Match $skill or ¥skill at the beginning of the first line
24
+ SKILL_PATTERN = re.compile(r"^[$¥](?P<skill>\S+)")
25
+
22
26
 
23
27
  def get_last_new_user_input(session: Session) -> str | None:
24
28
  """Get last user input & developer message (CLAUDE.md) from conversation history. if there's a tool result after user input, return None"""
@@ -73,6 +77,21 @@ def get_at_patterns_with_source(session: Session) -> list[AtPatternSource]:
73
77
  return patterns
74
78
 
75
79
 
80
+ def get_skill_from_user_input(session: Session) -> str | None:
81
+ """Get $skill reference from the first line of last user input."""
82
+ for item in reversed(session.conversation_history):
83
+ if isinstance(item, model.ToolResultItem):
84
+ return None
85
+ if isinstance(item, model.UserMessageItem):
86
+ content = item.content or ""
87
+ first_line = content.split("\n", 1)[0]
88
+ m = SKILL_PATTERN.match(first_line)
89
+ if m:
90
+ return m.group("skill")
91
+ return None
92
+ return None
93
+
94
+
76
95
  async def _load_at_file_recursive(
77
96
  session: Session,
78
97
  pattern: str,
@@ -373,6 +392,36 @@ async def image_reminder(session: Session) -> model.DeveloperMessageItem | None:
373
392
  )
374
393
 
375
394
 
395
+ async def skill_reminder(session: Session) -> model.DeveloperMessageItem | None:
396
+ """Load skill content when user references a skill with $skill syntax."""
397
+ skill_name = get_skill_from_user_input(session)
398
+ if not skill_name:
399
+ return None
400
+
401
+ # Get the skill from skill module
402
+ skill = get_skill(skill_name)
403
+ if not skill:
404
+ return None
405
+
406
+ # Get base directory from skill_path
407
+ base_dir = str(skill.skill_path.parent) if skill.skill_path else "unknown"
408
+
409
+ content = f"""<system-reminder>The user activated the "{skill.name}" skill. Here is the skill content:
410
+
411
+ <skill>
412
+ <name>{skill.name}</name>
413
+ <base_dir>{base_dir}</base_dir>
414
+
415
+ {skill.to_prompt()}
416
+ </skill>
417
+ </system-reminder>"""
418
+
419
+ return model.DeveloperMessageItem(
420
+ content=content,
421
+ skill_name=skill.name,
422
+ )
423
+
424
+
376
425
  def _is_memory_loaded(session: Session, path: str) -> bool:
377
426
  """Check if a memory file has already been loaded (tracked with is_memory=True)."""
378
427
  status = session.file_tracker.get(path)
@@ -510,6 +559,7 @@ ALL_REMINDERS = [
510
559
  last_path_memory_reminder,
511
560
  at_file_reader_reminder,
512
561
  image_reminder,
562
+ skill_reminder,
513
563
  ]
514
564
 
515
565
 
@@ -540,6 +590,7 @@ def load_agent_reminders(
540
590
  last_path_memory_reminder,
541
591
  file_changed_externally_reminder,
542
592
  image_reminder,
593
+ skill_reminder,
543
594
  ]
544
595
  )
545
596
 
@@ -25,7 +25,7 @@ class MetadataAccumulator:
25
25
  """
26
26
 
27
27
  def __init__(self, model_name: str) -> None:
28
- self._main = model.TaskMetadata(model_name=model_name)
28
+ self._main_agent = model.TaskMetadata(model_name=model_name) # Main agent metadata
29
29
  self._sub_agent_metadata: list[model.TaskMetadata] = []
30
30
  self._throughput_weighted_sum: float = 0.0
31
31
  self._throughput_tracked_tokens: int = 0
@@ -36,13 +36,12 @@ class MetadataAccumulator:
36
36
  def add(self, turn_metadata: model.ResponseMetadataItem) -> None:
37
37
  """Merge a turn's metadata into the accumulated state."""
38
38
  self._turn_count += 1
39
- main = self._main
40
39
  usage = turn_metadata.usage
41
40
 
42
41
  if usage is not None:
43
- if main.usage is None:
44
- main.usage = model.Usage()
45
- acc_usage = main.usage
42
+ if self._main_agent.usage is None:
43
+ self._main_agent.usage = model.Usage()
44
+ acc_usage = self._main_agent.usage
46
45
 
47
46
  model.TaskMetadata.merge_usage(acc_usage, usage)
48
47
  acc_usage.currency = usage.currency
@@ -63,9 +62,9 @@ class MetadataAccumulator:
63
62
  self._throughput_tracked_tokens += current_output
64
63
 
65
64
  if turn_metadata.provider is not None:
66
- main.provider = turn_metadata.provider
65
+ self._main_agent.provider = turn_metadata.provider
67
66
  if turn_metadata.model_name:
68
- main.model_name = turn_metadata.model_name
67
+ self._main_agent.model_name = turn_metadata.model_name
69
68
 
70
69
  def add_sub_agent_metadata(self, sub_agent_metadata: model.TaskMetadata) -> None:
71
70
  """Add sub-agent task metadata to the accumulated state."""
@@ -73,21 +72,22 @@ class MetadataAccumulator:
73
72
 
74
73
  def finalize(self, task_duration_s: float) -> model.TaskMetadataItem:
75
74
  """Return the final accumulated metadata with computed throughput and duration."""
76
- main = self._main
77
- if main.usage is not None:
75
+ if self._main_agent.usage is not None:
78
76
  if self._throughput_tracked_tokens > 0:
79
- main.usage.throughput_tps = self._throughput_weighted_sum / self._throughput_tracked_tokens
77
+ self._main_agent.usage.throughput_tps = self._throughput_weighted_sum / self._throughput_tracked_tokens
80
78
  else:
81
- main.usage.throughput_tps = None
79
+ self._main_agent.usage.throughput_tps = None
82
80
 
83
81
  if self._first_token_latency_count > 0:
84
- main.usage.first_token_latency_ms = self._first_token_latency_sum / self._first_token_latency_count
82
+ self._main_agent.usage.first_token_latency_ms = (
83
+ self._first_token_latency_sum / self._first_token_latency_count
84
+ )
85
85
  else:
86
- main.usage.first_token_latency_ms = None
86
+ self._main_agent.usage.first_token_latency_ms = None
87
87
 
88
- main.task_duration_s = task_duration_s
89
- main.turn_count = self._turn_count
90
- return model.TaskMetadataItem(main=main, sub_agent_task_metadata=self._sub_agent_metadata)
88
+ self._main_agent.task_duration_s = task_duration_s
89
+ self._main_agent.turn_count = self._turn_count
90
+ return model.TaskMetadataItem(main_agent=self._main_agent, sub_agent_task_metadata=self._sub_agent_metadata)
91
91
 
92
92
 
93
93
  @dataclass
@@ -126,17 +126,28 @@ class TaskExecutor:
126
126
  self._context = context
127
127
  self._current_turn: TurnExecutor | None = None
128
128
  self._started_at: float = 0.0
129
+ self._metadata_accumulator: MetadataAccumulator | None = None
129
130
 
130
131
  @property
131
132
  def current_turn(self) -> TurnExecutor | None:
132
133
  return self._current_turn
133
134
 
134
135
  def cancel(self) -> list[events.Event]:
135
- """Cancel the current turn and return any resulting events."""
136
+ """Cancel the current turn and return any resulting events including metadata."""
136
137
  ui_events: list[events.Event] = []
137
138
  if self._current_turn is not None:
138
139
  ui_events.extend(self._current_turn.cancel())
139
140
  self._current_turn = None
141
+
142
+ # Emit partial metadata on cancellation
143
+ if self._metadata_accumulator is not None and self._started_at > 0:
144
+ task_duration_s = time.perf_counter() - self._started_at
145
+ accumulated = self._metadata_accumulator.finalize(task_duration_s)
146
+ if accumulated.main_agent.usage is not None:
147
+ session_id = self._context.session_ctx.session_id
148
+ ui_events.append(events.TaskMetadataEvent(metadata=accumulated, session_id=session_id))
149
+ self._context.session_ctx.append_history([accumulated])
150
+
140
151
  return ui_events
141
152
 
142
153
  async def run(self, user_input: model.UserInputPayload) -> AsyncGenerator[events.Event]:
@@ -152,7 +163,8 @@ class TaskExecutor:
152
163
  del user_input # Persisted by the operation handler before launching the task.
153
164
 
154
165
  profile = ctx.profile
155
- metadata_accumulator = MetadataAccumulator(model_name=profile.llm_client.model_name)
166
+ self._metadata_accumulator = MetadataAccumulator(model_name=profile.llm_client.model_name)
167
+ metadata_accumulator = self._metadata_accumulator
156
168
 
157
169
  while True:
158
170
  # Process reminders at the start of each turn
@@ -226,6 +238,13 @@ class TaskExecutor:
226
238
  return
227
239
 
228
240
  if turn is None or turn.task_finished:
241
+ # Sub-agent with empty result should retry instead of finishing
242
+ if ctx.sub_agent_state is not None and turn is not None and not turn.task_result.strip():
243
+ yield events.ErrorEvent(
244
+ error_message="Sub-agent returned empty result, retrying...",
245
+ can_retry=True,
246
+ )
247
+ continue
229
248
  break
230
249
 
231
250
  # Finalize metadata
@@ -3,11 +3,10 @@ from .file.apply_patch_tool import ApplyPatchTool
3
3
  from .file.edit_tool import EditTool
4
4
  from .file.read_tool import ReadTool
5
5
  from .file.write_tool import WriteTool
6
- from .memory.skill_loader import Skill, SkillLoader
7
- from .memory.skill_tool import SkillTool
8
6
  from .report_back_tool import ReportBackTool
9
7
  from .shell.bash_tool import BashTool
10
8
  from .shell.command_safety import SafetyCheckResult, is_safe_command
9
+ from .skill.skill_tool import SkillTool
11
10
  from .sub_agent_tool import SubAgentTool
12
11
  from .todo.todo_write_tool import TodoWriteTool
13
12
  from .todo.update_plan_tool import UpdatePlanTool
@@ -40,8 +39,6 @@ __all__ = [
40
39
  "ReportBackTool",
41
40
  "SafetyCheckResult",
42
41
  "SimpleTruncationStrategy",
43
- "Skill",
44
- "SkillLoader",
45
42
  "SkillTool",
46
43
  "SubAgentTool",
47
44
  "TodoContext",
@@ -1,38 +1,22 @@
1
+ """SkillTool - Tool for agent to activate and load skills."""
2
+
1
3
  from pathlib import Path
2
4
 
3
5
  from pydantic import BaseModel
4
6
 
5
- from klaude_code.core.tool.memory.skill_loader import SkillLoader
6
7
  from klaude_code.core.tool.tool_abc import ToolABC, load_desc
7
8
  from klaude_code.core.tool.tool_registry import register
8
9
  from klaude_code.protocol import llm_param, model, tools
10
+ from klaude_code.skill import get_available_skills, get_skill, list_skill_names
9
11
 
10
12
 
11
13
  @register(tools.SKILL)
12
14
  class SkillTool(ToolABC):
13
- """Tool to execute/load a skill within the main conversation"""
14
-
15
- _skill_loader: SkillLoader | None = None
16
- _discovery_done: bool = False
17
-
18
- @classmethod
19
- def set_skill_loader(cls, loader: SkillLoader) -> None:
20
- """Set the skill loader instance"""
21
- cls._skill_loader = loader
22
- cls._discovery_done = False
23
-
24
- @classmethod
25
- def _ensure_skills_discovered(cls) -> None:
26
- if cls._discovery_done:
27
- return
28
- if cls._skill_loader is not None:
29
- cls._skill_loader.discover_skills()
30
- cls._discovery_done = True
15
+ """Tool to execute/load a skill within the main conversation."""
31
16
 
32
17
  @classmethod
33
18
  def schema(cls) -> llm_param.ToolSchema:
34
- """Generate schema with embedded available skills metadata"""
35
- cls._ensure_skills_discovered()
19
+ """Generate schema with embedded available skills metadata."""
36
20
  skills_xml = cls._generate_skills_xml()
37
21
 
38
22
  return llm_param.ToolSchema(
@@ -53,16 +37,17 @@ class SkillTool(ToolABC):
53
37
 
54
38
  @classmethod
55
39
  def _generate_skills_xml(cls) -> str:
56
- """Generate XML format skills metadata"""
57
- if not cls._skill_loader:
40
+ """Generate XML format skills metadata."""
41
+ skills = get_available_skills()
42
+ if not skills:
58
43
  return ""
59
44
 
60
45
  xml_parts: list[str] = []
61
- for skill in cls._skill_loader.loaded_skills.values():
46
+ for name, description, location in skills:
62
47
  xml_parts.append(f"""<skill>
63
- <name>{skill.name}</name>
64
- <description>{skill.description}</description>
65
- <location>{skill.location}</location>
48
+ <name>{name}</name>
49
+ <description>{description}</description>
50
+ <location>{location}</location>
66
51
  </skill>""")
67
52
  return "\n".join(xml_parts)
68
53
 
@@ -71,7 +56,7 @@ class SkillTool(ToolABC):
71
56
 
72
57
  @classmethod
73
58
  async def call(cls, arguments: str) -> model.ToolResultItem:
74
- """Load and return full skill content"""
59
+ """Load and return full skill content."""
75
60
  try:
76
61
  args = cls.SkillArguments.model_validate_json(arguments)
77
62
  except ValueError as e:
@@ -80,18 +65,10 @@ class SkillTool(ToolABC):
80
65
  output=f"Invalid arguments: {e}",
81
66
  )
82
67
 
83
- cls._ensure_skills_discovered()
84
-
85
- if not cls._skill_loader:
86
- return model.ToolResultItem(
87
- status="error",
88
- output="Skill loader not initialized",
89
- )
90
-
91
- skill = cls._skill_loader.get_skill(args.command)
68
+ skill = get_skill(args.command)
92
69
 
93
70
  if not skill:
94
- available = ", ".join(cls._skill_loader.list_skills())
71
+ available = ", ".join(list_skill_names())
95
72
  return model.ToolResultItem(
96
73
  status="error",
97
74
  output=f"Skill '{args.command}' does not exist. Available skills: {available}",
@@ -101,7 +78,7 @@ class SkillTool(ToolABC):
101
78
  base_dir = str(skill.skill_path.parent) if skill.skill_path else "unknown"
102
79
 
103
80
  # Return with loading message format
104
- result = f"""<command-message>The "{skill.name}" skill is running</command-message>
81
+ result = f"""<command-message>The "{skill.name}" skill is activated</command-message>
105
82
  <command-name>{skill.name}</command-name>
106
83
 
107
84
  Base directory for this skill: {base_dir}
@@ -230,6 +230,7 @@ class DeveloperMessageItem(BaseModel):
230
230
  at_files: list[AtPatternParseResult] | None = None
231
231
  command_output: CommandOutput | None = None
232
232
  user_image_count: int | None = None
233
+ skill_name: str | None = None # Skill name activated via $skill syntax
233
234
 
234
235
 
235
236
  class ImageURLPart(BaseModel):
@@ -417,7 +418,7 @@ class TaskMetadata(BaseModel):
417
418
  class TaskMetadataItem(BaseModel):
418
419
  """Aggregated metadata for a complete task, stored in conversation history."""
419
420
 
420
- main: TaskMetadata = Field(default_factory=TaskMetadata)
421
+ main_agent: TaskMetadata = Field(default_factory=TaskMetadata) # Main agent metadata
421
422
  sub_agent_task_metadata: list[TaskMetadata] = Field(default_factory=lambda: list[TaskMetadata]())
422
423
  created_at: datetime = Field(default_factory=datetime.now)
423
424
 
@@ -235,7 +235,7 @@ def _render_metadata_item(item: model.TaskMetadataItem) -> str:
235
235
  lines: list[str] = []
236
236
 
237
237
  # Main agent metadata
238
- lines.append(_render_single_metadata(item.main, indent=0, show_context=True))
238
+ lines.append(_render_single_metadata(item.main_agent, indent=0, show_context=True))
239
239
 
240
240
  # Sub-agent metadata with indent
241
241
  for sub in item.sub_agent_task_metadata:
@@ -205,11 +205,13 @@ def build_meta_snapshot(
205
205
  "work_dir": str(work_dir),
206
206
  "sub_agent_state": sub_agent_state.model_dump(mode="json") if sub_agent_state else None,
207
207
  "file_tracker": {path: status.model_dump(mode="json") for path, status in file_tracker.items()},
208
- "todos": [todo.model_dump(mode="json") for todo in todos],
208
+ "todos": [todo.model_dump(mode="json", exclude_defaults=True) for todo in todos],
209
209
  "created_at": created_at,
210
210
  "updated_at": updated_at,
211
211
  "messages_count": messages_count,
212
212
  "model_name": model_name,
213
213
  "model_config_name": model_config_name,
214
- "model_thinking": model_thinking.model_dump(mode="json") if model_thinking else None,
214
+ "model_thinking": model_thinking.model_dump(mode="json", exclude_defaults=True, exclude_none=True)
215
+ if model_thinking
216
+ else None,
215
217
  }
@@ -0,0 +1,27 @@
1
+ """Skill module - independent skill management system.
2
+
3
+ This module provides the core skill functionality:
4
+ - Skill discovery and loading from multiple directories
5
+ - System skill installation
6
+ - Global skill access via manager functions
7
+
8
+ Public API:
9
+ - get_skill(name) - Get a skill by name
10
+ - get_available_skills() - Get list of (name, description, location) tuples
11
+ - get_skill_loader() - Get the global SkillLoader instance
12
+ - list_skill_names() - Get list of skill names
13
+ - Skill - Skill data class
14
+ - SkillLoader - Skill loader class
15
+ """
16
+
17
+ from klaude_code.skill.loader import Skill, SkillLoader
18
+ from klaude_code.skill.manager import get_available_skills, get_skill, get_skill_loader, list_skill_names
19
+
20
+ __all__ = [
21
+ "Skill",
22
+ "SkillLoader",
23
+ "get_available_skills",
24
+ "get_skill",
25
+ "get_skill_loader",
26
+ "list_skill_names",
27
+ ]
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: deslop
3
+ description: Remove AI-generated code slop from files or diffs. Use this skill when reviewing AI-generated code to clean up unnecessary comments, defensive code, type hacks, and style inconsistencies. Triggers include "deslop", "remove slop", "clean up AI code", "review for slop".
4
+ metadata:
5
+ short-description: Remove AI code slop
6
+ ---
7
+
8
+ # Deslop
9
+
10
+ Remove AI-generated slop from code. Check the specified files or diff and remove:
11
+
12
+ - Extra comments that a human wouldn't add or are inconsistent with the rest of the file
13
+ - Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted/validated codepaths)
14
+ - Casts to `any` or `# type: ignore` to get around type issues
15
+ - Any other style that is inconsistent with the file
16
+
17
+ Report at the end with only a 1-3 sentence summary of what you changed.