klaude-code 1.2.10__py3-none-any.whl → 1.2.11__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/cli/main.py +2 -7
- klaude_code/cli/runtime.py +23 -19
- klaude_code/core/agent.py +7 -0
- klaude_code/core/executor.py +1 -4
- klaude_code/core/manager/agent_manager.py +15 -9
- klaude_code/core/manager/llm_clients_builder.py +4 -7
- klaude_code/core/prompt.py +4 -4
- klaude_code/core/prompts/prompt-claude-code.md +1 -12
- klaude_code/core/prompts/prompt-minimal.md +12 -0
- klaude_code/core/task.py +4 -0
- klaude_code/core/tool/memory/memory_tool.md +4 -0
- klaude_code/core/tool/memory/skill_loader.py +1 -1
- klaude_code/core/tool/todo/todo_write_tool.md +0 -157
- klaude_code/core/tool/todo/todo_write_tool_raw.md +182 -0
- klaude_code/core/tool/tool_registry.py +3 -4
- klaude_code/llm/client.py +1 -1
- klaude_code/protocol/model.py +3 -0
- klaude_code/protocol/op.py +5 -2
- klaude_code/protocol/sub_agent.py +1 -0
- klaude_code/session/export.py +11 -1
- klaude_code/session/session.py +1 -5
- klaude_code/session/templates/export_session.html +155 -0
- klaude_code/ui/modes/repl/event_handler.py +1 -5
- klaude_code/ui/modes/repl/input_prompt_toolkit.py +3 -34
- klaude_code/ui/renderers/metadata.py +21 -0
- klaude_code/ui/renderers/tools.py +13 -2
- klaude_code/ui/rich/markdown.py +4 -1
- klaude_code/ui/terminal/__init__.py +55 -0
- {klaude_code-1.2.10.dist-info → klaude_code-1.2.11.dist-info}/METADATA +1 -4
- {klaude_code-1.2.10.dist-info → klaude_code-1.2.11.dist-info}/RECORD +32 -30
- {klaude_code-1.2.10.dist-info → klaude_code-1.2.11.dist-info}/WHEEL +0 -0
- {klaude_code-1.2.10.dist-info → klaude_code-1.2.11.dist-info}/entry_points.txt +0 -0
klaude_code/cli/main.py
CHANGED
|
@@ -3,7 +3,6 @@ import datetime
|
|
|
3
3
|
import os
|
|
4
4
|
import subprocess
|
|
5
5
|
import sys
|
|
6
|
-
import uuid
|
|
7
6
|
from importlib.metadata import PackageNotFoundError
|
|
8
7
|
from importlib.metadata import version as pkg_version
|
|
9
8
|
|
|
@@ -340,8 +339,8 @@ def main_callback(
|
|
|
340
339
|
return
|
|
341
340
|
|
|
342
341
|
# Resolve session id before entering asyncio loop
|
|
342
|
+
# session_id=None means create a new session
|
|
343
343
|
session_id: str | None = None
|
|
344
|
-
is_new_session = False
|
|
345
344
|
if resume:
|
|
346
345
|
session_id = resume_select_session()
|
|
347
346
|
if session_id is None:
|
|
@@ -349,10 +348,7 @@ def main_callback(
|
|
|
349
348
|
# If user didn't pick, allow fallback to --continue
|
|
350
349
|
if session_id is None and continue_:
|
|
351
350
|
session_id = Session.most_recent_session_id()
|
|
352
|
-
# If still no session_id,
|
|
353
|
-
if session_id is None:
|
|
354
|
-
session_id = uuid.uuid4().hex
|
|
355
|
-
is_new_session = True
|
|
351
|
+
# If still no session_id, leave as None to create a new session
|
|
356
352
|
|
|
357
353
|
debug_enabled, debug_filters = resolve_debug_settings(debug, debug_filter)
|
|
358
354
|
|
|
@@ -367,6 +363,5 @@ def main_callback(
|
|
|
367
363
|
run_interactive(
|
|
368
364
|
init_config=init_config,
|
|
369
365
|
session_id=session_id,
|
|
370
|
-
is_new_session=is_new_session,
|
|
371
366
|
)
|
|
372
367
|
)
|
klaude_code/cli/runtime.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import sys
|
|
3
|
-
import uuid
|
|
4
3
|
from dataclasses import dataclass
|
|
5
4
|
from typing import Any, Protocol
|
|
6
5
|
|
|
@@ -15,7 +14,6 @@ from klaude_code.core.executor import Executor
|
|
|
15
14
|
from klaude_code.core.manager import build_llm_clients
|
|
16
15
|
from klaude_code.protocol import events, op
|
|
17
16
|
from klaude_code.protocol.model import UserInputPayload
|
|
18
|
-
from klaude_code.protocol.sub_agent import iter_sub_agent_profiles
|
|
19
17
|
from klaude_code.trace import DebugType, log, set_debug_logging
|
|
20
18
|
from klaude_code.ui.modes.repl import build_repl_status_snapshot
|
|
21
19
|
from klaude_code.ui.modes.repl.input_prompt_toolkit import REPLStatusSnapshot
|
|
@@ -97,11 +95,9 @@ async def initialize_app_components(init_config: AppInitConfig) -> AppComponents
|
|
|
97
95
|
|
|
98
96
|
# Initialize LLM clients
|
|
99
97
|
try:
|
|
100
|
-
enabled_sub_agents = [p.name for p in iter_sub_agent_profiles()]
|
|
101
98
|
llm_clients = build_llm_clients(
|
|
102
99
|
config,
|
|
103
100
|
model_override=init_config.model,
|
|
104
|
-
enabled_sub_agents=enabled_sub_agents,
|
|
105
101
|
)
|
|
106
102
|
except ValueError as exc:
|
|
107
103
|
if init_config.model:
|
|
@@ -207,12 +203,14 @@ async def run_exec(init_config: AppInitConfig, input_content: str) -> None:
|
|
|
207
203
|
components = await initialize_app_components(init_config)
|
|
208
204
|
|
|
209
205
|
try:
|
|
210
|
-
#
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
await components.executor.submit_and_wait(op.InitAgentOperation(session_id=session_id, is_new_session=True))
|
|
206
|
+
# Initialize a new session (session_id=None means create new)
|
|
207
|
+
await components.executor.submit_and_wait(op.InitAgentOperation())
|
|
214
208
|
await components.event_queue.join()
|
|
215
209
|
|
|
210
|
+
# Get the session_id from the newly created agent
|
|
211
|
+
session_ids = components.executor.context.agent_manager.active_session_ids()
|
|
212
|
+
session_id = session_ids[0] if session_ids else None
|
|
213
|
+
|
|
216
214
|
# Submit the input content directly
|
|
217
215
|
await components.executor.submit_and_wait(
|
|
218
216
|
op.UserInputOperation(input=UserInputPayload(text=input_content), session_id=session_id)
|
|
@@ -224,11 +222,12 @@ async def run_exec(init_config: AppInitConfig, input_content: str) -> None:
|
|
|
224
222
|
await cleanup_app_components(components)
|
|
225
223
|
|
|
226
224
|
|
|
227
|
-
async def run_interactive(
|
|
228
|
-
|
|
229
|
-
) -> None:
|
|
230
|
-
"""Run the interactive REPL using the provided configuration."""
|
|
225
|
+
async def run_interactive(init_config: AppInitConfig, session_id: str | None = None) -> None:
|
|
226
|
+
"""Run the interactive REPL using the provided configuration.
|
|
231
227
|
|
|
228
|
+
If session_id is None, a new session is created with an auto-generated ID.
|
|
229
|
+
If session_id is provided, attempts to resume that session.
|
|
230
|
+
"""
|
|
232
231
|
components = await initialize_app_components(init_config)
|
|
233
232
|
|
|
234
233
|
# No theme persistence from CLI anymore; config.theme controls theme when set.
|
|
@@ -236,8 +235,10 @@ async def run_interactive(
|
|
|
236
235
|
# Create status provider for bottom toolbar
|
|
237
236
|
def _status_provider() -> REPLStatusSnapshot:
|
|
238
237
|
agent: Agent | None = None
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
# Get the first active agent (there should only be one in interactive mode)
|
|
239
|
+
active_agents = components.executor.context.active_agents
|
|
240
|
+
if active_agents:
|
|
241
|
+
agent = next(iter(active_agents.values()), None)
|
|
241
242
|
|
|
242
243
|
# Check for updates (returns None if uv not available)
|
|
243
244
|
update_message = get_update_message()
|
|
@@ -279,10 +280,13 @@ async def run_interactive(
|
|
|
279
280
|
restore_sigint = install_sigint_double_press_exit(_show_toast_once, _hide_progress)
|
|
280
281
|
|
|
281
282
|
try:
|
|
282
|
-
await components.executor.submit_and_wait(
|
|
283
|
-
op.InitAgentOperation(session_id=session_id, is_new_session=is_new_session)
|
|
284
|
-
)
|
|
283
|
+
await components.executor.submit_and_wait(op.InitAgentOperation(session_id=session_id))
|
|
285
284
|
await components.event_queue.join()
|
|
285
|
+
|
|
286
|
+
# Get the actual session_id (may have been auto-generated if None was passed)
|
|
287
|
+
active_session_ids = components.executor.context.agent_manager.active_session_ids()
|
|
288
|
+
active_session_id = active_session_ids[0] if active_session_ids else session_id
|
|
289
|
+
|
|
286
290
|
# Input
|
|
287
291
|
await input_provider.start()
|
|
288
292
|
async for user_input in input_provider.iter_inputs():
|
|
@@ -293,7 +297,7 @@ async def run_interactive(
|
|
|
293
297
|
continue
|
|
294
298
|
# Submit user input operation - directly use the payload from iter_inputs
|
|
295
299
|
submission_id = await components.executor.submit(
|
|
296
|
-
op.UserInputOperation(input=user_input, session_id=
|
|
300
|
+
op.UserInputOperation(input=user_input, session_id=active_session_id)
|
|
297
301
|
)
|
|
298
302
|
# If it's an interactive command (e.g., /model), avoid starting the ESC monitor
|
|
299
303
|
# to prevent TTY conflicts with interactive prompts (questionary/prompt_toolkit).
|
|
@@ -302,7 +306,7 @@ async def run_interactive(
|
|
|
302
306
|
else:
|
|
303
307
|
# Esc monitor for long-running, interruptible operations
|
|
304
308
|
async def _on_esc_interrupt() -> None:
|
|
305
|
-
await components.executor.submit(op.InterruptOperation(target_session_id=
|
|
309
|
+
await components.executor.submit(op.InterruptOperation(target_session_id=active_session_id))
|
|
306
310
|
|
|
307
311
|
stop_event, esc_task = start_esc_interrupt_monitor(_on_esc_interrupt)
|
|
308
312
|
# Wait for this specific task to complete before accepting next input
|
klaude_code/core/agent.py
CHANGED
|
@@ -122,6 +122,7 @@ class Agent:
|
|
|
122
122
|
self.session: Session = session
|
|
123
123
|
self.profile: AgentProfile = profile
|
|
124
124
|
self._current_task: TaskExecutor | None = None
|
|
125
|
+
self._prev_context_token: int = 0 # Track context size from previous task for delta calculation
|
|
125
126
|
if not self.session.model_name and model_name:
|
|
126
127
|
self.session.model_name = model_name
|
|
127
128
|
|
|
@@ -169,6 +170,12 @@ class Agent:
|
|
|
169
170
|
|
|
170
171
|
try:
|
|
171
172
|
async for event in task.run(user_input):
|
|
173
|
+
# Compute context_delta for TaskMetadataEvent
|
|
174
|
+
if isinstance(event, events.TaskMetadataEvent):
|
|
175
|
+
usage = event.metadata.main.usage
|
|
176
|
+
if usage is not None and usage.context_token is not None:
|
|
177
|
+
usage.context_delta = usage.context_token - self._prev_context_token
|
|
178
|
+
self._prev_context_token = usage.context_token
|
|
172
179
|
yield event
|
|
173
180
|
finally:
|
|
174
181
|
self._current_task = None
|
klaude_code/core/executor.py
CHANGED
|
@@ -114,10 +114,7 @@ class ExecutorContext:
|
|
|
114
114
|
|
|
115
115
|
async def handle_init_agent(self, operation: op.InitAgentOperation) -> None:
|
|
116
116
|
"""Initialize an agent for a session and replay history to UI."""
|
|
117
|
-
|
|
118
|
-
raise ValueError("session_id cannot be None")
|
|
119
|
-
|
|
120
|
-
await self.agent_manager.ensure_agent(operation.session_id, is_new_session=operation.is_new_session)
|
|
117
|
+
await self.agent_manager.ensure_agent(operation.session_id)
|
|
121
118
|
|
|
122
119
|
async def handle_user_input(self, operation: op.UserInputOperation) -> None:
|
|
123
120
|
"""Handle a user input operation by running it through an agent."""
|
|
@@ -38,13 +38,19 @@ class AgentManager:
|
|
|
38
38
|
|
|
39
39
|
await self._event_queue.put(event)
|
|
40
40
|
|
|
41
|
-
async def ensure_agent(self, session_id: str
|
|
42
|
-
"""Return an existing agent for the session or create a new one.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
async def ensure_agent(self, session_id: str | None = None) -> Agent:
|
|
42
|
+
"""Return an existing agent for the session or create a new one.
|
|
43
|
+
|
|
44
|
+
If session_id is None, a new session is created with an auto-generated ID.
|
|
45
|
+
If session_id is provided, attempts to load existing session or creates new one.
|
|
46
|
+
"""
|
|
47
|
+
if session_id is None:
|
|
48
|
+
session = Session.create()
|
|
49
|
+
else:
|
|
50
|
+
agent = self._active_agents.get(session_id)
|
|
51
|
+
if agent is not None:
|
|
52
|
+
return agent
|
|
53
|
+
session = Session.load(session_id)
|
|
48
54
|
profile = self._model_profile_provider.build_profile(self._llm_clients)
|
|
49
55
|
agent = Agent(session=session, profile=profile, model_name=self._llm_clients.main_model_name)
|
|
50
56
|
|
|
@@ -58,9 +64,9 @@ class AgentManager:
|
|
|
58
64
|
)
|
|
59
65
|
)
|
|
60
66
|
|
|
61
|
-
self._active_agents[
|
|
67
|
+
self._active_agents[session.id] = agent
|
|
62
68
|
log_debug(
|
|
63
|
-
f"Initialized agent for session: {
|
|
69
|
+
f"Initialized agent for session: {session.id}",
|
|
64
70
|
style="cyan",
|
|
65
71
|
debug_type=DebugType.EXECUTION,
|
|
66
72
|
)
|
|
@@ -6,8 +6,7 @@ from klaude_code.config import Config
|
|
|
6
6
|
from klaude_code.core.manager.llm_clients import LLMClients
|
|
7
7
|
from klaude_code.llm.client import LLMClientABC
|
|
8
8
|
from klaude_code.llm.registry import create_llm_client
|
|
9
|
-
from klaude_code.protocol.sub_agent import
|
|
10
|
-
from klaude_code.protocol.tools import SubAgentType
|
|
9
|
+
from klaude_code.protocol.sub_agent import iter_sub_agent_profiles
|
|
11
10
|
from klaude_code.trace import DebugType, log_debug
|
|
12
11
|
|
|
13
12
|
|
|
@@ -15,7 +14,6 @@ def build_llm_clients(
|
|
|
15
14
|
config: Config,
|
|
16
15
|
*,
|
|
17
16
|
model_override: str | None = None,
|
|
18
|
-
enabled_sub_agents: list[SubAgentType] | None = None,
|
|
19
17
|
) -> LLMClients:
|
|
20
18
|
"""Create an ``LLMClients`` bundle driven by application config."""
|
|
21
19
|
|
|
@@ -43,12 +41,11 @@ def build_llm_clients(
|
|
|
43
41
|
main_llm_config=llm_config,
|
|
44
42
|
)
|
|
45
43
|
|
|
46
|
-
for
|
|
47
|
-
model_name = config.subagent_models.get(
|
|
44
|
+
for profile in iter_sub_agent_profiles():
|
|
45
|
+
model_name = config.subagent_models.get(profile.name)
|
|
48
46
|
if not model_name:
|
|
49
47
|
continue
|
|
50
48
|
|
|
51
|
-
profile = get_sub_agent_profile(sub_agent_type)
|
|
52
49
|
if not profile.enabled_for_model(main_model_name):
|
|
53
50
|
continue
|
|
54
51
|
|
|
@@ -56,6 +53,6 @@ def build_llm_clients(
|
|
|
56
53
|
sub_llm_config = config.get_model_config(model_name_for_factory)
|
|
57
54
|
return create_llm_client(sub_llm_config)
|
|
58
55
|
|
|
59
|
-
clients.register_sub_client_factory(
|
|
56
|
+
clients.register_sub_client_factory(profile.name, _factory)
|
|
60
57
|
|
|
61
58
|
return clients
|
klaude_code/core/prompt.py
CHANGED
|
@@ -6,8 +6,8 @@ from pathlib import Path
|
|
|
6
6
|
|
|
7
7
|
COMMAND_DESCRIPTIONS: dict[str, str] = {
|
|
8
8
|
"rg": "ripgrep - fast text search",
|
|
9
|
-
"fd": "
|
|
10
|
-
"tree": "
|
|
9
|
+
"fd": "simple and fast alternative to find",
|
|
10
|
+
"tree": "directory listing as a tree",
|
|
11
11
|
"sg": "ast-grep - AST-aware code search",
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ COMMAND_DESCRIPTIONS: dict[str, str] = {
|
|
|
15
15
|
PROMPT_FILES: dict[str, str] = {
|
|
16
16
|
"main_gpt_5_1": "prompts/prompt-codex-gpt-5-1.md",
|
|
17
17
|
"main_gpt_5_1_codex_max": "prompts/prompt-codex-gpt-5-1-codex-max.md",
|
|
18
|
-
"
|
|
18
|
+
"main": "prompts/prompt-claude-code.md",
|
|
19
19
|
"main_gemini": "prompts/prompt-gemini.md", # https://ai.google.dev/gemini-api/docs/prompting-strategies?hl=zh-cn#agentic-si-template
|
|
20
20
|
# Sub-agent prompts keyed by their name
|
|
21
21
|
"Task": "prompts/prompt-subagent.md",
|
|
@@ -49,7 +49,7 @@ def _get_file_key(model_name: str, sub_agent_type: str | None) -> str:
|
|
|
49
49
|
case name if "gemini" in name:
|
|
50
50
|
return "main_gemini"
|
|
51
51
|
case _:
|
|
52
|
-
return "
|
|
52
|
+
return "main"
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
def _build_env_info(model_name: str) -> str:
|
|
@@ -84,15 +84,4 @@ assistant: [Uses the Explore tool to find the files that handle client errors in
|
|
|
84
84
|
<example>
|
|
85
85
|
user: What is the codebase structure?
|
|
86
86
|
assistant: [Uses the Explore tool]
|
|
87
|
-
</example>
|
|
88
|
-
|
|
89
|
-
## Memory
|
|
90
|
-
MEMORY PROTOCOL:
|
|
91
|
-
1. Use the `view` command of your `Memory` tool to check for earlier progress.
|
|
92
|
-
2. ... (work on the task) ...
|
|
93
|
-
- As you make progress, record status / progress / thoughts etc in your memory.
|
|
94
|
-
ASSUME INTERRUPTION: Your context window might be reset at any moment, so you risk losing any progress that is not recorded in your memory directory.
|
|
95
|
-
|
|
96
|
-
Note: when editing your memory folder, always try to keep its content up-to-date, coherent and organized. You can rename or delete files that are no longer relevant. Do not create new files unless necessary.
|
|
97
|
-
|
|
98
|
-
Only write down information relevant to current project in your memory system.
|
|
87
|
+
</example>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
You are an interactive CLI tool. Use the tools available to you to assist the user.
|
|
2
|
+
|
|
3
|
+
## Guidelines
|
|
4
|
+
- Never use emojis.
|
|
5
|
+
- Your output will be displayed on a command line interface. Your responses should be short and concise.
|
|
6
|
+
- Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like Bash or code comments as means to communicate with the user during the session.
|
|
7
|
+
- NEVER create Markdown files unless they're absolutely necessary for achieving your goal.
|
|
8
|
+
- Use TodoWrite tool to help you manage and plan tasks.
|
|
9
|
+
- For maximum efficiency, whenever you need to perform multiple independent operations, invoke all relevant tools simultaneously rather than sequentially.
|
|
10
|
+
|
|
11
|
+
## Professional objectivity
|
|
12
|
+
Prioritize technical accuracy and truthfulness over validating the user's beliefs. Focus on facts and problem-solving, providing direct, objective technical info without any unnecessary superlatives, praise, or emotional validation. It is best for the user if you honestly applies the same rigorous standards to all ideas and disagrees when necessary, even if it may not be what the user wants to hear. Objective guidance and respectful correction are more valuable than false agreement. Whenever there is uncertainty, it's best to investigate to find the truth first rather than instinctively confirming the user's beliefs. Avoid using over-the-top validation or excessive praise when responding to users such as "You're absolutely right" or similar phrases.
|
klaude_code/core/task.py
CHANGED
|
@@ -29,9 +29,11 @@ class MetadataAccumulator:
|
|
|
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
|
|
32
|
+
self._turn_count: int = 0
|
|
32
33
|
|
|
33
34
|
def add(self, turn_metadata: model.ResponseMetadataItem) -> None:
|
|
34
35
|
"""Merge a turn's metadata into the accumulated state."""
|
|
36
|
+
self._turn_count += 1
|
|
35
37
|
main = self._main
|
|
36
38
|
usage = turn_metadata.usage
|
|
37
39
|
|
|
@@ -43,6 +45,7 @@ class MetadataAccumulator:
|
|
|
43
45
|
acc_usage.cached_tokens += usage.cached_tokens
|
|
44
46
|
acc_usage.reasoning_tokens += usage.reasoning_tokens
|
|
45
47
|
acc_usage.output_tokens += usage.output_tokens
|
|
48
|
+
acc_usage.last_turn_output_token = usage.output_tokens
|
|
46
49
|
acc_usage.currency = usage.currency
|
|
47
50
|
|
|
48
51
|
if usage.context_token is not None:
|
|
@@ -91,6 +94,7 @@ class MetadataAccumulator:
|
|
|
91
94
|
main.usage.throughput_tps = None
|
|
92
95
|
|
|
93
96
|
main.task_duration_s = task_duration_s
|
|
97
|
+
main.turn_count = self._turn_count
|
|
94
98
|
return model.TaskMetadataItem(main=main, sub_agent_task_metadata=self._sub_agent_metadata)
|
|
95
99
|
|
|
96
100
|
|
|
@@ -14,3 +14,7 @@ Usage tips:
|
|
|
14
14
|
- Check your memory directory before starting tasks to recall previous context
|
|
15
15
|
- Record important decisions, progress, and learnings as you work
|
|
16
16
|
- Keep memory files organized and up-to-date; delete obsolete files
|
|
17
|
+
|
|
18
|
+
Note: when editing your memory folder, always try to keep its content up-to-date, coherent and organized. You can rename or delete files that are no longer relevant. Do not create new files unless necessary.
|
|
19
|
+
|
|
20
|
+
Only write down information relevant to current project in your memory system.
|
|
@@ -39,7 +39,7 @@ class SkillLoader:
|
|
|
39
39
|
USER_SKILLS_DIRS = [
|
|
40
40
|
Path("~/.claude/skills"),
|
|
41
41
|
Path("~/.klaude/skills"),
|
|
42
|
-
Path("~/.claude/plugins/marketplaces"),
|
|
42
|
+
# Path("~/.claude/plugins/marketplaces"),
|
|
43
43
|
]
|
|
44
44
|
# Project-level skills directory
|
|
45
45
|
PROJECT_SKILLS_DIR = Path("./.claude/skills")
|
|
@@ -22,161 +22,4 @@ Skip using this tool when:
|
|
|
22
22
|
|
|
23
23
|
NOTE that you should not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly.
|
|
24
24
|
|
|
25
|
-
#### Examples of When to Use the Todo List
|
|
26
|
-
|
|
27
|
-
<example>
|
|
28
|
-
User: I want to add a dark mode toggle to the application settings. Make sure you run the tests and build when you're done!
|
|
29
|
-
Assistant: I'll help add a dark mode toggle to your application settings. Let me create a todo list to track this implementation.
|
|
30
|
-
*Creates todo list with the following items:*
|
|
31
|
-
1. Creating dark mode toggle component in Settings page
|
|
32
|
-
2. Adding dark mode state management (context/store)
|
|
33
|
-
3. Implementing CSS-in-JS styles for dark theme
|
|
34
|
-
4. Updating existing components to support theme switching
|
|
35
|
-
5. Running tests and build process, addressing any failures or errors that occur
|
|
36
|
-
*Begins working on the first task*
|
|
37
|
-
|
|
38
|
-
<reasoning>
|
|
39
|
-
The assistant used the todo list because:
|
|
40
|
-
1. Adding dark mode is a multi-step feature requiring UI, state management, and styling changes
|
|
41
|
-
2. The user explicitly requested tests and build be run afterward
|
|
42
|
-
3. The assistant inferred that tests and build need to pass by adding "Ensure tests and build succeed" as the final task
|
|
43
|
-
</reasoning>
|
|
44
|
-
</example>
|
|
45
|
-
|
|
46
|
-
<example>
|
|
47
|
-
User: Help me rename the function getCwd to getCurrentWorkingDirectory across my project
|
|
48
|
-
Assistant: Let me first search through your codebase to find all occurrences of 'getCwd'.
|
|
49
|
-
*Uses grep or search tools to locate all instances of getCwd in the codebase*
|
|
50
|
-
Assistant: I've found 15 instances of 'getCwd' across 8 different files. Let me create a todo list to track these changes.
|
|
51
|
-
*Creates todo list with specific items for each file that needs updating*
|
|
52
|
-
|
|
53
|
-
<reasoning>
|
|
54
|
-
The assistant used the todo list because:
|
|
55
|
-
1. First, the assistant searched to understand the scope of the task
|
|
56
|
-
2. Upon finding multiple occurrences across different files, it determined this was a complex task with multiple steps
|
|
57
|
-
3. The todo list helps ensure every instance is tracked and updated systematically
|
|
58
|
-
4. This approach prevents missing any occurrences and maintains code consistency
|
|
59
|
-
</reasoning>
|
|
60
|
-
</example>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<example>
|
|
64
|
-
User: I need to implement these features for my e-commerce site: user registration, product catalog, shopping cart, and checkout flow.
|
|
65
|
-
Assistant: I'll help implement these features. First, let's add all the features to the todo list.
|
|
66
|
-
*Creates a todo list breaking down each feature into specific tasks based on the project architecture*
|
|
67
|
-
Assistant: Let's start with user registration. This will involve creating database models, API endpoints, and frontend forms that integrate with your existing authentication system.
|
|
68
|
-
|
|
69
|
-
<reasoning>
|
|
70
|
-
The assistant used the todo list because:
|
|
71
|
-
1. The user provided multiple complex features to implement in a comma separated list
|
|
72
|
-
2. The todo list helps organize these large features into manageable tasks
|
|
73
|
-
3. This approach allows for tracking progress across the entire implementation
|
|
74
|
-
</reasoning>
|
|
75
|
-
</example>
|
|
76
|
-
|
|
77
|
-
<example>
|
|
78
|
-
User: Can you help optimize my React application? It's rendering slowly and has performance issues.</user>
|
|
79
|
-
Assistant: I'll help optimize your React application. First, let me examine your codebase to identify potential performance bottlenecks.
|
|
80
|
-
*Reviews component structure, render patterns, state management, and data fetching*
|
|
81
|
-
Assistant: After analyzing your codebase, I've identified several performance issues. Let me create a todo list to track our optimization efforts.
|
|
82
|
-
*Creates todo list with items like: 1) Implementing memoization for expensive calculations in ProductList, 2) Adding virtualization for long lists in Dashboard, 3) Optimizing image loading in Gallery component, 4) Fixing state update loops in ShoppingCart, 5) Reviewing bundle size and implementing code splitting*
|
|
83
|
-
Let's start by implementing memoization for the expensive calculations in your ProductList component.</assistant>
|
|
84
|
-
|
|
85
|
-
<reasoning>
|
|
86
|
-
The assistant used the todo list because:
|
|
87
|
-
1. First, the assistant examined the codebase to identify specific performance issues
|
|
88
|
-
2. Based on this analysis, it identified multiple optimization opportunities
|
|
89
|
-
3. Performance optimization is a non-trivial task requiring multiple steps
|
|
90
|
-
4. The todo list helps methodically track improvements across different components
|
|
91
|
-
5. This systematic approach ensures all performance bottlenecks are addressed
|
|
92
|
-
</reasoning>
|
|
93
|
-
</example>
|
|
94
|
-
|
|
95
|
-
#### Examples of When NOT to Use the Todo List
|
|
96
|
-
|
|
97
|
-
<example>
|
|
98
|
-
User: How do I print 'Hello World' in Python?
|
|
99
|
-
Assistant: In Python, you can print "Hello World" with this simple code:
|
|
100
|
-
|
|
101
|
-
python
|
|
102
|
-
print("Hello World")
|
|
103
|
-
|
|
104
|
-
This will output the text "Hello World" to the console when executed.</assistant>
|
|
105
|
-
|
|
106
|
-
<reasoning>
|
|
107
|
-
The assistant did not use the todo list because this is a single, trivial task that can be completed in one step. There's no need to track multiple tasks or steps for such a straightforward request.
|
|
108
|
-
</reasoning>
|
|
109
|
-
</example>
|
|
110
|
-
|
|
111
|
-
<example>
|
|
112
|
-
User: What does the git status command do?
|
|
113
|
-
Assistant: The git status command shows the current state of your working directory and staging area. It displays which changes have been staged, which haven't, and which files aren't being tracked by Git. This is a fundamental command for understanding the current state of your repository before making commits.
|
|
114
|
-
|
|
115
|
-
<reasoning>
|
|
116
|
-
The assistant did not use the todo list because this is an informational request with no actual coding task to complete. The user is simply asking for an explanation, not for the assistant to perform multiple steps or tasks.
|
|
117
|
-
</reasoning>
|
|
118
|
-
</example>
|
|
119
|
-
|
|
120
|
-
<example>
|
|
121
|
-
User: Can you add a comment to the calculateTotal function to explain what it does?
|
|
122
|
-
Assistant: Sure, let me add a comment to the calculateTotal function to explain what it does.
|
|
123
|
-
* Uses the Edit tool to add a comment to the calculateTotal function *
|
|
124
|
-
|
|
125
|
-
<reasoning>
|
|
126
|
-
The assistant did not use the todo list because this is a single, straightforward task confined to one location in the code. Adding a comment doesn't require tracking multiple steps or systematic organization.
|
|
127
|
-
</reasoning>
|
|
128
|
-
</example>
|
|
129
|
-
|
|
130
|
-
<example>
|
|
131
|
-
User: Run npm install for me and tell me what happens.
|
|
132
|
-
Assistant: I'll run the npm install command for you.
|
|
133
|
-
|
|
134
|
-
*Executes: npm install*
|
|
135
|
-
|
|
136
|
-
The command completed successfully. Here's the output:
|
|
137
|
-
[Output of npm install command]
|
|
138
|
-
|
|
139
|
-
All dependencies have been installed according to your package.json file.
|
|
140
|
-
|
|
141
|
-
<reasoning>
|
|
142
|
-
The assistant did not use the todo list because this is a single command execution with immediate results. There are no multiple steps to track or organize, making the todo list unnecessary for this straightforward task.
|
|
143
|
-
</reasoning>
|
|
144
|
-
</example>
|
|
145
|
-
|
|
146
|
-
#### Task States and Management
|
|
147
|
-
|
|
148
|
-
1. **Task States**: Use these states to track progress:
|
|
149
|
-
- pending: Task not yet started
|
|
150
|
-
- in_progress: Currently working on (limit to ONE task at a time)
|
|
151
|
-
- completed: Task finished successfully
|
|
152
|
-
|
|
153
|
-
**IMPORTANT**: Task descriptions must have two forms:
|
|
154
|
-
- content: The imperative form describing what needs to be done (e.g., "Run tests", "Build the project")
|
|
155
|
-
- activeForm: The present continuous form shown during execution (e.g., "Running tests", "Building the project")
|
|
156
|
-
|
|
157
|
-
2. **Task Management**:
|
|
158
|
-
- Update task status in real-time as you work
|
|
159
|
-
- Mark tasks complete IMMEDIATELY after finishing (don't batch completions)
|
|
160
|
-
- Exactly ONE task must be in_progress at any time (not less, not more)
|
|
161
|
-
- Complete current tasks before starting new ones
|
|
162
|
-
- Remove tasks that are no longer relevant from the list entirely
|
|
163
|
-
|
|
164
|
-
3. **Task Completion Requirements**:
|
|
165
|
-
- ONLY mark a task as completed when you have FULLY accomplished it
|
|
166
|
-
- If you encounter errors, blockers, or cannot finish, keep the task as in_progress
|
|
167
|
-
- When blocked, create a new task describing what needs to be resolved
|
|
168
|
-
- Never mark a task as completed if:
|
|
169
|
-
- Tests are failing
|
|
170
|
-
- Implementation is partial
|
|
171
|
-
- You encountered unresolved errors
|
|
172
|
-
- You couldn't find necessary files or dependencies
|
|
173
|
-
|
|
174
|
-
4. **Task Breakdown**:
|
|
175
|
-
- Create specific, actionable items
|
|
176
|
-
- Break complex tasks into smaller, manageable steps
|
|
177
|
-
- Use clear, descriptive task names
|
|
178
|
-
- Always provide both forms:
|
|
179
|
-
- content: "Fix authentication bug"
|
|
180
|
-
- activeForm: "Fixing authentication bug"
|
|
181
|
-
|
|
182
25
|
When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully.
|